My Task Scheduler calls a Powershell script that starts a SAS program, which in turn executes a Windows command using %sysexec (and does a lot of other stuff on the side).
When I run the Powershell script interactively or start it manually in the Task Scheduler, the %sysexec command is executed correctly in the SAS program.
If the Powershell script is not started interactively by the Task Scheduler and I am not logged in on the computer, the %sysexec command is not executed. Nevertheless, it returns sysrc=0 as a result (success).
On the old machine with Windows Server 2012 it worked, on the new machine with Windows 2019 it does not.
I have written a highly simplified example here.
Task Scheduler Action:
powershell -executionpolicy bypass "C:\temp\test_sas.ps1"
Powershell Script test_sas.ps1:
$sasrootdirStr = "D:\sas\SASHome\SASFoundation\9.4"
$pgmdirStr = "C:\temp"
$pgmnameStr= "test_sas"
$logdirStr = "C:\temp"
$logfileStr = $logdirStr + "\" + $pgmnameStr + ".log"
& "$sasrootdirStr\sas.exe" "$pgmdirStr\$pgmnameStr.sas" -log "$logfileStr"
SAS program test_sas.sas:
%macro test_sas;
%local macroname;
%let macroname= test_sas;
%let newdir = %str(C:\temp\martin);
%let sysrc = -1;
%sysexec "mkdir" &newdir..;
%if &sysrc ne 0 %then %do;
%put ERROR: ¯oname: Could not execute command mkdir (sysrc: &sysrc.).;
%end;
%put sysrc: &sysrc;
%mend test_sas;
%test_sas;
Result in logfile test_sas.log (the %sysexec command mkdir was not executed):
sysrc: 0
NOTE: SAS Institute Inc, SAS Campus Drive, Cary, NC USA 27513-2414
NOTE: The SAS System used:
real time 0.60 seconds
cpu time 0.68 seconds
Used software versions:
new (with error):
SAS 9.04.01M7P080520
Windows Server 2019 Standard Version 1809
Powershell 5.1.17763.2931
old (without errors):
SAS 9.04.01M4P110916
Windows Server 2012 R2 Standard
Powershell 4.0
What is wrong?
data _null_; infile "mkdir ""&newdir""" pipe; input; put _infile_; run;
works. But the result code of the datastep is always zero (syserr=0, success), even if the windows command could not be successfully executed.
How can I get a useful return value from the command executed in the pipe? I really need this one.
The following code for the powershell script works.
Instead of using the call operator (&), I can use the start-process comandlet. The %sysexec command in the child SAS program will then execute correctly under all circumstances, even if it is triggered in a task scheduler action.
Powershell script test_sas.ps1:
$process = (Start-Process -FilePath "$sasrootdirStr\sas.exe" -ArgumentList "`"$pgmdirStr\$pgmnameStr.sas`" -log `"$logfileStr`"" -PassThru -Wait)
Write-Host "Process terminated with return code: " $process.ExitCode
Related
I have windows 2012 server with LSI Megaraid controller. I am able to get raid status using below command in powershell and redirect output to a file.
C:\> MegaCli64.exe -LDInfo -Lall -aALL | Out-File raid.txt
However I tried to run same command using task scheduler and it is not working. I want to send the output of raid command or send raid.txt to a mail using task scheduler.
Some piece of advise for sceduled jobs :
1) Always set the working directory if you work with local files.
2) Always use the full path (not the relative one) for the programs you call and the files you manipulate. Do not expect the exe you call being in the paths pointed by $env:path.
3) Put your commands into a script file and make sure that a log (any type), with a time stamp, is composed each time your script is called.
4) Here is one way, but it exits multiples ways, to register your script in the scheduler :
# First set a Trigger
$SixInTheMorning = New-JobTrigger -Daily -At "06:00 AM"
# Second set your script
$scriptPath1 = 'C:\Batchs\WS_PowerShell\Myscript.PS1'
# Third register you job
Register-ScheduledJob -Name "AJobName" -FilePath $scriptPath1 -Trigger $scriptPath1
I have a batch file structured like below:
cd "C:\my\scripts\directory
powershell -f myPowershellSCript.ps1
exit %errorlevel%
This batch file is being sent through an in house remote shell application (which is mostly a black box to me) in a non-interactive way to another machine to be run. I can execute the application and watch it's output on the terminal locally. The script is completing the powershell script and then just dropping back to the remote shell on the test machine without ever running the last line in the batch file. I see the cmd.exe shell drop back to a prompt at C:\my\scripts\directory on the remote machine and just wait. Because it's non-interactive the script never completes.
I'd like to tag that last exit line onto the end of the line that calls powershell, but everything I've tried (below) has not worked. I fear that powershell is taking everything as input instead of batch interpreting them as two separate commands.
powershell -f SecurePaymentsTestLauncher.ps1 && exit 1
powershell -nonInteractive -f SecurePaymentsTestLauncher.ps1 && exit 1
powershell -nonInteractive -command "& 'SecurePaymentsTestLauncher.ps1'" && exit 1
powershell -nonInteractive -command "& 'SecurePaymentsTestLauncher.ps1'" ; exit 1
powershell -nonInteractive -f SecurePaymentsTestLauncher.ps1 ; exit 1
still produces the same result. No return from the remote execution.
How do I append a second command to a batch file line when the first command is a call to powershell?
Is your PowerShell process exiting status 0? The && conditional operator only executes the command it precedes when the command it follows exits 0. If you want to exit 1 regardless of whether PowerShell exits zero or non-zero, use a single &.
In your powershell command, you might also need to call the .ps1 script name as .\SecurePaymentsTestLauncher.ps1 and add the -ExecutionPolicy RemoteSigned arguments.
Try
cd "C:\my\scripts\directory"
start powershell -f myPowershellSCript.ps1
exit %errorlevel%
Using 'start' in front of powershell instantiates a separate powershell host outside of the batch script host, which will allow your ps1 file to do its thing while your batch script goes straight to 'exit %errorlevel%'
I have windows server 2012 R2 , and i have defined a task inside windows task scheduler, as follow:-
-i create a .ps file, which mainly calls a remote URL:-
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$request = [System.Net.WebRequest]::Create("https://ipAddress/")
$response = $request.GetResponse()
$response.Close()
-then i create a .bat file to call the power-shell script, as follow:-
"%SYSTEMROOT%\system32\windowspowershell\v1.0\powershell.exe" -Command Start-Process "$PSHOME\powershell.exe" -Verb RunAs -ArgumentList "'-NoExit %~dp0\AppPoolActivation.ps1'"
-i define the task to run daily on each 30 minutes for a duration of day.
-the task will be calling the .bat file.
now i am facing a problem is that when the task runs successfully, two processes will keep running 1)Windows Power Shell & 2)Console Windows host. which will cause my server to became very slow and will stop responding after around 12 hours,, now here is how my task manager will looks like when the task runs for around 5 times-
where many instances of Windows Power Shell & Console Windows host are running,, so can anyone adivce on this please ? i though the related processes will end as soon as the windows task ends..
-NoExit means no exit... So if you want it to close after the script is executed, then don't use it.
I'm writing a script that normally will get called by another application (VMware vCenter Server). From that application I trigger a batch file (redirect.bat) and pass a variable which is the powershell script name (TestMe.ps1).
The script is placed on a Windows Server and when I go into the command prompt of the Windows Server and call the redirect script, I see that my PowerShell script runs as expected. However when I trigger it from the app the Powershell script is not run or doesn't produce output. I have confirmation that the redirect.bat is run, because the redirect.bat writes a line in a log file.
The vCenter Server app is running under Local System account. Could it be a permissions error? Is LocalSystem allowed to run Powershell scripts?
I now have no clue if the Powershell script even starts, because it (of course) is not visible in my console when running. The batch file always returns errorlevel = 0.
Any tips on how to insert debugging info in the script that should always give output? Tips on how to troubleshoot this?
redirect.bat:
set POWERSHELL=C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -nologo -noprofile -noninteractive
SET ERRORLEVEL =
echo %1 > G:\DataStoreAlarms\Log\Redirect-batch.txt
start %POWERSHELL% -command "&"%1""
echo Error level: %ERRORLEVEL% >> G:\DataStoreAlarms\Log\Redirect-batch.txt
I call redirect.bat from the command line and from the app like this:
redirect.bat G:\DataStoreAlarms\Scripts\TestGabrie.ps1
TestGabrie.ps1:
$String = "This is a test"
$String | Out-File -FilePath "G:\DataStoreAlarms\Log\Powershell.txt" -Append
Regards
Gabrie
Problem seemed to be the START command:
start %POWERSHELL% -command "&"%1""
After changing it to this, it worked:
%POWERSHELL% -command "&"%1""
Thanks for all your help.
In Windows I have console programs that run in the background with the console hidden. Is there anyway to direct input to the programs console? I want to be able to do something like:
echo Y| *the_running_process_here*
to send Y to the process' stdin.
As far as I know this is not possible by basic cmd commands. PowerShell is more powerful though and can use the .NET framework from windows.
I found this PowerShell script which claims to pass text to an already opened cmd:
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "cmd.exe"; #process file
$psi.UseShellExecute = $false; #start the process from it's own executable file
$psi.RedirectStandardInput = $true; #enable the process to read from standard input
$p = [System.Diagnostics.Process]::Start($psi);
Start-Sleep -s 2 #wait 2 seconds so that the process can be up and running
$p.StandardInput.WriteLine("dir"); #StandardInput property of the Process is a .NET StreamWriter object
Source: https://stackoverflow.com/a/16100200/10588376
You would have to safe this script with an .ps1 ending and run it.
A workaround to use this as a cmd command would be to make it accept arguments, so that you can run it with yourScript.ps1 procced_pid arguments for example.
The standard windows cmd is just too limited to fullfill such a task by its own.