ChatGPT解决这个技术问题 Extra ChatGPT

How to split long commands over multiple lines in PowerShell

How do you take a command like the following in PowerShell and split it across multiple lines?

&"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -verb:sync -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" -dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"

M
Myrddin Emrys

Trailing backtick character, i.e.,

&"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" `
-verb:sync `
-source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" `
-dest:contentPath="c:\websites\xxx\wwwroot,computerName=192.168.1.1,username=administrator,password=xxx"

White space matters. The required format is Space`Enter.


This seems to break command history (up arrow) functionality; as each line shows up as a separate command. Is there a way around this?
If you're running powershell 3 or higher, see github.com/lzybkr/psreadline - history traversal is fixed for multiline statements.
The space in front of the back-tick is required #learned-the-hard-way
@josh-graham And there should NOT be any space (or inline comment) AFTER the back-tick. #learned-the-hard-way
Backticks are brittle (as above comments state) and hard to find when parsing or reviewing a file. @StevenPenny 's answer is better if you want easier to debug code.
s
spottedmahn

Another method for cleaner argument passing would be splatting.

Define your parameters and values as a hashtable like this:

$params = @{ 'class' = 'Win32_BIOS';
             'computername'='SERVER-R2';
             'filter'='drivetype=3';
             'credential'='Administrator' }

And then call your commandlet like this:

Get-WmiObject @params

Microsoft Docs: About Splatting

TechNet Magazine 2011: Windows PowerShell: Splatting

Looks like it works with Powershell 2.0 and up


This is wonderful! AND you can add parameters like this: $params.add('name','Bob Newhart') ramblingcookiemonster.wordpress.com/2014/12/01/…
The semicolons are ok but superfluous. Only required if there are multiple values per line.
This doesn't work for normal shell command, mainly for PowerShell commandlets
This should be the new accepted answer. Splatting is a very standard thing to do nowadays.
P
Peter Mortensen

Ah, and if you have a very long string that you want to break up, say of HTML, you can do it by putting a @ on each side of the outer " - like this:

$mystring = @"
Bob
went
to town
to buy
a fat
pig.
"@

You get exactly this:

Bob
went
to town
to buy
a fat
pig.

And if you are using Notepad++, it will even highlight correctly as a string block.

Now, if you wanted that string to contain double quotes, too, just add them in, like this:

$myvar = "Site"
$mystring = @"
<a href="http://somewhere.com/somelocation">
Bob's $myvar
</a>
"@

You would get exactly this:

<a href="http://somewhere.com/somelocation">
Bob's Site
</a>

However, if you use double-quotes in that @-string like that, Notepad++ doesn't realize that and will switch out the syntax colouring as if it were not quoted or quoted, depending on the case.

And what's better is this: anywhere you insert a $variable, it DOES get interpreted! (If you need the dollar sign in the text, you escape it with a tick mark like this: ``$not-a-variable`.)

NOTICE! If you don't put the final "@ at the very start of the line, it will fail. It took me an hour to figure out that I could not indent that in my code!

Here is MSDN on the subject: Using Windows PowerShell “Here-Strings”


Neat trick, though if I have a variable $... it seems to not work. I get "the character is not allowed after a here string header..."
I don't think you can break a variable name, just a string.
A
Aaron Jensen

You can use the backtick operator:

& "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" `
    -verb:sync `
    -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" `
    -dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"

That's still a little too long for my taste, so I'd use some well-named variables:

$msdeployPath = "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
$verbArg = '-verb:sync'
$sourceArg = '-source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web"'
$destArg = '-dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"'

& $msdeployPath $verbArg $sourceArg $destArg

I like variable names over other suggestions because it's possibly the most readable option for non powershell experts. If I saw a tutorial/set-up guide that used splatting I would be totally lost at what is going on without a sub-tutorial on splatting. Likewise, backticks seem fragile and probably less well known than simple tried and true PS variables.
P
Peter Mortensen

If you have a function:

$function:foo | % Invoke @(
  'bar'
  'directory'
  $true
)

If you have a cmdlet:

[PSCustomObject] @{
  Path  = 'bar'
  Type  = 'directory'
  Force = $true
} | New-Item

If you have an application:

{foo.exe @Args} | % Invoke @(
  'bar'
  'directory'
  $true
)

Or

icm {foo.exe @Args} -Args @(
  'bar'
  'directory'
  $true
)

K
Kirill Yunussov

Another way to break a string across multiple lines is to put an empty expression in the middle of the string, and break it across lines:

sample string:

"stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow"

broken across lines:

"stackoverflow stackoverflow $(
)stackoverflow stack$(
)overflow stackoverflow"

B
Bad

In PowerShell 5 and PowerShell 5 ISE, it is also possible to use just Shift + Enter for multiline editing (instead of standard backticks ` at the end of each line):

PS> &"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" # Shift+Enter
>>> -verb:sync # Shift+Enter
>>> -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" # Shift+Enter
>>> -dest:contentPath="c:\websites\xxx\wwwroot,computerName=192.168.1.1,username=administrator,password=xxx"

M
Mark

Splat Method with Calculations

If you choose splat method, beware calculations that are made using other parameters. In practice, sometimes I have to set variables first then create the hash table. Also, the format doesn't require single quotes around the key value or the semi-colon (as mentioned above).

Example of a call to a function that creates an Excel spreadsheet

$title = "Cut-off File Processing on $start_date_long_str"
$title_row = 1
$header_row = 2
$data_row_start = 3
$data_row_end = $($data_row_start + $($file_info_array.Count) - 1)

# use parameter hash table to make code more readable
$params = @{
    title = $title
    title_row = $title_row
    header_row = $header_row
    data_row_start = $data_row_start
    data_row_end = $data_row_end
}
$xl_wksht = Create-Excel-Spreadsheet @params

Note: The file array contains information that will affect how the spreadsheet is populated.