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
,该问题将得到解决。
-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
,该问题将得到解决。