c++windowsshortcutstartmenu

C++: How do I create a Shortcut in the Start Menu on Windows


I would like to know how to obtain the path to the start menu folder on Windows and then create a shortcut to a path that might contain non-ASCII characters.


Solution

  • Here is the solution. It uses Qt but it's also possible without. Then just use std::wstring instead of QString. For concatenating the paths and filenames you will then have to use string operations instead of using QDir.

    #include <shlobj.h> 
    
    bool createStartMenuEntry(QString targetPath) {
        targetPath = QDir::toNativeSeparators(targetPath);
    
        WCHAR startMenuPath[MAX_PATH];
        HRESULT result = SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, startMenuPath);
    
        if (SUCCEEDED(result)) {
            QString linkPath = QDir(QString::fromWCharArray(startMenuPath)).absoluteFilePath("Shortcut Name.lnk");
    
            CoInitialize(NULL);
            IShellLinkW* shellLink = NULL;
            result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink);
            if (SUCCEEDED(result)) {
                shellLink->SetPath(targetPath.toStdWString().c_str());
                shellLink->SetDescription(L"Shortcut Description");
                shellLink->SetIconLocation(targetPath.toStdWString().c_str(), 0);
                IPersistFile* persistFile;
                result = shellLink->QueryInterface(IID_IPersistFile, (void**)&persistFile);
    
                if (SUCCEEDED(result)) {
                    result = persistFile->Save(linkPath.toStdWString().c_str(), TRUE);
    
                    persistFile->Release();
                } else {
                    return false;
                }
                shellLink->Release();
            } else {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }
    

    Thats the part that obtains the location of the start-menu folder:

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

    The rest is then creation of the shortcut. Exchange shortcut name and description for your desired values.