Скрипт Powershell запускается при вставке в Powershell, но не при запуске из ярлыка - PullRequest
1 голос
/ 07 марта 2019

Я пытаюсь собрать скрипт, который преобразует несколько файлов Excel в PDF-файлы. Я впервые делаю что-то подобное в Powershell. Я нашел ссылку на один онлайн, который работает .

$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

Есть идеи, почему это не получится?

1 Ответ

1 голос
/ 08 марта 2019

уточнить:

  • Прекрасно использовать кавычки в Юникоде (не в диапазоне ASCII), такие как в PowerShell - см. Нижний раздел.

  • Однако, чтобы использовать такие символы в файлах сценариев , эти файлы должны использовать кодировку символов Unicode , например UTF-8 или UTF-16LE («Юникод»).

Ваша проблема заключалась в том, что ваш файл сценария был сохранен как UTF-8 без спецификации , что приводит к неверной интерпретации Windows PowerShell (но не PowerShell Core ) it , потому что по умолчанию используется кодировка "ANSI" , то есть однобайтовая устаревшая кодировка, связанная с языком устаревшей системы (например, Windows-1252 в США и Западной Европе) , который PowerShell называет Default.

Хотя замена кавычек Unicode их аналогами ASCII решает непосредственную проблему, любые другие символы, не входящие в диапазон ASCII, в сценарии будут по-прежнему неправильно интерпретироваться.

  • Правильным решением является повторное сохранение файла в формате UTF-8 с спецификацией .
  • Хорошей привычкой является регулярное сохранение всех сценариев PowerShell (исходного кода) в формате UTF-8 с спецификацией , поскольку это гарантирует, что они интерпретируются одинаково независимо от того, языковой системы любого компьютера.

Чтобы продемонстрировать конкретную проблему:

  • , ЛЕВАЯ МАРКА ДВОЙНОЙ ЦИТАТЫ (U+201C) Символ Unicode, кодируется как 3 байтов в формате UTF-8: 0xE2 0x80 0x9C.

    • Вы можете проверить это с помощью вывода из '“' | 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))).

Взаимозаменяемое использование кавычек / дефисов / пробелов в диапазоне ASCII и Unicode в PowerShell:

В правильно закодированном входном файле PowerShell допускает взаимозаменяемое использование следующих кавычек и знаков препинания; например, "hi", ”hi” и даже "hi„ эквивалентны.

Примечание:

  • Важно : Выше описывается взаимозаменяемое синтаксическое использование этих символов ; если вы используете такие символы в идентификаторах (что не следует) или в строках [1] , они не обработаны то же самое.

  • Вышесказанное было частично извлечено из исходного кода на GitHub (класс SpecialCharacters в файле parserutils.cs).


[1] Существуют ограниченные исключения: учитывая, что оператор -eq PowerShell сравнивает строку с использованием инвариантной культуры вместо выполнения порядкового сравнения, space- символ варианты может обрабатываться одинаково при сравнении строк, в зависимости от платформы хоста ; например, "foo bar" -eq "foo`u{a0}bar" дает $true в macOS и Linux (но не в Windows!), поскольку обычное пространство диапазона ASCII считается равным пробелу без перерывов (U+00A0).

...