如何在 Powershell 中为文件名中包含特殊字符的文件创建 Windows 快捷方式?
How to create a Windows Shortcut in Powershell to a file with special characters in filename?
我通常不会遇到编程问题,因为我可以很容易地找到大多数问题的答案。但是我在这个问题上束手无策。
在 Powershell 中创建 Windows 快捷方式的众所周知的方法如下:
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("F:\path\to\shortcut.lnk")
$Shortcut.TargetPath = "F:\some\other\path\to\targetfile.txt"
$Shortcut.Save()
然而,这种方法有一个缺点,我开始越来越困扰它:当文件名有特殊字符时它不起作用,例如文件名中的笑脸:
"targetfile .txt"
我研究了这个问题并发现 here WshShortcut 对象和 WScript 不能接受文件名中的 unicode。它似乎只适用于一组简单的字符。当然,当你在Windows和select中右键单击文件时“创建快捷方式”Windows创建带有特殊字符的快捷方式是没有问题的。
有人用 C# 编写脚本 an alternative way to create shortcuts using Shell32 但我不知道是否可以在 Powershell 中完成。它看起来像是一种旧方法,可能不适用于 Windows.
的较新版本
有人可以帮我解决这个问题吗?如何在 Powershell 中为文件名中包含特殊字符的文件创建 Windows 快捷方式?
如有疑问,请使用 C#:
$ShellLinkCSharp = @'
namespace Shox
{
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
[CoClass(typeof(CShellLinkW))]
interface IShellLinkW
{
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, uint fFlags);
IntPtr GetIDList();
void SetIDList(IntPtr pidl);
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
ushort GetHotKey();
void SetHotKey(ushort wHotKey);
uint GetShowCmd();
void SetShowCmd(uint iShowCmd);
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, [Optional] uint dwReserved);
void Resolve(IntPtr hwnd, uint fFlags);
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
[ClassInterface(ClassInterfaceType.None)]
class CShellLinkW { }
public static class ShellLink
{
public static void CreateShortcut(
string lnkPath,
string targetPath,
string description,
string workingDirectory)
{
if (string.IsNullOrWhiteSpace(lnkPath))
throw new ArgumentNullException("lnkPath");
if (string.IsNullOrWhiteSpace(targetPath))
throw new ArgumentNullException("targetPath");
IShellLinkW link = new IShellLinkW();
link.SetPath(targetPath);
if (!string.IsNullOrWhiteSpace(description))
{
link.SetDescription(description);
}
if (!string.IsNullOrWhiteSpace(workingDirectory))
{
link.SetWorkingDirectory(workingDirectory);
}
IPersistFile file = (IPersistFile)link;
file.Save(lnkPath, true);
Marshal.FinalReleaseComObject(link);
}
}
}
'@
# Check if Shox.ShellLink class already exists; if not, import it:
if (-not ([System.Management.Automation.PSTypeName]'Shox.ShellLink').Type)
{
Add-Type -TypeDefinition $ShellLinkCSharp
}
[Shox.ShellLink]::CreateShortcut(
'F:\path\to\shortcut1.lnk',
'F:\some\other\path\to\targetfile1 .txt',
' my description ',
'F:\some\another\path\my_working_directory')
[Shox.ShellLink]::CreateShortcut(
'F:\path\to\shortcut2.lnk',
'F:\some\other\path\to\targetfile2 .txt',
$null, # No description
$null) # No working directory
我通常不会遇到编程问题,因为我可以很容易地找到大多数问题的答案。但是我在这个问题上束手无策。
在 Powershell 中创建 Windows 快捷方式的众所周知的方法如下:
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("F:\path\to\shortcut.lnk")
$Shortcut.TargetPath = "F:\some\other\path\to\targetfile.txt"
$Shortcut.Save()
然而,这种方法有一个缺点,我开始越来越困扰它:当文件名有特殊字符时它不起作用,例如文件名中的笑脸:
"targetfile .txt"
我研究了这个问题并发现 here WshShortcut 对象和 WScript 不能接受文件名中的 unicode。它似乎只适用于一组简单的字符。当然,当你在Windows和select中右键单击文件时“创建快捷方式”Windows创建带有特殊字符的快捷方式是没有问题的。
有人用 C# 编写脚本 an alternative way to create shortcuts using Shell32 但我不知道是否可以在 Powershell 中完成。它看起来像是一种旧方法,可能不适用于 Windows.
的较新版本有人可以帮我解决这个问题吗?如何在 Powershell 中为文件名中包含特殊字符的文件创建 Windows 快捷方式?
如有疑问,请使用 C#:
$ShellLinkCSharp = @'
namespace Shox
{
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
[CoClass(typeof(CShellLinkW))]
interface IShellLinkW
{
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, uint fFlags);
IntPtr GetIDList();
void SetIDList(IntPtr pidl);
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
ushort GetHotKey();
void SetHotKey(ushort wHotKey);
uint GetShowCmd();
void SetShowCmd(uint iShowCmd);
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, [Optional] uint dwReserved);
void Resolve(IntPtr hwnd, uint fFlags);
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
[ClassInterface(ClassInterfaceType.None)]
class CShellLinkW { }
public static class ShellLink
{
public static void CreateShortcut(
string lnkPath,
string targetPath,
string description,
string workingDirectory)
{
if (string.IsNullOrWhiteSpace(lnkPath))
throw new ArgumentNullException("lnkPath");
if (string.IsNullOrWhiteSpace(targetPath))
throw new ArgumentNullException("targetPath");
IShellLinkW link = new IShellLinkW();
link.SetPath(targetPath);
if (!string.IsNullOrWhiteSpace(description))
{
link.SetDescription(description);
}
if (!string.IsNullOrWhiteSpace(workingDirectory))
{
link.SetWorkingDirectory(workingDirectory);
}
IPersistFile file = (IPersistFile)link;
file.Save(lnkPath, true);
Marshal.FinalReleaseComObject(link);
}
}
}
'@
# Check if Shox.ShellLink class already exists; if not, import it:
if (-not ([System.Management.Automation.PSTypeName]'Shox.ShellLink').Type)
{
Add-Type -TypeDefinition $ShellLinkCSharp
}
[Shox.ShellLink]::CreateShortcut(
'F:\path\to\shortcut1.lnk',
'F:\some\other\path\to\targetfile1 .txt',
' my description ',
'F:\some\another\path\my_working_directory')
[Shox.ShellLink]::CreateShortcut(
'F:\path\to\shortcut2.lnk',
'F:\some\other\path\to\targetfile2 .txt',
$null, # No description
$null) # No working directory