Как запустить PowerShell на одной линии? - PullRequest
0 голосов
/ 07 января 2019

Согласно этому ответу операторы PowerShell могут быть разделены точкой с запятой.

Вот фрагмент скрипта, с которым я работаю (несколько отредактировано для упрощения):

Add-Type -AssemblyName System.Web;

$server = "http://website.com/index.php";

foreach ($path in [System.IO.Directory]::EnumerateFiles("C:\path\to\dir","*.xml","AllDirectories")) {

  try {
    $oXml = New-Object System.XML.XMLDocument;
    $oXml.Load($path);
    <more commands here>;
  } catch {}

}

Вот одна из моих многочисленных попыток его сжать:

powershell -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Web; $server = 'http://website.com/index.php'; foreach ($path in [System.IO.Directory]::EnumerateFiles("C:\path\to\dir","*.xml","AllDirectories")) { try { $oXml = New-Object System.XML.XMLDocument; $oXml.Load($path); <more commands here>;} catch {}}"

А вот ошибки, возвращаемые cmd:

At line:1 char:140
+ ... hp'; foreach ($path in [System.IO.Directory]::EnumerateFiles(C:\path ...
+                                                                  ~
Missing ')' in method call.
At line:1 char:140
+ ... ry]::EnumerateFiles(C:\path\to\dir,*.xml,A ...
+                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'C:\path\to\dir' in expression or statement.
At line:1 char:140
+ ... hp'; foreach ($path in [System.IO.Directory]::EnumerateFiles(C:\path ...
+                                                                  ~
Missing closing ')' after expression part of foreach loop.
At line:1 char:181
+ ... y]::EnumerateFiles(C:\path\to\dir,*.xml,Al ...
+                                                                 ~
Missing argument in parameter list.
At line:1 char:202
+ ... \path\to\dir,*.xml,AllDirectories)) { try  ...
+                                                                 ~
Unexpected token ')' in expression or statement.
At line:1 char:203
+ ... path\to\dir,*.xml,AllDirectories)) { try { ...
+                                                                 ~
Unexpected token ')' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall

Как я могу (должным образом) сжать вышеуказанный скрипт PowerShell в одну строку?

Ответы [ 5 ]

0 голосов
/ 07 января 2019

Я думаю это самый простой и понятный способ, потому что он не требует лишних переключателей; просто простой код PowerShell:

PowerShell  ^
   Add-Type -AssemblyName System.Web;  ^
   $server = \"http://website.com/index.php\";  ^
   foreach ($path in [System.IO.Directory]::EnumerateFiles(\"C:\path\to\dir\",\"*.xml\",\"AllDirectories\")) {  ^
     try {  ^
       $oXml = New-Object System.XML.XMLDocument;  ^
       $oXml.Load($path);  ^
       <more commands here>;  ^
     } catch {}  ^
   }
%End PowerShell%

Просто добавьте ^ в конце каждой строки и экранируйте каждую кавычку обратной косой чертой.

Этот способ гораздо больше читаемый, чем просто очень длинная строка ...

0 голосов
/ 07 января 2019

Ключ должен гарантировать, что вы будете придерживаться двойных кавычек в вашей команде powershell. например.

Powershell.exe -Command "foobar"

Тогда все в вашей команде должно использовать одинарные кавычки. например.

Powershell.exe -Command "Write-Host 'foobar'"

Иногда вам приходится использовать двойные кавычки в одинарных кавычках, поэтому вы можете обойти это, используя escape-символ (\). например.

Powershell.exe -Command "Write-Host \"foobar\""

Или бежать, используя двойные двойные кавычки (""). например.

Powershell.exe -Command "Write-Host ""foobar"""

Наконец, когда вещи в вашей команде становятся хитрыми, вы также можете использовать escape-символ с серьезным акцентом (`). например.

Powershell.exe -Command "Write-Host `'foobar`'"

Надеюсь, это поможет.

0 голосов
/ 07 января 2019

Вы не избегаете своих кавычек в своих строках. Поскольку вы передаете аргумент командной строки в виде строки (то есть в двойных кавычках), как только он попадает в следующую двойную кавычку, он думает, что это конец команды. Из того, что у вас есть, проще всего изменить кавычки внутри команды с одинарными кавычками вместо двойных:

powershell -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Web; $server = 'http://website.com/index.php'; foreach ($path in [System.IO.Directory]::EnumerateFiles('C:\path\to\dir','*.xml','AllDirectories')) { try { $oXml = New-Object System.XML.XMLDocument; $oXml.Load($path); <more commands here>;} catch {}}"

Вы также можете просто использовать двойные двойные кавычки, например:

powershell -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Web; $server = ""http://website.com/index.php""; foreach ($path in [System.IO.Directory]::EnumerateFiles(""C:\path\to\dir"",""*.xml"",""AllDirectories"")) { try { $oXml = New-Object System.XML.XMLDocument; $oXml.Load($path); <more commands here>;} catch {}}"

Есть и другие способы сбежать, но любой из них должен делать то, что вам нужно.

0 голосов
/ 07 января 2019

Николь, у тебя есть два варианта.

Первый похож на технику, которую вы используете сейчас, но замените любые двойные кавычки в сценарии одинарными кавычками. Оберните весь сценарий в двойные кавычки с амперсандом и скобками. Это даст вам что-то вроде этого ...

powershell -ExecutionPolicy Bypass -Command "& {Add-Type -AssemblyName System.Web; $server = 'http://website.com/index.php'; foreach ($path in [System.IO.Directory]::EnumerateFiles('C:\path\to\dir','*.xml','AllDirectories')) { try { $oXml = New-Object System.XML.XMLDocument; $oXml.Load($path); <more commands here>;} catch {}}}"

Ваш второй вариант - закодировать сценарий в base64, чтобы вам не приходилось беспокоиться о том, насколько сложен сценарий. Затем запустите powershell.exe с помощью параметра -EncodedCommand.

Чтобы сделать это, вы сначала должны подготовить скрипт в кодировке base64, как этот

$Script = @'
Add-Type -AssemblyName System.Web;

$server = "http://website.com/index.php";

foreach ($path in [System.IO.Directory]::EnumerateFiles("C:\path\to\dir","*.xml","AllDirectories")) {

  try {
    $oXml = New-Object System.XML.XMLDocument;
    $oXml.Load($path);
    <more commands here>;
  } catch {}

}
'@

$ByteScript  = [System.Text.Encoding]::Unicode.GetBytes($Script)
[System.Convert]::ToBase64String($ByteScript)

Обратите внимание, что ваш настоящий скрипт находится между многострочным строковым литералом с @ 'и' @ в отдельных строках вокруг него. Результатом этой команды является строка вашего сценария в кодировке base64. Теперь вы просто используете это в командной строке

powershell.exe -EncodedCommand "QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBlAGIAOwANAAoADQAKACQAcwBlAHIAdgBlA
HIAIAA9ACAAIgBoAHQAdABwADoALwAvAHcAZQBiAHMAaQB0AGUALgBjAG8AbQAvAGkAbgBkAGUAeAAuAHAAaABwACIAOwANAAoADQAKAGYAbwByAGUAYQ
BjAGgAIAAoACQAcABhAHQAaAAgAGkAbgAgAFsAUwB5AHMAdABlAG0ALgBJAE8ALgBEAGkAcgBlAGMAdABvAHIAeQBdADoAOgBFAG4AdQBtAGUAcgBhAHQ
AZQBGAGkAbABlAHMAKAAiAEMAOgBcAHAAYQB0AGgAXAB0AG8AXABkAGkAcgAiACwAIgAqAC4AeABtAGwAIgAsACIAQQBsAGwARABpAHIAZQBjAHQAbwBy
AGkAZQBzACIAKQApACAAewANAAoADQAKACAAIAB0AHIAeQAgAHsADQAKACAAIAAgACAAJABvAFgAbQBsACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAI
ABTAHkAcwB0AGUAbQAuAFgATQBMAC4AWABNAEwARABvAGMAdQBtAGUAbgB0ADsADQAKACAAIAAgACAAJABvAFgAbQBsAC4ATABvAGEAZAAoACQAcABhAH
QAaAApADsADQAKACAAIAAgACAAPABtAG8AcgBlACAAYwBvAG0AbQBhAG4AZABzACAAaABlAHIAZQA+ADsADQAKACAAIAB9ACAAYwBhAHQAYwBoACAAewB
9AA0ACgANAAoAfQA="

Единственный главный недостаток этого заключается в том, что закодированные Base64 строки больше, чем исходная строка.

0 голосов
/ 07 января 2019

Либо используйте ' вместо ", либо вам нужно экранировать кавычки:

C:\>powershell -Command "echo "Hello, World!"; echo "Hello, World!""
Hello
World!
Hello
World!

Powershell видит это как echo Hello, World!, которое печатает каждое слово в отдельной строке. Теперь мы избегаем цитаты:

C:\>powershell -Command "echo \"Hello, World!\"; echo \"Hello, World!\""
Hello, World!
Hello, World!

Powershell видит это как echo "Hello, World!", что дает вам то, что вы хотите.

Итак, ваша строка становится (разделена для удобства чтения):

powershell -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Web;
    $server = \"http://website.com/index.php\";
    foreach ($path in [System.IO.Directory]::EnumerateFiles(\"C:\path\to\dir\",\"*.xml\",
             \"AllDirectories\")) 
    { try { $oXml = New-Object System.XML.XMLDocument; $oXml.Load($path); <more commands here>;} catch {}}"

Однако в этом случае @ комментарий Дрю, вероятно, является лучшим подходом ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...