C ++ ShellExecute专门不打开LNK文件

时间:2019-01-16 21:36:58

标签: c++ winapi shellexecute

-Windows 7 64位
-Visual Studio 2013(v120)
-已启用Unicode
-Target Build- Debug 32-bit

我想构建一个启动器(供个人使用),但是我无法让ShellExecute使用所有文件类型或路径,特别是快捷方式(LNK)。我已经研究和尝试了以下多种组合...
-我正在使用转义序列
-我正在添加文件扩展名(并且尝试不使用)
-我包含了Windows.h
-打印目录FindFirstFile / FindNextFile,以明确确保路径没有错别字
-尝试使用文字和变量作为文件路径参数
-尝试以管理员权限运行VS
-尝试使用ShellExecute,ShellExecuteA,ShellExecuteEx和System(具有适当的字符集)
-动词尝试NULL,“ runas”和“ open”
-使用相同的路径从命令行或资源管理器中正常启动
-尝试使用%USERPROFILE%宏代替用户名(返回2)
-似乎可以使用EXE和URL
-似乎无法在包括C:\在内的任何路径上直接与任何LNK一起使用

疑似问题
-32bit / 64bit差异
-UAC /惊喜
-字符集
-文件扩展名
-防病毒干扰(尽管AV不会向我发出任何警报),并且我在沉默AV的同时进行了测试

这是我尝试过的最简单的程序之一...

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <atlstr.h>

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    // Variables below for testing as path argument
    // Paths that end with LNK are the only ones that I can't get to launch
    CStringW link("C:\\Users\\Home\\Documents\\Art\\blender.lnk"); // Doesn't work
    CStringW target("C:\\Program Files\\Blender Foundation\\Blender\\blender.exe"); // Launches software as expected
    CStringW url("https://stackoverflow.com"); // Launches browser with URL as expected

    int error = reinterpret_cast<int>(ShellExecute(
        NULL, 
        NULL, 
        L"C:\\Users\\Home\\Documents\\Art\\blender.lnk", // Using literal with LNK extension also does not work
        NULL, 
        NULL, 
        SW_SHOWDEFAULT
        ));


    // EVEN SYSTEM CAN NOT FIND THE PATH!!!
    // system("C:\\Users\\Home\\Documents\\Art\\blender.lnk");

    std::cout << error << std::endl; // Returns 3 "The specified path was not found.".

    // Free COM
    CoUninitialize();

    return 0;
}

1 个答案:

答案 0 :(得分:1)

首先,检查.lnk文件是否在路径中。

然后(也是引起问题的最可能原因)检查是否正确创建了.lnk文件名。为了确保它不像“ blender.lnk.lnk”(如果设置为这个,我可以重现您的问题)。

您也可以尝试自己手动分析链接文件的路径。 这是示例:

void ShortcutToRealpath(LPWSTR pszString, LPSTR pdzString)
{
    IShellLink   *pShellLink;
    HRESULT hRes;

    ::CoInitialize(NULL);
    hRes = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
    if (SUCCEEDED(hRes))
    {
        IPersistFile   *ppf;
        hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&ppf);
        if (SUCCEEDED(hRes))
        {
            hRes = ppf->Load(pszString, TRUE);
            if (SUCCEEDED(hRes))
            {
                pShellLink->GetPath(pdzString, MAX_PATH, NULL, 0);
            }
            ppf->Release();
        }
        pShellLink->Release();
    }
    ::CoUninitialize();
}

当我构建为x86平台时,路径将被解析为: enter image description here 这就是您的程序找不到路径的原因。

如果我选择x64: enter image description here

将目标文件放入相应的文件。

编辑:

用MS工具Procmom.exe测试之后,我发现了其他东西,如果以32位运行,它将显示: enter image description here

密钥值为C:\Program Files (x86),如果我们以64位运行,则密钥引用为“ HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir”,密钥值为C:\Program Files。在检查注册表后: enter image description here enter image description here 看来C:\Program Files在默认情况下对32位注册表不可见(我不确定具体原因)。 如果在32位注册表中将密钥ProgramFilesDir更改为C:\Program Files,此问题将得到解决。