InternetOpen
Пишу вот так:
HINTERNET hConnect = NULL;
hSession = InternetOpen("FTP", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
вылетает ошибка:
[Linker Error] Unresolved external 'InternetOpenA' referenced from UNIT1.OBJ
что это такое?
Все необходимые объявления сделаны?
Чехарды с Unicode и однобайтовыми строками в проекте нет?
Библиотеки к проекту подключены?
Все необходимые объявления сделаны?
Чехарды с Unicode и однобайтовыми строками в проекте нет?
что конкретно нужно подключить?
что конкретно нужно подключить?
Ну, например, direct50.bpl, или там inet.lib, или ещё что-нибудь.
Т.е. если линкер пишет "Unresolved external", значит в объектных модулях, которые он пытается скомпоновать, такой функции не находится. Значит, или модуля подходящего нет, или функция объявлена, но не определена, или объявлена с одним именем, а определена с другим.
В Win32 API функции с буквой A в конце являются ANSI-версиями, а с буквой W - Unicode-версиями одной и той же функции. Например, та же InternetOpen в заголовочном файле wininet.h объявлена так:
HINTERNET
WINAPI
InternetOpenA(
IN LPCSTR lpszAgent,
IN DWORD dwAccessType,
IN LPCSTR lpszProxy OPTIONAL,
IN LPCSTR lpszProxyBypass OPTIONAL,
IN DWORD dwFlags
);
INTERNETAPI
HINTERNET
WINAPI
InternetOpenW(
IN LPCWSTR lpszAgent,
IN DWORD dwAccessType,
IN LPCWSTR lpszProxy OPTIONAL,
IN LPCWSTR lpszProxyBypass OPTIONAL,
IN DWORD dwFlags
);
#ifdef UNICODE
#define InternetOpen InternetOpenW
#else
#define InternetOpen InternetOpenA
#endif // !UNICODE
Поэтому есть смысл проверить, нет ли в программе чехарды с Unicode.
что конкретно нужно подключить?
Если собираешься использовать функции WinInet, в проект обязательно должна быть подключена либа wininet.lib - или же подключай wininet.dll динамически. Тогда еесественно необходимо объявить указатели на загружаемые функции.
вот что делаю:
if (dllWinInet == NULL)
{
return;
}
FTPOpen = (InternetOpenA *)GetProcAddress(dllWinInet, "InternetOpenA");
FTPConnect = (InternetConnectA * )GetProcAddress(dllWinInet, "InternetConnectA");
в хидере:
// InternetOpen
typedef HINTERNET (__import * InternetOpenA
(
LPCSTR lpszAgent,
DWORD dwAccessType,
LPCSTR lpszProxy OPTIONAL,
LPCSTR lpszProxyBypass OPTIONAL,
DWORD dwFlags
));
InternetOpenA * FTPOpen;
// InternetConnect
typedef HINTERNET (__import * InternetConnectA
(
IN HINTERNET hInternet,
IN LPCSTR lpszServerName,
IN INTERNET_PORT nServerPort,
IN LPCSTR lpszUserName OPTIONAL,
IN LPCSTR lpszPassword OPTIONAL,
IN DWORD dwService,
IN DWORD dwFlags,
IN DWORD_PTR dwContext
));
InternetConnectA * FTPConnect;
в обработчике кнопки:
HINTERNET hConnect = NULL;
hSession = FTPOpen
(
"FTP",
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
0
);
hConnect = FTPConnect
(
hSession,
"ftp.anywhere.corp",
INTERNET_DEFAULT_FTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_FTP,
NULL,
NULL
);
и вот на FTPConnect ошибка вылетает:
Access violation at 0x00401c23: read of address 0x000002fc
hSession перед вызовом действителен? Проверки то в коде нет.
теперь заработало, в смысле ошибки нет, хотя не знаю, что конкретно я исправил :)
но вот теперь не коннектиться к ftp, пишет:
FTPConnect failed with error 6: Неверный дескриптор
добавил из MSDN обработку ошибок:
{
TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
wsprintf(szBuf,
"%s failed with error %d: %s",
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, szBuf, "Error", MB_OK);
LocalFree(lpMsgBuf);
ExitProcess(dw);
}
вот такой теперя обработчик кнопки:
HINTERNET hConnect = NULL;
hSession = FTPOpen
(
"FTP",
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
0
);
if (hSession)
ShowMessage("OK");
hConnect = FTPConnect
(
hSession,
"ftp.anywhere.corp",
INTERNET_DEFAULT_FTP_PORT,
NULL,
NULL,
INTERNET_SERVICE_FTP,
NULL,
NULL
);
ErrorExit("FTPConnect");
Сдаётся мне, что неверно импортируются эти две функции.
Вот пример работающего кода(прошу прощения за длинный листинг,старался максимально его сократить, если не поможет могу кинуть файлом):
LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD_PTR);
typedef HINTERNET (__stdcall *pInternetOpen)(LPCTSTR,DWORD,LPCTSTR,LPCTSTR,DWORD);
typedef HINTERNET (__stdcall *pFtpFindFirstFile)(HINTERNET,LPCTSTR,
LPWIN32_FIND_DATA,DWORD,DWORD_PTR);
typedef BOOL (__stdcall *pInternetNextFile) (HINTERNET,LPVOID);
typedef BOOL (__stdcall *pFtpPutFile)(HINTERNET,LPCTSTR,LPCTSTR,DWORD,DWORD_PTR);
typedef BOOL (__stdcall *pFtpGetFile)(HINTERNET,LPCTSTR,LPCTSTR,
BOOL,DWORD,DWORD,DWORD_PTR);
typedef BOOL (__stdcall *pFtpDeleteFile)(HINTERNET,LPCTSTR);
typedef BOOL (__stdcall *pFtpGetCurrentDirectory)(HINTERNET,LPCTSTR,LPDWORD);
typedef BOOL (__stdcall *pFtpSetCurrentDirectory)(HINTERNET,LPCTSTR);
typedef BOOL (__stdcall *pInternetCloseHandle)(HINTERNET);
...
pInternetConnect fInternetConnect;
pInternetOpen fInternetOpen;
pFtpFindFirstFile fFtpFindFirstFile;
pInternetNextFile fInternetNextFile;
pFtpPutFile fFtpPutFile;
pFtpGetFile fFtpGetFile;
pFtpDeleteFile fFtpDeleteFile;
pFtpGetCurrentDirectory fFtpGetCurrentDirectory;
pFtpSetCurrentDirectory fFtpSetCurrentDirectory;
pInternetCloseHandle fInternetCloseHandle;
pInternetSetStatusCallback fInternetSetStatusCallback;
pRasGetErrorString fRasGetErrorString;
pRasDial fRasDial;
pRasEnumConnections fRasEnumConnections;
pRasGetConnectStatus fRasGetConnectStatus;
pRasEnumEntries fRasEnumEntries;
pRasGetEntryDialParams fRasGetEntryDialParams;
pRasHangUp fRasHangUp;
HINSTANCE hRasInstance,hInetInstance;
DWORD dwStatusCurrent;
...
void __fastcall TfmMainFtp::FormCreate(TObject *Sender)
{
First = 0;
MutexFirst = CreateMutex(NULL,true,"MyMutex");
int Res = GetLastError();
if(Res==ERROR_ALREADY_EXISTS){
First = 1;
Close();
}
hRas = 0;
hRasInstance = LoadLibrary("RASAPI32.DLL");
if (!hRasInstance) {
LogEvents("Unable to load RAS DLL.");
Close();
return;
}
fRasGetErrorString = (pRasGetErrorString)
GetProcAddress(hRasInstance, "RasGetErrorStringA");
fRasDial = (pRasDial)
GetProcAddress(hRasInstance, "RasDialA");
fRasEnumConnections = (pRasEnumConnections)
GetProcAddress(hRasInstance, "RasEnumConnectionsA");
fRasGetConnectStatus = (pRasGetConnectStatus)
GetProcAddress(hRasInstance, "RasGetConnectStatusA");
fRasEnumEntries = (pRasEnumEntries)
GetProcAddress(hRasInstance, "RasEnumEntriesA");
fRasGetEntryDialParams = (pRasGetEntryDialParams)GetProcAddress(hRasInstance, "RasGetEntryDialParamsA");
fRasHangUp = (pRasHangUp)
GetProcAddress(hRasInstance, "RasHangUpA");
if (!fRasGetErrorString || !fRasDial || !fRasEnumConnections ||
!fRasGetConnectStatus || !fRasEnumEntries || !fRasHangUp) {
LogEvents("Ошибка загрузки функций дозвона");
Close();
return;
}
hInetInstance = LoadLibrary("WININET.DLL");
if(!hInetInstance){
LogEvents("Unable to load WININET DLL.");
Close();
return;
}
fInternetConnect = (pInternetConnect)GetProcAddress(hInetInstance,"InternetConnectA");
fInternetOpen = (pInternetOpen)GetProcAddress(hInetInstance,"InternetOpenA");
fFtpFindFirstFile =(pFtpFindFirstFile)GetProcAddress(hInetInstance,"FtpFindFirstFileA");
fInternetNextFile =(pInternetNextFile)GetProcAddress(hInetInstance,"InternetFindNextFileA");
fFtpPutFile =(pFtpPutFile)GetProcAddress(hInetInstance,"FtpPutFileA");
fFtpGetFile=(pFtpGetFile)GetProcAddress(hInetInstance,"FtpGetFileA");
fFtpDeleteFile=(pFtpDeleteFile)GetProcAddress(hInetInstance,"FtpDeleteFileA");
fFtpGetCurrentDirectory=(pFtpGetCurrentDirectory)GetProcAddress(hInetInstance,"FtpGetCurrentDirectoryA");
fFtpSetCurrentDirectory=(pFtpSetCurrentDirectory)GetProcAddress(hInetInstance,"FtpSetCurrentDirectoryA");
fInternetCloseHandle=(pInternetCloseHandle)GetProcAddress(hInetInstance,"InternetCloseHandle");
fInternetSetStatusCallback = (pInternetSetStatusCallback)GetProcAddress(hInetInstance,"InternetSetStatusCallback");
if(!fInternetConnect||!fInternetOpen
||!fFtpFindFirstFile||!fInternetNextFile
||!fFtpPutFile||!fFtpGetFile||!fFtpDeleteFile
||!fFtpGetCurrentDirectory||!fFtpSetCurrentDirectory
||!fInternetCloseHandle||!fInternetSetStatusCallback){
LogEvents("Ошибка загрузки функций интернет");
Close();
return;
}
}
...
//тут куча разных функций, не важно
///
hInetOpen = fInternetOpen("Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914) ",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
if(!hInetOpen)LogEvents("Хедер инициализирован");
hInetConnection = fInternetConnect(hInetOpen,Host.c_str(),INTERNET_DEFAULT_FTP_PORT,UserName.c_str(),Pass.c_str(),INTERNET_SERVICE_FTP,0,0);
if(hInetConnection==NULL){
LogEvents("Невозможно установить соединение");
fInternetCloseHandle(hInetConnection);
fInternetCloseHandle(hInetOpen);
Close();
/* TODO : Проверка наличия соединения */
}
//Тут собственно отправка
if(FilesForSend){
String FileRem = lvList->Items->Item[FilesForSend-1]->Caption;
String File = DirOutLocal+"\\"+FileRem;
if(!fFtpPutFile(hInetConnection,File.c_str(),FileRem.c_str(),FTP_TRANSFER_TYPE_BINARY,0)){
LogEvents("Не отправлен файл "+FileRem);
return false;
}
DeleteFile(File);
LogEvents("Отправлен файл "+FileRem);
LogEvents("Удален файл\t"+FileRem);
lvList->Items->Delete(FilesForSend-1);
Application->ProcessMessages();
PostMessage(FormParent,MYWM_SEND,0,0);
FilesForSend--;
}
return FilesForSend;