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

C++ ShellExecute specifically not opening LNK files

-Windows 7 64 位
-Visual Studio 2013 (v120)
- 启用 Unicode
-目标构建-调试 32 位

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

疑似问题
-32 位/64 位差异
-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://whosebug.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;
}

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

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

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

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 平台时,路径将被解析为: 这就是你的程序找不到路径的原因。

如果我 select x64:

把你的目标文件放到对应的文件中。

编辑:

我用MS工具Procmom.exe测试后,发现了一些其他的东西,如果运行是32位的,会显示:

键值是 C:\Program Files (x86),如果我们 运行 它是 64 位的,键是对“HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir”的引用,键值是 C:\Program Files。检查注册表后: 好像C:\Program Files默认对32位注册表是不可见的(具体原因我不太清楚)。 如果您在 32 位注册表中将密钥 ProgramFilesDir 更改为 C:\Program Files,该问题将得到解决。