IPersistFile :: Save方法无法保存快捷方式

时间:2013-09-01 01:40:01

标签: c++ shortcut

我正在尝试在启动文件夹中保存应用程序的快捷方式。这一切都编译,但它实际上无法保存游戏。该错误似乎发生在hres = ppf->Save(wsz, TRUE);,其中hres设置为-2147024891。如果这意味着具体的东西,我还没有发现什么。我的代码几乎是从MSDN中逐字复制的,所以我很困惑为什么它不起作用。也许我没有权限保存启动文件夹的快捷方式?然后,我对这一切也相当新,所以这可能是我正在做的一些基本错误。我正在复制我所有的#includes,以防出现问题。

编辑:
首先,为了避免混淆,这是基于CLI的C ++。

检查hres是否存在错误只是MDSN代码的一部分。这几乎与网站示例中的代码完全相同。我已经输入了断点,这就是我知道在运行hres = ppf->Save(wsz, TRUE);行之后hres变为-2147024891的方法。

如果这些错误,mediaMaestroLocation设置为"C:\Users\Keith\Documents\Visual Studio 2012\Projects\MediaMaestro\Debug\MediaMaestro.exe",startupDestination设置为"C:\Users\Keith\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"。虽然exe位置看起来很棒,但我想知道在目标文件夹路径之后没有\是否重要。我已经检查过了,但我需要花几分钟时间弄清楚如何先做。

#include <windows.h>
#include <string>
#include <stdio.h>
#include <shobjidl.h>
#include <shlobj.h>
#include "objbase.h"
#include <objidl.h>
#include <shlguid.h>
#include <winnls.h>

#using <System.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Windows::Forms;

char startupDestination[MAX_PATH];
char mediaMaestroLocation[MAX_PATH];

DWORD nChars = 0;
BOOL yChars = 0;

HRESULT CreateLink() 
{ 
    CoInitializeEx( NULL, 0 );
    HRESULT hres = 0;
    IShellLink* psl; 

    if (SUCCEEDED(hres)) 
    { 

        // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
        // has already been called.
        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); 
        if (SUCCEEDED(hres)) 
        { 
            IPersistFile* ppf; 

            // Set the path to the shortcut target and add the description. 
            psl->SetPath(mediaMaestroLocation); 
            psl->SetDescription("Media Maestro"); 

            // Query IShellLink for the IPersistFile interface, used for saving the 
            // shortcut in persistent storage. 
            hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); 

            if (SUCCEEDED(hres)) 
            { 
                WCHAR wsz[MAX_PATH]; 

                // Ensure that the string is Unicode. 
                MultiByteToWideChar(CP_ACP, 0, startupDestination, -1, wsz, MAX_PATH); 


                // Add code here to check return value from MultiByteWideChar 
                // for success.

                // Save the link by calling IPersistFile::Save. 
                hres = ppf->Save(wsz, TRUE); 
                ppf->Release(); 
            }
            psl->Release(); 
        }
    }
    CoUninitialize();
    return hres; 
}


以下是调用该函数的UI中的click事件:

void settingsLaunchOnStart_Click( Object^ Sender, EventArgs^ e )
   {

       if (settingsLaunchOnStart->Checked == false)
       {
            HRESULT r;
            nChars = GetModuleFileName( NULL, mediaMaestroLocation, sizeof(mediaMaestroLocation) );
            yChars = SHGetFolderPath( NULL, CSIDL_STARTUP, NULL, SHGFP_TYPE_CURRENT, startupDestination);
            r = CreateLink();
       }
       else if (settingsLaunchOnStart->Checked == true)
       {

        //code to remove the shortcut
       }
   }



有什么我想念的吗?

2 个答案:

答案 0 :(得分:3)

事实证明,仅仅命名输出文件夹路径是不够的,我还必须命名文件和扩展名。对我来说这似乎很奇怪,因为我认为我没有看到其他一个例子。无论如何,这是我更新的工作代码:

HRESULT CreateLink() 
{ 
    CoInitializeEx( NULL, 0 );
    HRESULT hres = 0;
    IShellLink* psl; 

    if (SUCCEEDED(hres)) 
    { 

        // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
        // has already been called.
        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLink, (LPVOID*)&psl); //CLSCTX_ALL CLSCTX_INPROC_SERVER (void**)&psl (LPVOID*)&psl
        if (SUCCEEDED(hres)) 
        { 
            IPersistFile* ppf; 

            // Set the path to the shortcut target and add the description. 
            psl->SetPath(mediaMaestroLocation);
            psl->SetDescription(L"Media Maestro"); 
            psl->SetIconLocation(mediaMaestroLocation, 0);

            // Query IShellLink for the IPersistFile interface, used for saving the 
            // shortcut in persistent storage. 
            hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); //(void**)&psl (LPVOID*)&ppf

            if (SUCCEEDED(hres)) 
            { 
                WCHAR wsz[MAX_PATH]; 

                // Save the link by calling IPersistFile::Save. 

                hres = _wmakepath_s( wsz, _MAX_PATH, NULL, startupDestination,
                      L"MediaMaestro", L"lnk" );

                hres = ppf->Save(wsz, TRUE); 
                ppf->Release(); 
            }
            psl->Release(); 
        }
    }
    CoUninitialize();
    return hres; 
}

添加_wmakepath_s,我可以将我的程序名称及其扩展名附加到我从SHGetFolderPath获取的文件路径中。一旦我将其提供给IPersistFile界面,它就会保存它。

答案 1 :(得分:0)

你只是将hres初始化为0然后检查它是否成功?你永远不会在某个地方宣布它,并且-2147024891可能意味着该变量尚未初始化。

一个疯狂的猜测是它永远不会删除:hres = ppf->Save(wsz, TRUE);行,因此它没有初始化:P尝试在调试时输出一些断点,并且可能会使用一些监视来查看变量:)

最好的问候。