C++ URLDownloadToFile 到 CLR 论坛中的可执行目录
C++ URLDownloadToFile to executable directory in CLR forum
我想弄清楚如何解决我在使用 C++ 中的 URLDownloadToFile 函数时遇到的两个问题。第一个是当尝试下载有问题的文件时,直到 CLR C++ window 关闭,下载才真正出现。二是如下图,生成的文件的文件名和扩展名(上面是成功的window)乱七八糟的(虽然正常打开显示文件下载正常,名字为例外)。如果有人对我如何解决这两个问题有任何建议,我将不胜感激。
对于这个逻辑,我使用:
{
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, 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
不是正确的以 null 结尾的字符串。此代码不会导致 string
对象指向为 currentDirectoryLPTSTR
分配的内存,就像您清楚地认为的那样。
然后您 append()
ing 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, 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%
下创建的子文件夹供您的程序使用。
我想弄清楚如何解决我在使用 C++ 中的 URLDownloadToFile 函数时遇到的两个问题。第一个是当尝试下载有问题的文件时,直到 CLR C++ window 关闭,下载才真正出现。二是如下图,生成的文件的文件名和扩展名(上面是成功的window)乱七八糟的(虽然正常打开显示文件下载正常,名字为例外)。如果有人对我如何解决这两个问题有任何建议,我将不胜感激。
对于这个逻辑,我使用:
{
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, 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
不是正确的以 null 结尾的字符串。此代码不会导致 string
对象指向为 currentDirectoryLPTSTR
分配的内存,就像您清楚地认为的那样。
然后您 append()
ing 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, 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%
下创建的子文件夹供您的程序使用。