Hi Don,
Thanks for the reply. Â Much appreciated.
I’ve worked this one out, at least for my environment. The solution is somewhat JAMS specific, but I thought I’d share for the sake of completeness to this thread. Â Perhaps someone Googling for this same issue someday will hit this thread.
First of all, JAMS has a custom Powershell host which it uses to launch Powershell jobs. It also uses a concept called an execution method to determine how to launch the job. Â Since my job is just a Powershell script invoking SAS, I’ve cloned the standard Powershell execution method for my SAS jobs. Â I’ve done this instead of using the default Powershell execution method since I have to do some return code fiddling so that a SAS warning (non-zero return code) is not treated as an error and stop the downstream jobs from executing.
Here is some output from a simple JAMS job echoing the $host object:
Source Code:
$host | Format-List *
if ($host.Name -eq "JAMSHost") {
"This job <<JAMS.Jobname>> is running under JAMS."
}
And the Output in the JAMS log:
Name : JAMSHost
Version : 4.3.1.0
InstanceId : ab689a2e-3b18-42b9-92e0-d19826aedaad
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-AU
CurrentUICulture : en-US
PrivateData : MVPSI.JAMS.Host.PowerShell.JAMSHostInfo
IsRunspacePushed :
Runspace :
This job _WriteVariables is running under JAMS.
So, in my script, I could do this check on the $host.Name property, and conditionally execute $host.SetShouldExit($lastexitcode) for JAMS submitted jobs only.
However, a JAMS execution method also supports the concept of a template.  A template is a “wrapper” around the job’s source code (a bit more than that really, but this explanation will do).
So, my JAMS execution method template is:
<<JAMS.Source>>
# echo the SAS exit code to the JAMS log, and pass this code back to JAMS
"LASTEXITCODE=$lastexitcode"
$host.SetShouldExit($lastexitcode)
### END OF FILE - do not add anything below this line ###
This essentially appends the $host.SetShouldExit($lastexitcode) statement to the end of the job source. Â This returns the correct errorcode created by my Powershell script back to the JAMS scheduler.
Details:
Here is what I think is happening:
-
JAMS creates a temporary file from the template. Â It expands JAMS tokens, such as <<JAMS.Source>> within the template. Â It appends the $host.SetShouldExit statement to the end of the source code.
-
It launches the temporary script using its custom Powershell host.
-
When it encounters my script invocation, it starts another process to run the script (???)
-
When my script invokes SAS via $p=Start-Process … -ArgumentList -Wait -NoNewWindow -Passthru, it starts another process to run the script.
-
I use $script:sasrc=$p.ExitCode to capture the exit code from SAS
-
I set $global:lastexitcode=$script:sasrc at the end of my script (I’m not sure this is needed??? But it works.)
-
This sets $lastexitcode within the JAMS custom host, after my script has ended.
-
Finally, $host.SetShouldExit($lastexitcode) returns the exit code to the scheduler.
I think that’s the sequence of events…