Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
424 views
in Technique[技术] by (71.8m points)

url - C++ URLDownloadToFile to executable directory in CLR forum

I'm trying to figure out how I can fix two issues that I've been having with the URLDownloadToFile function in C++. The first is that when attempting to download the file in question, the download doesn't actually appear until the CLR C++ window is closed. The second is that as shown on the image below, the resulting file's file name and extension (Which is above the success window) is messed up (Although opening it normally shows that the file downloaded fine, with the name as the exception). If anyone has any suggestions on what I could do to fix these two issues, I'd greatly appreciate it.

What occurs when I attempt to run this code for downloading the file in question

For this logic, I'm using:

{
    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;
}
question from:https://stackoverflow.com/questions/65924443/c-urldownloadtofile-to-executable-directory-in-clr-forum

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

LPTSTR currentDirectoryLPTSTR = new TCHAR[currentDirectory.size() + 1]; allocates memory, but does not fill it with any data.

std::string(currentDirectoryLPTSTR) creates a new string object and tries to copy data from currentDirectoryLPTSTR into the string. Which is undefined behavior since currentDirectoryLPTSTR is not a proper null-terminated string. This code does not cause the string object to point at the memory allocated for currentDirectoryLPTSTR, like you clearly think it does.

You are then append()ing File to that string object, not to the contents of currentDirectoryLPTSTR.

And then you throw away the string object you just created, and pass the unfilled currentDirectoryLPTSTR as-is to URLDownloadToFile(). Which is why your output file has a messed-up filename (you are lucky it even shows up in the correct folder at all).

Try this instead:

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;
    }
}

On a side note, you really shouldn't be downloading files to the same folder that your program is running from. If your program is installed in a folder like C:Program Files or C:Program Files (x86), somewhere only admins can write to, then the download will be likely to fail. You should be downloading to a folder that the user has write access to, such as to a subfolder you create under %APPDATA% for your program to use.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...