如何在一行上运行PowerShell?

时间:2019-01-06 23:40:35

标签: powershell batch-file cmd

根据this answer,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 :(得分:4)

Nicole,您在这里有两个选择。

首先类似于您现在使用的技术,但是用单引号替换脚本中的任何双引号。将整个脚本用与号和方括号括在双引号中。这会给你这样的东西...

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编码,因此您不必担心脚本的复杂程度。然后使用-EncodedCommand选项启动powershell.exe。

为此,您首先需要像这样准备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编码的字符串大于原始字符串。

答案 1 :(得分:1)

使用"代替C:\>powershell -Command "echo "Hello, World!"; echo "Hello, World!"" Hello World! Hello World! ,或者您需要转义引号:

echo Hello, World!

Powershell将其视为C:\>powershell -Command "echo \"Hello, World!\"; echo \"Hello, World!\"" Hello, World! Hello, World! ,它将每个单词打印在单独的行上。现在我们转义引号:

echo "Hello, World!"

Powershell将其视为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 {}}" ,这将为您提供所需的内容。

因此,您的行变成了(为了便于阅读):

Failed to convert object of type <class 'dict'> to Tensor.

但是,在这种情况下,@ Drew的评论可能是一种更好的方法...

答案 2 :(得分:1)

您没有在字符串中转义引号。因为您要以字符串形式传递命令行参数(即,双引号内),所以只要它命中下一个双引号,它就会认为这是命令的结尾。有了您所拥有的,最简单的选择是在命令中用单引号而不是双引号将引号更改:

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 {}}"

还有其他逃生方式,但是其中任何一种都可以满足您的需求。

答案 3 :(得分:1)

关键是确保您在powershell命令中坚持双引号。例如。

Powershell.exe -Command "foobar"

然后,命令中的所有内容都应使用单引号。例如。

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

有时您最终不得不在单引号内重用双引号,因此可以通过使用转义符(\)来解决此问题。例如。

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

或者使用双引号(“”)进行转义。例如。

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

最后,当命令中的内容变得棘手时,您还可以使用重音符转义符(`)。例如。

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

我希望这会有所帮助。

答案 4 :(得分:1)

我认为this is是最简单,最清晰的方法,因为它不需要任何多余的切换;只是普通的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%

只需在每行末尾添加一个^,并用反斜杠将每个引号转义。

这种方式比很长的一行更具可读性 ...