1

I have a Windows batch file for cmd.exe. It has a single line of code to invoke the PowerShell Send-MailMessage cmdlet and exit back to cmd.exe. Currently the line reads like:

PowerShell -Command "Send-MailMessage -To one.person@somewhere.com, another.person@sameplace.com -Subject 'A rather lengthy text' -From info@my.com -SmtpServer hostname.subdomain.mycompany.com -UseSsl -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'UserName',('SecretePassword1234'|ConvertTo-SecureString -AsPlainText -Force)) -Body 'A static text.'"

It works great. But I find it difficult to edit it in NotePad or any text editor because the line is way too long. What I want is to use the CMD.EXE's caret ^ character to break up the long string within the double quotes into multiple lines. However, the PowerShell.EXE command requires that:

PowerShell -Command <string>

The above syntax requires that CMD.EXE parse everything after -Command to be a SINGLE string, aka a single argument. I've tried the following that didn't work:

PowerShell -Command "Semd-MailMessage Blab Blab " ^
"More Blah Blah"

If I break up the line in my batch file as above, CMD.EXE will parse the first part of the string as one argument, and the string on the next line as another argument. Wrong. So what should I do?

twoleggedhorse
  • 4,938
  • 4
  • 23
  • 38
  • Have you tried turning on line-wrap? Also I find that a program such as Notepad++ gives you syntax highlighting and is very useful for this sort of thing... – twoleggedhorse Sep 22 '17 at 20:49
  • Both your lines start and end with double quotes. Seems like you would only want your first line to start with a double quote and your last line to end with a double quote. – Squashman Sep 22 '17 at 20:51
  • I'm pretty sure that PowerShell uses a ` (back tick) rather than the ^ up arrow of cmd – twoleggedhorse Sep 22 '17 at 20:52
  • You could also create a .ps1 file and simply run that from cmd. Then you have the luxury of being inside Powershell rather than a single line in cmd – twoleggedhorse Sep 22 '17 at 20:55
  • @Squashman: I also tried the following: PowerShell -Command "Send-MailMessage -To one.person@somewhere.com ^ -Subject 'A rather lengthy text' -From info@my.com -SmtpServer hostname.subdomain.mycompany.com -UseSsl ^ -Credential (New-Object -TypeName System.Management.Automation.PSCredential ^ -ArgumentList 'UserName',('SecretePassword1234'|ConvertTo-SecureString -AsPlainText -Force)) ^ -Body 'A static text.'" And I got inside the PowerShell and I got the prompt: cmdlet Send-MailMessage at command pipeline position 1 Supply values for the following parameters: From: – Gardner W. Hui Sep 22 '17 at 21:04
  • I would agree with @twoleggedhorse. Write it all in the .ps1 file and use the backtick as the line continuation. Then execute the .ps1 file from your batch file. – Squashman Sep 22 '17 at 21:04
  • Would you not concatenate the two double quoted strings with **`+`** before using `cmd.exe`'s **`^`** concatenation character. As another option, you could use `Set` to build your long line, and use the variable, _although you may need to be creative with escape characters too_. – Compo Sep 22 '17 at 21:10
  • Why? Don't use cmd.exe at all and just use PowerShell directly. – Bill_Stewart Sep 22 '17 at 21:15
  • @GardnerW.Hui, do not put that much code in a comment. – Squashman Sep 22 '17 at 21:22

4 Answers4

2

I would put your command into a powershell script and then call that from cmd using the following command (or something similar):

powershell.exe -noprofile -executionpolicy bypass -file "path to my file.ps1"

then your editing can all happen inside the powershell ide and you can split your command up as required; either by using variables and/or by using the ` (back tick) character. Your Powershell script could then look like the following with is a lot easier to manage; plus you get the benefit of intellisense as you edit the script:

Send-MailMessage `
-To one.person@somewhere.com, another.person@sameplace.com `
-Subject 'A rather lengthy text' `
-From info@my.com `
-SmtpServer hostname.subdomain.mycompany.com `
-UseSsl `
-Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'UserName', ('SecretePassword1234'|ConvertTo-SecureString -AsPlainText -Force)) `
-Body 'A static text.'
twoleggedhorse
  • 4,938
  • 4
  • 23
  • 38
  • 1
    I'd use [splatting](https://blogs.technet.microsoft.com/heyscriptingguy/2010/10/18/use-splatting-to-simplify-your-powershell-scripts/) to ease building the command. –  Sep 22 '17 at 21:27
2

I can agree as you've indicated that this doesn't work:

PowerShell -Command "Semd-MailMessage Blab Blab " ^
"More Blah Blah"

…and also agree that this doesn't either:

@Echo Off
PowerShell -Command "Get-WmiObject -Class Win32_Product "^
"| Select-Object -Property Name | Sort-Object Name"
Pause

However this does:

@Echo Off
PowerShell -Command "Get-WmiObject -Class Win32_Product "^
 "| Select-Object -Property Name | Sort-Object Name"
Pause

…note the very small but seemingly very important single space at the beginning of the continuation line!

Compo
  • 36,585
  • 5
  • 27
  • 39
2

I think this is the simplest and clearest way to solve this problem because this method does not require additional files nor additional options, just plain PowerShell code:

PowerShell  ^
   Send-MailMessage  ^
      -To one.person@somewhere.com, another.person@sameplace.com  ^
      -Subject 'A rather lengthy text'  ^
      -From info@my.com  ^
      -SmtpServer hostname.subdomain.mycompany.com  ^
      -UseSsl  ^
      -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'UserName',('SecretePassword1234'^|ConvertTo-SecureString -AsPlainText -Force))  ^
      -Body 'A static text.'

Just be sure to properly escape special Batch characters, like ^|.

Aacini
  • 65,180
  • 12
  • 72
  • 108
0

You either set variables in a batch file or you can do something completely hokey like this.

@echo off

setlocal enabledelayedexpansion
set "pscommand="
FOR %%G IN (
            "Send-MailMessage -To one.person@somewhere.com, "
            "another.person@sameplace.com "
            "-Subject 'A rather lengthy text' "
            "-From info@my.com "
            "-SmtpServer hostname.subdomain.mycompany.com "
            "-UseSsl -Credential "
            "(New-Object -TypeName System.Management.Automation.PSCredential "
            "-ArgumentList 'UserName',('SecretePassword1234'|ConvertTo-SecureString -AsPlainText -Force)) "
            "-Body 'A static text.'"
            ) DO (
                set "pscommand=!pscommand!%%~G"
            )

PowerShell -Command "%pscommand%"
Squashman
  • 13,649
  • 5
  • 27
  • 36