Learn Easier Way to Build Command for PowerShell.exe


Summary: Learn how to parse a here-string with Windows PowerShell.

Honorary Scripting Guy, Sean Kearney, is here to show you a neat little trick.

Anyone who has ever scheduled a PowerShell task knows that if you want to launch a cmdlet directly in PowerShell, you would launch it like this:

PowerShell.exe –ExecutionPolicy Bypass –command ‘Get-ChildItem’

No challenge there. It also does not end there. You can add some down-right complex stuff in there, for example:

PowerShell.exe –executionpolicy Bypass –command ‘Set-ExecutionPolicy Bypass;Import-Module DeployImage; New-WindowsPeImage’

This is an example of something I was playing with in the DeployImage module when launching PowerShell automatically.

Then again, in many cases, a script would be much easier to run if you knew where the script actually was. The challenge I ran into was trying to put together really complex command while typing it in the parameter.

Then it dawned on me, “Why not write it as a script to make sure it works?” Yeah, that was pretty obvious. But how would I flip it back to a command for the PowerShell.exe? This is where a here-string is perfect!

Here I have an example of something that I was actually doing. I needed to take the following script and flip it to a command in the PowerShell.exe.

Set-ExecutionPolicy -executionpolicy Bypass

$USBDisk=(Get-Disk | Where-Object { $_.BusType -eq 'USB' -and '$_.IsActive' })

$DriveLetter=($USBDisk | Get-Partition).DriveLetter

Set-Location ($DriveLetter+':\DeployImage\')

Import-Module ($DriveLetter+':\DeployImage\DeployImage.Psd1)'

I then stored it as a here-string:

$PowerShellScript=@'

Set-ExecutionPolicy -executionpolicy Bypass

$USBDisk=(Get-Disk | Where-Object { $_.BusType -eq 'USB' -and '$_.IsActive' })

$DriveLetter=($USBDisk | Get-Partition).DriveLetter

Set-Location ($DriveLetter+':\DeployImage\')

Import-Module ($DriveLetter+':\DeployImage\DeployImage.Psd1)'

'@

Now all we need is to find where each line terminates and switch it with a semicolon.

We can examine each byte in the here-string in the following manner:

[byte][char]($PowerShellScript)[10]

We would eventually notice that two characters at the end of each line are:

  • Ascii 13 (Return)
  • Ascii 10 (Linefeed)

Although we can’t see or type these, we can represent these as a string in the following manner:

$CRLF=[char][byte]13 + [char][byte]10

Armed with this, we can now do something really neat—use the Replace method and switch out each carriage return/linefeed with a semicolon:

$PowerShellCommand=$PowerShellScript.replace($CRLF,’;’)

You can now use this in whatever fashion suits you—even if that means dropping it into the clipboard!

Have fun and enjoy!

I invite you to follow the Scripting Guys on Twitter and Facebook. If you have any questions, send email to them at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, always remember that with great PowerShell comes great responsibility.

Sean Kearney, Honorary Scripting Guy, Cloud and Datacenter Management MVP

Comments (3)

  1. megamorf says:

    Or you just do: $PowerShellScript.Replace("`r`n",";")

  2. Alfie_J says:

    Why not just use PowerShell.exe to call a ps1 script?

  3. @megamorf

    Excellent point! That’s another good option. The reason I opted for the coded version was also to demonstrate how you can build ASCII characters that may not be pre-defined. But it’s good to note that PowerShell has built in "shortcuts" for some of these 🙂

    @alfie_j

    The reason is simple actually. There are some scenarios (like when launching PowerShell.exe from a WindowsPE environment that you may want to launch a mini startup script but may not know the drive letter. Or perhaps you want to keep the file system out of
    this entirely (such as a scheduled task)

    The point is to just show you another option you can leverage in whatever way you like 🙂

    Cheers!
    Sean
    Honorary Scripting Guy

Skip to main content