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 FilesC:\Program Files (x86) 这样的文件夹中,只有管理员可以写入,那么下载很可能会失败。您应该下载到用户具有写入权限的文件夹,例如您在 %APPDATA% 下创建的子文件夹供您的程序使用。