创建StartMenu条目

时间:2017-09-14 20:53:08

标签: c++ winapi unicode path directory

我尝试在StartMenu文件夹中创建指向文件的链接,我的代码为:

bool createStartMenuEntry(string targetPath, string name){
    std::wstring stemp = s2ws(targetPath);
    LPCWSTR target = stemp.c_str();

    WCHAR startMenuPath[MAX_PATH];
    HRESULT result = SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, startMenuPath);

    if (SUCCEEDED(result)) {
        std::wstring linkPath = std::wstring(startMenuPath) + s2ws(name);
        LPCWSTR link = linkPath.c_str();

        //TEST MESSAGE!!!
        MessageBox(NULL, LPCSTR(target), LPCSTR(link), MB_ICONWARNING);

        CoInitialize(NULL);
        IShellLinkW* shellLink = NULL;
        result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink);
        if (SUCCEEDED(result)) {
            shellLink->SetPath(target);
            //shellLink->SetDescription(L"Shortcut Description");
            shellLink->SetIconLocation(target, 0);
            IPersistFile* persistFile;
            result = shellLink->QueryInterface(IID_IPersistFile, (void**)&persistFile);

            if (SUCCEEDED(result)) {
                result = persistFile->Save(link, TRUE);

                persistFile->Release();
            }
            else {
                return false;
            }
            shellLink->Release();
        }
        else {
            return false;
        }
    }
    else {
        return false;
    }
    return true;
}

字符串到宽字符串转换:

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

当我像createStartMenuEntry("E:\\file.exe" , "File")那样调用我的func时,在测试消息中我只有第一个路径字母而快捷方式未创建,我认为是unicode转换中的问题。

1 个答案:

答案 0 :(得分:2)

这里有很多问题:

  • MessageBox(NULL, LPCSTR(target), LPCSTR(link), MB_ICONWARNING);是各种错误的。你不应该像这样投射字符串。如果您在未定义UNICODE的情况下进行编译,则必须使用MessageBoxW()来显示LPCWSTR字符串。您得到一个字符,因为"c:\\"作为Unicode字符串在内存中是'c',0,':',0,'\\',0,0,0,并且当被视为窄ANSI字符串时,它与"c"字符串相同。
  • 您忽略了persistFile->Save()的结果!您还会忽略SetPath()SetIconLocation()
  • 的结果
  • 普通用户无法写入CSIDL_COMMON_PROGRAMS,只有管理员具有该文件夹的写入权限,因为它由所有用户共享。如果您不打算要求UAC提升,则必须改为CSIDL_PROGRAMS
  • 您不应使用std::string来存储路径,只能使用std::wstringWCHAR* / LP[C]WSTR,因为包含某些Unicode字符的路径无法用窄的ANSI字符串表示