How to run PowerShell on one line?

2019-07-25 18:33发布

As per this answer, PowerShell statements can be separated with semicolins.

Here's a snippet of the script I'm working with (somewhat redacted for simplification):

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

}

Here's one of my many attempts at condensing it:

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

And here are the errors returned by the 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

How can I (properly) condense the above PowerShell script into one line?

5条回答
beautiful°
2楼-- · 2019-07-25 19:19

You're not escaping your quotes within your strings. Because you're passing the command line argument as a string (i.e., within double quotes), as soon as it hits the next double quote it thinks it's the end of the command. With what you have there, the easiest option is to change the quotes within the command with single quotes instead of double:

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

You could also just use double double quotes, ie:

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

There's other ways to escape as well, but either of those should do what you need.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-07-25 19:20

Either use ' instead of ", or you need to escape the quotes:

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

Powershell sees this as echo Hello, World!, which prints each word on a separate line. Now we escape the quotes:

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

Powershell sees this as echo "Hello, World!", which gives you what you want.

So, your line becomes (split for readability):

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

However, in this case @Drew's comment is probably a better approach...

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-07-25 19:26

The key is to ensure you stick to the double quotes in your powershell command. eg.

Powershell.exe -Command "foobar"

Then everything in your command should use single quotes. eg.

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

Sometimes you end up having to reuse double quotes within your single quotes, and so you can work around this by using either the escape character (\). eg.

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

Or escape using double-double quotes (""). eg.

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

Lastly, when things in your command get tricky, you can also use the grave accent escape character (`). eg.

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

I hope this helps.

查看更多
时光不老,我们不散
5楼-- · 2019-07-25 19:28

I think this is the simplest and clearest way because it don't requires any superfluous switch; just plain PowerShell code:

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%

Just add a ^ at end of each line and escape each quote with backslash.

This way is much more readable than just a very long line...

查看更多
我命由我不由天
6楼-- · 2019-07-25 19:33

Nicole, you have two options here.

First is similar to the technique that you are using now but replace any of the double quotes in the script with single quotes. Wrap the whole script in double quotes with an ampersand and brackets. This would give you something like this...

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

Your second option is to base64 encode the script so you don't have to worry about how complex the script it. Then launch powershell.exe using the -EncodedCommand option.

To do this, you would prepare the base64 encoded script first like this

$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)

Notice that your actual script is between the multiline string literal with @' and '@ on separate lines around it. The output from that command is a base64 encoded string of your script. Now you just use that in your command line

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

The only main drawback to this would be that Base64 Encoded strings are larger than the original string.

查看更多
登录 后发表回答