Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
475 views
in Technique[技术] by (71.8m points)

unicode - PowerShell script runs when pasted into the PowerShell window, but not when run from shortcut

I am trying to put together a script that will convert several Excel files into PDF files. 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()

If I copy and paste this into a PowerShell window, the program runs as intended. However, when I attempted to make a shortcut to run the program, I get several errors (the file is saved as a .ps1).

This is the path and arguments I made when setting up the shortcut:

C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -noexit -ExecutionPolicy Bypass -File C:[File Path]

This is the error message I get:

At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:8 char:62
+  $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + a€?.pdf ...
+                                                              ~
You must provide a value expression following the '+' operator.
At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:8 char:63
+ ... lepath = Join-Path -Path $path -ChildPath ($wb.BaseName + a€?.pdfa€)
+                                                               ~~~~~~~~~~
Unexpected token 'a€?.pdfa€' in expression or statement.
At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:8 char:62
+  $filepath = Join-Path -Path $path -ChildPath ($wb.BaseName + a€?.pdf ...
+                                                              ~
Missing closing ')' in expression.
At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:7 char:1
+ {
+ ~
Missing closing '}' in statement block or type definition.
At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:8 char:73
+ ... lepath = Join-Path -Path $path -ChildPath ($wb.BaseName + a€?.pdfa€)
+                                                                         ~
Unexpected token ')' in expression or statement.
At C:Userscbeals.ENVIROTECHDocumentsTestConvertExcelToPDF.ps1:14 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ExpectedValueExpression

Why would this be failing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

To clarify:

  • It is perfectly fine to use Unicode (non-ASCII-range) quotation marks such as in PowerShell - see the bottom section.

  • However, in order to use such characters in script files, these files must use a Unicode character encoding such as UTF-8 or UTF-16LE ("Unicode").

Your problem was that your script file was saved as UTF-8 without a BOM, which causes Windows PowerShell (but not PowerShell Core) to misinterpret it, because it defaults to "ANSI" encoding, i.e., the single-byte legacy encoding associated with the legacy system locale (e.g., Windows-1252 in the US and Western Europe), which PowerShell calls Default.

While replacing the Unicode quotation marks with their ASCII counterparts solves the immediate problem, any other non-ASCII-range characters in the script would continue to be misinterpreted.

  • The proper solution is to re-save the file as UTF-8 with BOM.
  • It is a good habit to form to routinely save all PowerShell scripts (source code) as UTF-8 with BOM, because that ensures that they're interpreted the same, irrespective of any given computer's system locale.

To demonstrate the specific problem:

  • , the LEFT DOUBLE QUOTATION MARK (U+201C) Unicode character, is encoded as three bytes in UTF-8 format: 0xE2 0x80 0x9C.

  • You can verify this via the output from '“' | Format-Hex -Encoding Utf8 (only the byte sequence matters here; the printed characters. on the right are not representative in this case).

  • When Windows PowerShell reads this sequence as "ANSI"-encoded, it considers each byte a character in its own right, which is why you saw three characters for the single in your output, namely a€?.

  • You can verify this with [Text.Encoding]::Default.GetString([byte[]] (0xE2, 0x80, 0x9C)) (from PowerShell Core, use [Text.Encoding]::GetEncoding([cultureinfo]::CurrentCulture.TextInfo.ANSICodePage).GetString([byte[]] (0xE2, 0x80, 0x9C))).


Interchangeable use of ASCII-range and Unicode quotation marks, dashes, and whitespace in PowerShell:

In a properly encoded input file, PowerShell allows interchangeable use of the following quotation and punctuation characters; e.g., "hi", ”hi” and even "hi? are equivalent.

Note:

  • Important: The above describes interchangeable syntactic use of these characters; if you use such characters in identifiers (which you shouldn't) or in strings[1], they are not treated the same.

  • The above was in part gleaned from the source code on GitHub (class SpecialCharacters in file parserutils.cs).


[1] There are limited exceptions: given that PowerShell's -eq operator compares string using the invariant culture rather than performing ordinal comparison, space-character variations may be treated the same in string comparisons, depending on the host platform; e.g., "foo bar" -eq "foo`u{a0}bar" yields $true on macOS and Linux (but not Windows!), because the regular ASCII-range space is considered equal to the no-break space (U+00A0) there.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...