本文记录违规地采用 IShellLinkW 创建 URL 网址超链接快捷方式的方法
开始之前,必须说明的是,在微软文档上明确说明不能用来创建指向 URL 的快捷方式
This interface cannot be used to create a link to a URL.
详细请看 https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ishelllinkw
但实际上是可以在 SetPath 里面设置 URL 路径的。尽管微软文档上明确说了不行,但实际上是可以的
为了方便地使用 IShellLinkW 接口,本文使用了 CsWin32 库。此库的使用方法请参阅 dotnet 使用 CsWin32 库简化 Win32 函数调用逻辑
引用之后的 csproj 项目文件的代码大概如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWin32" PrivateAssets="all" Version="0.3.264" />
</ItemGroup>
</Project>
添加 NativeMethods.txt 文件,添加如下代码
ICustomDestinationList
IObjectCollection
IShellLinkW
IPersistFile
IPropertyStore
PKEY_Title
PropVariantClear
CoCreateInstance
添加 NativeMethods.json 文件,添加如下代码
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false
}
封装 ShellLinkProvider 类,用来获取 IShellLinkW 对象,代码如下
internal static class ShellLinkProvider
{
public static unsafe IShellLinkW* CreateShellLink()
{
IShellLinkW* link = CreateCom<IShellLinkW>(CLSID_IShellLinkW);
return link;
}
private static readonly Guid CLSID_IShellLinkW = new Guid("00021401-0000-0000-C000-000000000046");
private static unsafe T* CreateCom<T>(in Guid clsid)
where T : unmanaged
{
int hr = PInvoke.CoCreateInstance<T>(in clsid, /* No aggregation */ null, CLSCTX.CLSCTX_INPROC_SERVER, out var ptr);
Marshal.ThrowExceptionForHR(hr);
return ptr;
}
}
再封装 ShortcutHelper 类,用来辅助创建快捷方式
internal static class ShortcutHelper
{
/// <summary>
/// 创建一个快捷方式
/// </summary>
/// <param name="lnkFilePath">快捷方式的完全限定路径。</param>
/// <param name="workDir"></param>
/// <param name="args">快捷方式启动程序时需要使用的参数。</param>
/// <param name="targetPath"></param>
/// <param name="iconFile"></param>
public static unsafe void CreateShortcut(string lnkFilePath, string targetPath, string workDir, string args = "", string iconFile = "")
{
IShellLinkW* shellLinkW = ShellLinkProvider.CreateShellLink();
shellLinkW->SetPath(targetPath);
shellLinkW->SetArguments(args);
shellLinkW->SetWorkingDirectory(workDir);
shellLinkW->SetIconLocation(iconFile, -1);
shellLinkW->QueryInterface(out IPersistFile* persistFile);
persistFile->Save(lnkFilePath, false);
}
}
尝试创建快捷方式,代码如下
var shortcutFile = Path.Join(AppContext.BaseDirectory, "1.lnk");
// 尽管文档上明确说明不能用来创建指向 URL 的快捷方式,但实际上是可以的
// > This interface cannot be used to create a link to a URL.
ShortcutHelper.CreateShortcut(shortcutFile, "https://blog.lindexi.com/", Directory.GetCurrentDirectory());
经过实际测试,创建出来的是 .lnk 格式的文件,而不是 .url 格式的文件,且创建出来的快捷方式双击可以打开超链接
再次说明,微软官方文档说明了,不应该使用 IShellLinkW 创建 URL 超链接
本文代码放在 github 和 gitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快
先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 8dc0e09a60e1bf0e5a6d88ab63bfeb64da7b3dde
以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 8dc0e09a60e1bf0e5a6d88ab63bfeb64da7b3dde
获取代码之后,进入 Workbench/BecearyernaDurfodejefela 文件夹,即可获取到源代码
更多技术博客,请参阅 博客导航
本文会经常更新,请阅读原文: https://blog.lindexi.com/post/%E4%BD%BF%E7%94%A8-IShellLinkW-%E5%88%9B%E5%BB%BA-URL-%E7%BD%91%E5%9D%80%E8%B6%85%E9%93%BE%E6%8E%A5%E5%BF%AB%E6%8D%B7%E6%96%B9%E5%BC%8F.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者收藏我的博客导航
本作品采用
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:
https://blog.lindexi.com
),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请
与我联系
。
无盈利,不卖课,做纯粹的技术博客
以下是广告时间
推荐关注 Edi.Wang 的公众号
欢迎进入 Eleven 老师组建的 .NET 社区
以上广告全是友情推广,无盈利