Liturgist Liturgist - 3 months ago 9
PowerShell Question

Error quoting and/or escaping, cmd running Powershell

I am missing something when I try to convert the following single line command into multiple lines. I searched, found, and tried to model this change after Powershell -Command over multiple line

What am I missing? I have tried to make it easy to test. Just change the first two (2) lines to something appropriate for your system.

=== emailtest.bat

@ECHO OFF
SET "RECIPIENT=me@nowhere.org"
SET "SMTPHOST=imr2.nowhere.org"
SET "FN=C:\Windows\win.ini"
@ECHO ON

powershell -Command "& send-mailmessage -to "%RECIPIENT%" -from 'noreply@nowhere.org' -subject 'test file transfer' -SmtpServer '%SMTPHOST%' -BodyAsHTML 'The file is <a href="%FN">here</a> for you.'

powershell -noprofile -Command "&{"^
send-mailmessage -to "%RECIPIENT%" ^
-from 'noreply@nowhere.org' ^
-subject 'test file transfer' ^
-SmtpServer '%SMTPHOST%' ^
-BodyAsHTML 'The file is <a href="%FN%">here</a> for you.'^
"}"


=== The output is

C:>call emailtest.bat

12:17:24.75 C:\Users\me\t
C:>powershell -Command "& send-mailmessage -to "me@nowhere.org" -from 'noreply@nowhere.org' -subject 'test file transfer' -SmtpServer 'imr2.nowhere.org' -BodyAsHTML 'The file is <a href="C:\Windows\win.ini">here</a> for you.'

12:17:27.28 C:\Users\me\t
C:>powershell -noprofile -Command "&{" send-mailmessage -to "me@nowhere.org" -from 'noreply@nowhere.org' -subject 'test file transfer' -SmtpServer 'imr2.nowhere.org' -BodyAsHTML 'The file is href="C:\Windows\win.ini""}" 0</a 1>for
The system cannot find the file specified.

Answer

I believe the example only works because it's still multiple commands per line. If you try to do one command on multiple lines then you start to need to escape them in powershell as well, here is a better solution using splatting.

powershell -NoProfile -Command "&{" ^
    "$message = @{};" ^
    "$message.Subject = 'test file transfer';" ^
    "$message.From = 'noreply@nowhere.org';" ^
    "$message.To = '%RECIPIENT%';" ^
    "$message.SmtpServer = '%SMTPHOST%';" ^
    "$message.Body = 'The file is <a href="%FN%">here</a> for you.';" ^
    "$message.BodyAsHTML = $true; " ^
    "Send-MailMessage @message" ^
}"

That being said, you should consider making this a ps1 file if at all possible. Readability is far from great. Also BodyAsHTML is a flag. You still need to set the body. Your code will still technically work as Body is a positional parameter, just clarifying why it was added in the splat.