PowerShell 脚本在粘贴到 PowerShell 窗口时运行,但在从快捷方式运行时不运行

CBe*_*als 3 unicode powershell utf-8 character-encoding codepages

我正在尝试编写一个脚本,将多个 Excel 文件转换为 PDF 文件。我在网上找到了一个有效的链接

\n
$path = Read-Host -Prompt \'Input Directory Path and Press Enter\'\n$xlFixedFormat = \xe2\x80\x9cMicrosoft.Office.Interop.Excel.xlFixedFormatType\xe2\x80\x9d -as [type]\n$excelFiles = Get-ChildItem -Path $path -include *.xls, *.xlsx -recurse\n$objExcel = New-Object -ComObject excel.application\n$objExcel.visible = $false\nforeach($wb in $excelFiles)\n{\n    $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + \xe2\x80\x9c.pdf\xe2\x80\x9d)\n    $workbook = $objExcel.workbooks.open($wb.fullname, 3)\n    $workbook.Saved = $true\n    \xe2\x80\x9csaving $filepath\xe2\x80\x9d\n    $workbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $filepath)\n    $objExcel.Workbooks.close()\n}\n$objExcel.Quit()\n
Run Code Online (Sandbox Code Playgroud)\n

如果我将其复制并粘贴到 PowerShell 窗口中,程序将按预期运行。但是,当我尝试创建运行该程序的快捷方式时,出现了几个错误(文件保存为 .ps1)。

\n

这是我在设置快捷方式时所做的路径和参数:

\n
$path = Read-Host -Prompt \'Input Directory Path and Press Enter\'\n$xlFixedFormat = \xe2\x80\x9cMicrosoft.Office.Interop.Excel.xlFixedFormatType\xe2\x80\x9d -as [type]\n$excelFiles = Get-ChildItem -Path $path -include *.xls, *.xlsx -recurse\n$objExcel = New-Object -ComObject excel.application\n$objExcel.visible = $false\nforeach($wb in $excelFiles)\n{\n    $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + \xe2\x80\x9c.pdf\xe2\x80\x9d)\n    $workbook = $objExcel.workbooks.open($wb.fullname, 3)\n    $workbook.Saved = $true\n    \xe2\x80\x9csaving $filepath\xe2\x80\x9d\n    $workbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $filepath)\n    $objExcel.Workbooks.close()\n}\n$objExcel.Quit()\n
Run Code Online (Sandbox Code Playgroud)\n

这是我收到的错误消息:

\n
C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -noexit -ExecutionPolicy Bypass -File C:\\[File Path]\n
Run Code Online (Sandbox Code Playgroud)\n

为什么这会失败?

\n

mkl*_*nt0 6

澄清:

\n
    \n
  • 使用 Unicode(非 ASCII 范围)引号是完全可以的,例如\xe2\x80\x9c在 PowerShell 中- 请参阅底部部分。

    \n
  • \n
  • 但是,为了在脚本文件中使用此类字符,这些文件必须使用Unicode字符编码,例如 UTF-8 或 UTF-16LE(“Unicode”)。

    \n
  • \n
\n

您的问题是您的脚本文件保存为没有BOM的 UTF-8 ,这会导致Windows PowerShell(但不是 PowerShell (Core) 7+误解,因为它默认为“ANSI”编码,即单字节与遗留系统区域设置相关的遗留编码又称为非 Unicode 程序的语言(例如,美国和西欧的Windows-1252Default ),PowerShell 将其称为.

\n

虽然用对应的 ASCII 引号替换 Unicode 引号可以解决眼前的问题,但脚本中的任何其他非 ASCII 范围字符将继续被误解。

\n
    \n
  • 正确的解决方案是将文件重新保存为带有 BOM 的UTF-8 。

    \n
  • \n
  • 养成定期将所有 PowerShell 脚本(源代码)保存为带有 BOM 的UTF-8是一个好习惯,因为这可以确保它们被解释为相同,而不管任何给定计算机的系统区域设置(文化)如何,并且无论您使用什么PowerShell 版本。

    \n
      \n
    • 请参阅此相关答案,其中演示了如何配置Visual Studio Code以将新的 PowerShell 文件创建为带有 BOM 的UTF-8 。
    • \n
    \n
  • \n
\n
\n

为了演示具体问题:

\n
    \n
  • \xe2\x80\x9c,左双引号 ( ) Unicode 字符,以UTF-8 格式U+201C编码为三个0xE2 0x80 0x9C字节: 。

    \n
  • \n
  • 您可以通过以下输出来验证这一点\'\xe2\x80\x9c\' | Format-Hex -Encoding Utf8(这里只有字节序列重要;右侧打印的字符在这种情况下不具有代表性)。

    \n
  • \n
  • 当 Windows PowerShell 将此序列读取为“ANSI”编码时,它会将每个字节视为其自身的一个字符,这就是为什么您在输出中看到单个字节的三个字符,即。\xe2\x80\x9c\xc3\xa2\xe2\x82\xac\xc5\x93

    \n
  • \n
  • 您可以使用[Text.Encoding]::Default.GetString([byte[]] (0xE2, 0x80, 0x9C))(从 PowerShell Core中使用[Text.Encoding]::GetEncoding([cultureinfo]::CurrentCulture.TextInfo.ANSICodePage).GetString([byte[]] (0xE2, 0x80, 0x9C)))来验证这一点。

    \n
  • \n
\n
\n

在 PowerShell 中可互换使用 ASCII 范围和 Unicode 引号、破折号和空格:

\n

在正确编码的输入文件中,PowerShell 允许互换使用以下引号和标点符号;例如,"hi"\xe2\x80\x9dhi\xe2\x80\x9d和 Even"hi\xe2\x80\x9e是等价的。

\n\n

笔记:

\n
    \n
  • 重要提示:上面描述了这些字符的可互换语法使用;如果您在标识符(不应该)或字符串[1]中使用此类字符,则它们不会被同等对待。

    \n
  • \n
  • 上面的部分内容是从 GitHub 上的源代码中收集的(Is...文件中的函数CharTraits.cs,另请参阅上面的SpecialChars定义)。

    \n
  • \n
\n
\n

[1] 有有限的例外:鉴于 PowerShell 的运算符使用不变区域性-eq来比较字符串而不是执行序数比较,因此在字符串比较中空格字符的变化可能会被视为相同,具体取决于主机平台;例如,在 macOS 和 Linux(但不是 Windows!)上产生,因为常规 ASCII 范围空间被认为等于那里的不间断空格 ( )。"foo bar" -eq "foo`u{a0}bar"$trueU+00A0

\n


归档时间:

查看次数:

2765 次

最近记录:

2 年,3 月 前