简体   繁体   English

如何将 Powershell 中的 Windows 快捷方式创建到文件名中包含特殊字符的文件?

[英]How to create a Windows Shortcut in Powershell to a file with special characters in filename?

I usually never have programming problems because I can easily find the answer to most of them.我通常不会遇到编程问题,因为我可以轻松找到大多数问题的答案。 But I am at my wits' end on this issue.但我在这个问题上束手无策。

The well known way of creating a Windows shortcut in Powershell is as follows:在 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()

However, this method has a shortcoming which I'm starting to be bothered by more and more: it does not work when the filename has special characters eg a smiley face in filename:然而,这种方法有一个缺点,我开始被越来越多的困扰:当文件名有特殊字符时它不起作用,例如文件名中的笑脸:

"targetfile 😍.txt"

I researched the issue and discovered here that the WshShortcut object and WScript cannot accept unicode in the filenames.我研究了这个问题并在这里发现 WshShortcut object 和 WScript 不能接受文件名中的 unicode。 It only seems to work for a simple set of characters.它似乎只适用于一组简单的字符。 Of course, when you right-click the file in Windows and select "Create Shortcut" Windows has no problems creating the shortcut with the special character in it.当然,当您右键单击 Windows 和 select 中的文件时,“创建快捷方式” Windows 在创建带有特殊字符的快捷方式时没有问题。

Someone scripted in C# an alternative way to create shortcuts using Shell32 but I don't know if it can be done in Powershell.有人在 C# 中编写了另一种使用 Shell32 创建快捷方式的方法,但我不知道它是否可以在 Powershell 中完成。 And it looks like an old method which might not work in newer builds of Windows.它看起来像是一种旧方法,可能不适用于 Windows 的较新版本。

Would someone please help me with this issue?有人可以帮我解决这个问题吗? How to create a Windows shortcut in Powershell to a file whose filename has special characters in it?如何将 Powershell 中的 Windows 快捷方式创建到文件名中包含特殊字符的文件?

When in doubt, use C#:如有疑问,请使用 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)
        {
            IShellLinkW link = new IShellLinkW();

            link.SetPath(targetPath);

            if (!string.IsNullOrWhiteSpace(description))
            {
                link.SetDescription(description);
            }

            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', '😍😍')

[Shox.ShellLink]::CreateShortcut('F:\path\to\shortcut2.lnk', 'F:\some\other\path\to\targetfile2 😍.txt', $null)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM