powershell - 将Powershell脚本粘贴到Powershell中时运行,但从快捷方式运行时不运行

标签 powershell unicode utf-8 character-encoding codepages

我正在尝试将一个脚本转换为几个excel文件。这是我第一次在Powershell中进行类似的操作。 I found a link to one online that works

$path = Read-Host -Prompt 'Input Directory Path and Press Enter' 
$xlFixedFormat = “Microsoft.Office.Interop.Excel.xlFixedFormatType” -as [type] 
$excelFiles = Get-ChildItem -Path $path -include *.xls, *.xlsx -recurse 
$objExcel = New-Object -ComObject excel.application 
$objExcel.visible = $false 
foreach($wb in $excelFiles) 
{ 
 $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + “.pdf”) 
 $workbook = $objExcel.workbooks.open($wb.fullname, 3) 
 $workbook.Saved = $true 
“saving $filepath” 
 $workbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $filepath) 
 $objExcel.Workbooks.close() 
} 
$objExcel.Quit()

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

这是设置快捷方式时我所做的路径和参数:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -ExecutionPolicy Bypass -File C:\[File Path]

这是我收到的错误消息:
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:8 char:62
+  $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + “.pdf ...
+                                                              ~
You must provide a value expression following the '+' operator.
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:8 char:63
+ ... lepath = Join-Path -Path $path -ChildPath ($wb.BaseName + “.pdfâ€)
+                                                               ~~~~~~~~~~
Unexpected token '“.pdfâ€' in expression or statement.
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:8 char:62
+  $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + “.pdf ...
+                                                              ~
Missing closing ')' in expression.
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:7 char:1
+ {
+ ~
Missing closing '}' in statement block or type definition.
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:8 char:73
+ ... lepath = Join-Path -Path $path -ChildPath ($wb.BaseName + “.pdfâ€)
+                                                                         ~
Unexpected token ')' in expression or statement.
At C:\Users\cbeals.ENVIROTECH\Documents\Test\ConvertExcelToPDF.ps1:14 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ExpectedValueExpression

任何想法为什么会失败?

最佳答案

澄清:

  • 在PowerShell 中使用Unicode(非ASCII范围)引号(例如 )完全可以-参见底部。
  • 但是,为了在脚本文件中使用此类字符,这些文件必须使用Unicode字符编码,例如UTF-8或UTF-16LE(“Unicode”)。

  • 您的问题是您的脚本文件被保存为没有BOM的UTF-8,这会导致Windows PowerShell(但不是PowerShell Core)误解为,因为默认为ANSIt编码,即单字节与旧版系统语言环境(例如,美国和西欧的Windows-1252)关联的旧版编码,PowerShell调用Default

    虽然用ASCII对应字符替换Unicode引号可以解决当前的问题,但是脚本中的任何其他非ASCII范围字符都将继续被误解。
  • 正确的解决方案是使用BOM将文件重新保存为UTF-8。
  • 这是一个好习惯,即使用BOM表来将常规的所有PowerShell脚本(源代码)定期保存为UTF-8格式,因为这样可以确保对它们的解释相同,而与任何给定计算机的系统区域设置无关。
  • 请参见this related answer,它显示了如何相应地配置Visual Studio Code。


  • 为了演示具体问题:

    左双重引用标记()Unicode字符
  • U+201C以UTF-8格式0xE2 0x80 0x9C编码为3个字节。
  • 您可以通过'“' | Format-Hex -Encoding Utf8的输出来验证这一点(这里仅字节序列很重要;在这种情况下,右侧的打印字符不具有代表性)。
  • 当Windows PowerShell将该序列读取为“ANSI”编码时,它将每个字节本身视为一个字符,这就是为什么您在输出中看到单个 3个字符的原因,即“
  • 您可以使用[Text.Encoding]::Default.GetString([byte[]] (0xE2, 0x80, 0x9C))进行验证(在PowerShell Core中,使用[Text.Encoding]::GetEncoding([cultureinfo]::CurrentCulture.TextInfo.ANSICodePage).GetString([byte[]] (0xE2, 0x80, 0x9C)))。


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

    在正确编码的输入文件中,PowerShell允许以下引号和标点字符可互换使用;例如"hi"”hi”甚至"hi„是等效的。
  • 双引号:
  • "(ASCII范围)-QUOTATION MARK ( U+0022 )
  • -LEFT DOUBLE QUOTATION MARK ( U+201C )
  • -RIGHT DOUBLE QUOTATION MARK ( U+201D )
  • -DOUBLE LOW-9 QUOTATION MARK ( U+201E )
  • 但是而不是:-DOUBLE HIGH-REVERSED-9 QUOTATION MARK ( U+201F ),即使其单引号被识别,也请参见this GitHub issue
  • 单引号:
  • '-(ASCII范围)APOSTROPHE ( U+0027 )
  • -LEFT SINGLE QUOTATION MARK (U+2018)
  • -RIGHT SINGLE QUOTATION MARK ( U+2019 )
  • -SINGLE LOW-9 QUOTATION MARK ( U+201A )
  • -SINGLE HIGH-REVERSED-9 QUOTATION MARK ( U+201B )
  • 破折号(严格来说,ASCII范围“破折号”是连字符):
  • -(ASCII范围)-HYPHEN-MINUS ( U+002D )
  • -EN DASH ( U+2013 )
  • -EM DASH ( U+2014 )
  • -HORIZONTAL BAR ( U+2015 )
  • 空格:
  • 注意:链接到下面的源代码位置未明确定义等效的空格字符(与引号和破折号不同)。以下内容是根据基于Unicode字符描述的实验得出的,可能不完整。排除了Unicode BMP(基本多语言平面)之外的字符,即那些代码点不适合.NET用来表示字符的16位代码单元的字符。
  • 行内空白:
  • 注意:空格字符和制表符字符的变体可以互换地用作句法分隔符。在空格字符变体中,只有U+200B(ZERO WIDTH SPACE)char。在语法上不被视为空格。
  • 空间:
  • (ASCII范围空格字符)U+0020(SPACE)
  •   U+00A0(NO-BREAK SPACE)
  • U+2002(EN SPACE)
  • U+2003(EM SPACE)
  • U+2004(THREE-PER-EM SPACE)
  • U+2005(FOUR-PER-EM SPACE))
  • U+2006(SIX-PER-EM SPACE)
  • U+2007(FIGURE SPACE)
  • U+2008(PUNCTUATION SPACE)
  • U+2009(THIN SPACE)
  • U+200A(HAIR SPACE)
  • U+202F(NARROW NO-BREAK SPACE)
  • U+205F(MEDIUM MATHEMATICAL SPACE)
  •   U+3000(IDEOGRAPHIC SPACE)
  • 制表符(由于无法在此处直接打印而显示为转义序列):
  • "`t"(ASCII范围制表符)-U+0009(CHARACTER TABULATION)
  • "`v"(ASCII范围的垂直制表符)-U+000B(LINE TABULATION))
  • 行分隔空格:
  • (ASCII范围LF)U+000A(LINE FEED)
  • (ASCII范围CR)U+000D(CARRIAGE RETURN)

  • 注意:
  • 重要:上面的描述了这些字符的可互换句法用法。如果您在标识符(不应使用)或字符串[1]中使用此类字符,则将它们视为不相同。
  • 以上是部分收集的from the source code on GitHub(文件SpecialCharacters中的parserutils.cs类)。


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

    关于powershell - 将Powershell脚本粘贴到Powershell中时运行,但从快捷方式运行时不运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55049410/

    相关文章:

    java - 如何使用 JavaScript 在 Spring MVC 中获取对 JSP 的 Unicode 响应

    ruby - 我总是在使用 Mechanize 的 UTF-8 错误中得到一个无效的字节序列

    windows - WMIC命令批量输出非UTF-8文本文件

    相同类型的Powershell参数集

    windows - 在 Windows 2012 R2 中使用 Powershell 导入计划任务

    asp.net - 无法提交配置更改,因为文件在磁盘上已更改

    java - PDFBox 在提取使用 DejaVu Sans Condensed 字体编码的文本时抛出错误

    javascript - 如何将 unicode 转义序列 URL 转换为 python unicode?

    perl - 如何使 Perl 正确解释 Unicode 字节?

    variables - $是什么? Powershell 中的别名?