问题描述
我想弄清楚如何解决我在 C++ 中使用 URLDownloadToFile 函数遇到的两个问题。第一个是当尝试下载有问题的文件时,在 CLR C++ 窗口关闭之前下载实际上不会出现。二是如下图所示,结果文件的文件名和扩展名(在成功窗口上方)乱七八糟(虽然正常打开显示文件下载正常,但名称除外)。如果有人对我如何解决这两个问题有任何建议,我将不胜感激。
对于这个逻辑,我使用:
{
char buffer[MAX_PATH];
GetmodulefileNameA(NULL,buffer,MAX_PATH);
std::string::size_type pos = std::string(buffer).find_last_of("\\/");
return std::string(buffer).substr(0,pos);
}
void StartDownload()
{
HRESULT downloadUpdate;
LPCTSTR downloadUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png",File = "download.png";
string currentDirectory = GetCurrentDirectory();
LPTSTR currentDirectoryLPTSTR = new TCHAR[currentDirectory.size() + 1];
std::string(currentDirectoryLPTSTR).append(File).c_str();
downloadUpdate = URLDownloadToFile(0,downloadUrl,currentDirectoryLPTSTR,0);
switch (downloadUpdate)
{
case S_OK:
updateSuccess();
break;
case E_OUTOFMEMORY:
updateOOMError();
break;
case INET_E_DOWNLOAD_FAILURE:
updateError();
break;
default:
updateErrorUnkNown();
break;
}
}
[STAThread]
int main() {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew UpdaterGUIProject::UpdaterGUI());
StartDownload();
return 0;
}
解决方法
LPTSTR currentDirectoryLPTSTR = new TCHAR[currentDirectory.size() + 1];
分配内存,但不填充任何数据。
std::string(currentDirectoryLPTSTR)
创建一个新的 string
对象并尝试将数据从 currentDirectoryLPTSTR
复制到 string
。这是未定义行为,因为 currentDirectoryLPTSTR
不是正确的以空字符结尾的字符串。此代码不会使 string
对象指向为 currentDirectoryLPTSTR
分配的内存,就像您显然认为的那样。
然后,您将 append()
File
指向该 string
对象,而不是 currentDirectoryLPTSTR
的内容。
然后您丢弃刚刚创建的 string
对象,并将未填充的 currentDirectoryLPTSTR
原样传递给 URLDownloadToFile()
。这就是为什么您的输出文件有一个混乱的文件名(您很幸运它甚至显示在正确的文件夹中)。
试试这个:
std::string GetCurrentDirectory()
{
char buffer[MAX_PATH] = {};
DWORD size = GetModuleFileNameA(NULL,buffer,MAX_PATH);
if (size == 0 || size == MAX_PATH) return "";
std::string fileName(buffer,size);
std::string::size_type pos = fileName.find_last_of("\\/");
return fileName.substr(0,pos + 1);
}
void StartDownload()
{
HRESULT downloadUpdate;
LPCSTR downloadUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png",File = "download.png";
string localFile = GetCurrentDirectory() + File;
downloadUpdate = URLDownloadToFileA(0,downloadUrl,localFile.c_str(),0);
switch (downloadUpdate)
{
case S_OK:
updateSuccess();
break;
case E_OUTOFMEMORY:
updateOOMError();
break;
case INET_E_DOWNLOAD_FAILURE:
updateError();
break;
default:
updateErrorUnknown();
break;
}
}
顺便提一下,您真的不应该将文件下载到运行程序的同一文件夹中。如果您的程序安装在 C:\Program Files
或 C:\Program Files (x86)
之类的文件夹中,只有管理员可以写入的某个地方,那么下载可能会失败。您应该下载到用户具有写入权限的文件夹,例如您在 %APPDATA%
下创建的子文件夹,供您的程序使用。