How to pass parameters to PowerShell script from batch file? - powershell

This should be an easy syntax fix, I just could not wrap my mind around all the google searching suggestions.
The ps1 script does work when invoked from PowerShell terminal, I can pass all three parameters and receive the email.
When trying to run it from a batch file (cmd)
ShellScript:
# get parameters
[CmdletBinding()]
param(
$recipients,
$subject,
$body
)
#$ParamSetName = $PsCmdLet.ParameterSetName
# send email
Send-MailMessage -From "noreply#snorepl.com" -To $recipients -Subject $subject -SmtpServer 'somesmtpserver.somedomain.com' -BODY $body
Batch script:
powershell.exe -ExecutionPolicy Bypass -command "C:\scripts\send_email.ps1 -recipients '%recipients%' -subject '%subject%' -body '%body%'"
When calling the bath script I get the following error:
The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx ception
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

Why not use the -File parameter?
powershell -ExecutionPolicy Bypass -File C:\Scripts\send_email.ps1 -Recipients '%recipients%' -Subject '%subject%' -Body '%body%'
(Aside: If you insist on -Command, why do you need the script? Just run Send-MailMessage directly.)

Related

Saving powershell command output into a file

I want to save the following powershell command into a file.ps1 from cmd:
powershell send-mailmessage -to "alerts#address.com" -from "info#address.com" -subject "Virus alert" -body "Cryptolocker variant detected on $env:computername " -smtp "companyname-com.mail.protection.outlook.com"
How can I do that?
try this:
echo <your_command> > file.ps1
echo prints whatever you give it (in this case your command) to the standard output (usually the console) and > redirects the string (your command) from the standard output to the file file.ps1
This can be written to a file by redirecting stdout of the ECHO command.
ECHO>file.ps1 powershell send-mailmessage ^
-to "alerts#address.com" ^
-from "info#address.com" ^
-subject "Virus alert" ^
-body "Cryptolocker variant detected on $env:computername " ^
-smtp "companyname-com.mail.protection.outlook.com"
If you are writing to a .ps1 file, why do you need to start another instance of PowerShell? To run the PowerShell script, leave the powershell command out and just use:
powershell -NoLogo -NoProfile -File file.ps1

$Env:ComputerName doesnt work with powershell Send-MailMessage in batch file

After a lot of errors and edits I got the Send-MailMessage to work through a command prompt. Below iteration sends out the emails perfect.
powershell Send-MailMessage -From " `<user#domain>`" -To " `<user#domain.com>`" -Subject 'Some subject goes here' -Body 'Some body with alert regarding Host: $env:computername. List of deleted files is attached.' -Attachments 'C:\somefile.txt' -Priority High -dno onSuccess, onFailure -SmtpServer 'smtp.domain.com'
However, this does not fetch the computername in the body. I have tried running this command in powershell directly and it works with the computername variable in body.
To get it to simply send out mails, I have already tried doing
powershell -command "command" or powershell -command "{command} or
powershell -command "& {command}" and so on and it doesnt even send
out emails.
As I am now successful sending out emails, I need to have the Computername inside the body text.
Use double quotes around the argument value to have variables contained expanded.
I.e.:
-Body "Some body with alert regarding Host: **$env:computername**. ..."
Relevant reading.
Your command line in the question and your own answer relies on the fact that powershell currently has the default (position 0) argument -Command,
but as this changes from PowerShell 6.0.0beta3 on to -File
you should explicitly use at least -C as the shortest
abbreviviation for -Command.
to speed up execution I'd use the additionl parameters -NoProfile or short -NoP and -NonInteractive or -NonI
to stop cmd from trying to interpret any parameters/arguments you should double quote them all - and escape any necessary inner double quotes with a backslash \" while also replacing double quotes with single ones if ever possible.
So I'd suggest:
powershell -NoP -NonI -C "Send-MailMessage -From \"SomeWeb-Prod#domain.com\" -To \"fromuser#domain.com\" -Subject 'Some notification for SomeWeb-Prod' -Body 'Some Alert for Host: %computername% with IP: %NetworkIP% at %time%. details in attached file.' -Attachments 'C:\somefile.txt' -Priority High -dno onFailure -SmtpServer 'smtp.domain.com'"
Or, (as you partly discovered yourself):
powershell -NoP -NonI -C "Send-MailMessage -From 'SomeWeb-Prod#domain.com' -To 'fromuser#domain.com' -Subject 'Some notification for SomeWeb-Prod' -Body 'Some Alert for Host: %computername% with IP: %NetworkIP% at %time%. details in attached file.' -Attachments 'C:\somefile.txt' -Priority High -dno onFailure -SmtpServer 'smtp.domain.com'"
"$env:computername" doesnot work for me. It simply prints it as $env:computername
%computername% worked.
Here's what's working for me right now.
powershell Send-MailMessage -From " `<user#domain.com>`" -To " `<user#domain.com>`" -Subject 'Some subject goes here' -Body 'Some body with alert regarding Host: %computername%. Some file is attached.' -Attachments 'C:\somefile.txt' -Priority High -dno onSuccess, onFailure -SmtpServer 'smtp.domain.com'
Update:
The above command worked on Win7 fine, but gave errors on server 2012. Finally this is what worked on win 2012
powershell "Send-MailMessage -From "SomeWeb-Prod#domain.com" -To "fromuser#domain.com" -Subject 'Some notification for SomeWeb-Prod' -Body 'Some Alert for Host: %computername% with IP: %NetworkIP% at %time%. details in attached file.' -Attachments 'C:\somefile.txt' -Priority High -dno onFailure -SmtpServer 'smtp.domain.com'"
It works for me, by using double quotes around variables.
I am using batch script to call powershell Send-MailMessage
Batch Script:send_email.bat
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -command 'E:\path\send_email.ps1
Pwershell Script send_email.ps1
Send-MailMessage -From "noreply#$env:computername" -To '<target_email#example.com>' -Subject 'Blah Blah' -SmtpServer 'smtp.domain.com' -Attachments 'E:\path\file.log' -BODY "Blah Blah on Host: $env:computername "

Send-MailMessage - from parameter error?

I'm trying to send a mail using PowerShell with below command:
powershell -command "& {Send-MailMessage -To "xxxxx#xx.com" -From "xxxx#domain.com" -SMTPServer xxx.xx.com -Subject "report" -Body "service is running"}"
but I'm getting this error:
Send-MailMessage : A positional parameter cannot be found that accepts argument
'xxx#xx.com'.
At line:1 char:20
+ & {Send-MailMessage <<<< -To "xxx#xx.com -From "xxx#xx.com -SMTPServer xxxx.xx.com -Subject "Daily report" -Body "service is running"}
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SendMailMessage
As others have already mentioned, your quoting is broken. You're trying to nest double quotes inside a double-quoted string without escaping them. The unescaped nested double quotes prematurely terminate your string, causing the error you observed.
The simplest fix for this problem is to replace the nested double quotes with single quotes, since you don't seem to be using variables in that command anyway:
powershell.exe -Command "& {Send-MailMessage -To 'xxxxx#xx.com' -From ..."
If you want to keep using nested double quotes (e.g. because you have variables in your scriptblock, which wouldn't be expanded in single-quoted strings) you need to escape them. If you're running the command from outside PowerShell (e.g. from CMD) you can do so by using backslashes:
powershell.exe -Command "& {Send-MailMessage -To \"xxxxx#xx.com\" -From ..."
If you're running the command from within PowerShell you need to escape the nested double quotes twice (once for PowerShell when it's parsing the commandline, and once for the actual command invocation):
powershell.exe -Command "& {Send-MailMessage -To \`"xxxxx#xx.com\`" -From ..."
However, if you're actually running it from PowerShell you don't need the powershell.exe -Command in the first place. Just invoke Send-MailMessage directly:
Send-MailMessage -To "xxxxx#xx.com" -From ...

PSSessionStateBroken with start-job -credential in scheduled task

The lines below work fine from a Powershell prompt, but fail from a scheduled task.
$pass = gc C:\secrets\shhh.txt | convertTo-secureString
$Cred = new-object -typeName System.management.automation.psCredential -argumentlist "domain\domainUser",$pass
$path = "\\server\share\folder"
$j = start-job {gci -path $args[0]} -cred $Cred -argumentList $path | wait-job | receive-job
$body = $j | out-string
$error | out-file C:\temp\err.txt
send-mailMessage -to me#domain.tld -from server#domain.tld -subject halp -smtpserver mailserver.domain.tld -body $body
In c:\temp\err.txt the Windows 2008R2 Scheduled Task leaves a breadcrumb:
[localhost] The background process exited abnormally.
+ CategoryInfo : OpenError: (localhost:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : 2101,PSSessionStateBroken
...which brings us to this Microsoft bug report. The report mentions a workaround with localhost loopback remoting, which sounds kinda dirty. Should I go there?
Is there a better solution? Maybe with one of the *session cmdlets or invoke-command? The scheduled task's Start in value is set, but maybe the background process uses some variable in some bad way, like so?
No luck yet calling powershell.exe with –version 2 or with -command "& {bigKlugeyScriptblock}" syntax.
edit: I'm trying to avoid creating a new domain account to run the task. The task can't run as domainUser from $cred, because that account should not have permissions on localhost.
As some possible work arounds how about:
Put alternate credentials on the scheduled task itself
Using the runas command to start powershell.exe as a different user
Using net use /user parameter to authenticate access to the network path
[/USER:[dotted domain name\]username]
[/USER:[username#dotted domain name]

Send-MailMessage parameter from command prompt

I'm trying to run Send-MailMessage directly from a command window.
C:\>powershell Send-MailMessage -from 'test#test.com' -to "target#test.com" -subject 'test' -smtpServer "srv.server.com" -Attachment c:\Test\log.txt -body "Test message"
This fails with
Send-MailMessage : A positional parameter cannot be found that accepts argument 'from'.
I'm sure it's possible. I just dont know how to pass the arguments correctly.
If you're running this from cmd.exe then you need to check out the PowerShell.exe help:
C:\> poweshell.exe /?
Specifically you should invoke the command like so:
C:\> powershell -command "& {Send-MailMessage -from 'test#test.com' ... }"
Watch out for the quote characters. In general use double quotes around the whole -command parameter value for cmd.exe interpret. Inside the command use single quoted strings unless you need variable expansion inside the string.