Difference between revisions of "Power Shell"

Jump to navigation Jump to search
2,017 bytes added ,  11:06, 25 May 2011
→‎Background Jobs: Added "Transcripts / Logging"
m (→‎Formatting: Added another example)
(→‎Background Jobs: Added "Transcripts / Logging")
Line 729: Line 729:


== Background Jobs ==
== Background Jobs ==
This feature allows Cmdlets to run as background jobs.  Its fairly easy to work out how to make individual Cmdlet's or PowerShell scripts to run as jobs (see [http://technet.microsoft.com/en-us/library/dd315273.aspx about_Jobs], but running functions are a bit more of a pain as the job runs in a new scope (so any functions, variables etc that are defined in your scripts scope, have no meaning in the background job's scope).  Therefore functions, etc, have to explicitly included in the background job...
This feature allows Cmdlets to run as background jobs.  Its fairly easy to work out how to make individual Cmdlet's or PowerShell scripts to run as jobs (see [http://technet.microsoft.com/en-us/library/dd315273.aspx about_Jobs], but running functions are a bit more of a pain as the job runs in a new scope (so any functions, variables etc that are defined in your scripts scope, have no meaning in the background job's scope).  Therefore functions, etc, have to explicitly included as a script block in the background job...


<source lang="powershell">
<source lang="powershell">
# First define  
# First define the script block and function
$funky = {
$funky = {
     function TestJob {
     function TestJob {
Line 740: Line 740:
}
}


# Start job
$job = Start-Job -ScriptBlock {TestJob} -InitializationScript $funky
$job = Start-Job -ScriptBlock {TestJob} -InitializationScript $funky


Line 749: Line 750:
</source>
</source>


Arguments have to be passed through to the job through the <code> -InputObject </code> parameter, which isn't particularly pretty.  For further info see http://robertrobelo.wordpress.com/2010/03/14/background-jobs-input-gotcha/.   
Arguments have to be passed through to the job through the <code> -InputObject </code> parameter, which isn't particularly pretty.  For further info see http://robertrobelo.wordpress.com/2010/03/14/background-jobs-input-gotcha/ for a decent explanation, though I do kind of cover this below.
 
'''Script Block''' or '''Script File'''...?
Your background task can either take the form of a script block, or a script filePersonally I prefer to keep everything in one script as it makes organisation easier, up to an extent.  There is a limit to size of a script block, no idea what it is, as the script I as trying to mangle into running as jobs was large (20 KB, nearly 1000 lines) and I didn't have a convenient way to test.  But your jobs will fail if they're too big.


=== Job Control ===
=== Job Control ===
Line 807: Line 811:
# Receive-Job -Id x    - shows the data returned from the job
# Receive-Job -Id x    - shows the data returned from the job
</source>
</source>
=== Transcripts / Logging ===
I haven't been able to get transcripts working properly with background jobs, at least, not to my liking.  It is possible to capture the console output from a background job into the transcript of the parent or master script.  But if you're running a large background job script and want to capture the transcript/logging from job separately you have to faff around - you can't just start and stop transcribing from within the (child) background job script, it won't write anything to disk.
Similarly, you can't redirect the output from <code> Receive-Job </code> to a file, you'll lose some of the output (I think this may only capture StdErr and/or explicitly returned objects, standard <code> Write-Host </code> output is dropped).
One way around this is to stop the transcript for your master/parent script, then start a temporary trasncript to capture then return from your child job once its finished, so so something like...
<source lang="powershell">
if ($job.State.ToString() -eq "Completed") {
    Write-Host ($job.Name + " writing log to job-" + $job.Name + ".log")
    # Nasty logging handling (Receive-Job StdOut to console only, can't redirect to file, can only catch StdErr to file)
    Stop-Transcript
    Start-Transcript -Path ("job-" + $job.Name + ".log")
    Receive-Job -Id $job.job.Id
    Stop-Transcript
    Start-Transcript -Path $Logfile -Append
}
</source>


=== Gotchas ===
=== Gotchas ===

Navigation menu