[英]InternetShortcut object IPersistFile::Save fails with E_FAIL (0x80004005)
This one had me stuck for too long, so I'm self answering this.这个让我卡了太久,所以我自己回答这个问题。 Apologies for the sardonic tone!
为讽刺的语气道歉!
Trying to use the official API to create.url files has only the following documentation :尝试使用官方 API 创建.url 文件只有以下文档:
- Create an instance of the Internet shortcut object with CoCreateInstance, using a CLSID of CLSID_InternetShortcut.
使用 CLSID_InternetShortcut 的 CLSID 使用 CoCreateInstance 创建 Internet 快捷方式 object 的实例。
- Use the IUniformResourceLocator::SetURL method to set the URL in the shortcut.
使用 IUniformResourceLocator::SetURL 方法在快捷方式中设置 URL。
- Use the IPersistFile::Save method to save the shortcut file to a desired location.
使用 IPersistFile::Save 方法将快捷方式文件保存到所需位置。
Ok, so that should look something like this (my actual code is rust, sorry for the lack of testing):好的,应该看起来像这样(我的实际代码是 rust,抱歉缺乏测试):
CoInitializeEx(nullptr, 0);
IUniformResourceLocator* url = nullptr;
CoCreateInstance(
CLSID_InternetShortcut,
nullptr,
CLSCTX_INPROC,
IID_IUniformResourceLocator,
(void**)&url,
);
Oh this fails with E_NOINTERFACE?哦,E_NOINTERFACE 失败了? Well there's not much code yet, so it's not too hard to guess that you have to init with STA, instead of the default MTA:
好吧,还没有太多代码,所以不难猜测您必须使用 STA 进行初始化,而不是使用默认的 MTA:
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
So that's the first step, the second is just something like:所以这是第一步,第二步是这样的:
url->SetURL(L"https://stackoverflow.com", 0);
Now for the third step:现在进行第三步:
IPersistFile* file = nullptr;
url->QueryInterface(IID_IPersistFile, (void**)&file);
file->Save(L"best-site.url", FALSE);
Huh, Save()
is returning E_FAIL?嗯,
Save()
正在返回 E_FAIL? That's strange, I'm using exactly the same code for saving a ShellLink object to a.lnk file?这很奇怪,我使用完全相同的代码将 ShellLink object 保存到 .lnk 文件?
The answer is actually quite simple: InternetShortcut
for whatever reason, unlike ShellLink
and presumably other shell objects requires that the path for Save()
is absolute.答案实际上很简单:无论出于何种原因,
InternetShortcut
都与ShellLink
和可能的其他 shell 对象不同,它要求Save()
的路径是绝对的。 (And only Save()
, Load()
is quite happy with a relative path) (而且只有
Save()
, Load()
对相对路径非常满意)
So, the full working code using WIL :因此,使用WIL的完整工作代码:
#include <windows.h>
#include <IntShCut.h>
#include <wil/com.h>
void save_link(LPCWSTR url_value, LPCWSTR path) {
auto url = wil::CoCreateInstance<IUniformResourceLocator>(CLSID_InternetShortcut, CLSCTX_INPROC);
THROW_IF_FAILED(url->SetURL(url_value, 0));
auto file = url.query<IPersistFile>();
WCHAR full_path[MAX_PATH];
GetFullPathName(path, ARRAYSIZE(full_path), full_path, nullptr);
THROW_IF_FAILED(file->Save(full_path, FALSE));
}
int main() {
THROW_IF_FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED));
save_link(L"https://stackoverflow.com", L"best-site.url");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.