{"id":4392,"date":"2012-12-31T00:01:00","date_gmt":"2012-12-31T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/12\/31\/using-windows-powershell-jobs\/"},"modified":"2012-12-31T00:01:00","modified_gmt":"2012-12-31T00:01:00","slug":"using-windows-powershell-jobs","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/using-windows-powershell-jobs\/","title":{"rendered":"Using Windows PowerShell Jobs"},"content":{"rendered":"<p><strong>Summary:<\/strong> Microsoft Scripting Guy, Ed Wilson, shows an excerpt from his new step-by-step book about using Windows PowerShell jobs.\nMicrosoft Scripting Guy, Ed Wilson, is here. Today I want to share a portion of my new Microsoft Press <a href=\"http:\/\/www.amazon.com\/Windows-PowerShell-3-0-Step\/dp\/0735663394\/ref=sr_1_2?s=books&amp;ie=UTF8&amp;qid=1356840351&amp;sr=1-2&amp;keywords=powershell+step+by+step\" target=\"_blank\">Windows PowerShell 3.0 Step by Step<\/a> book. This book is available now for preorder.<\/p>\n<h3>Using Windows PowerShell Jobs<\/h3>\n<p>You can begin a new Windows PowerShell job by using the <strong>Start-Job<\/strong> cmdlet. The command to run as a job is placed in a script block, and the jobs are sequentially named Job1, Job2 &hellip; This is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Start-Job -ScriptBlock {get-process} <br \/>Id Name PSJobTypeName State HasMoreData Location <br \/>&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; <br \/>10 Job10 BackgroundJob Running True localhost <br \/>PS C:&gt;\nThe jobs receive job IDs that are also sequentially numbered. The first job created in a Windows PowerShell console is always job ID 1. You can use either the job ID or the job name to obtain information about the job. This is seen here.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Get-Job -Name job10<\/p>\n<p style=\"padding-left: 30px\">Id Name PSJobTypeName State HasMoreData Location<\/p>\n<p style=\"padding-left: 30px\">&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">10 Job10 BackgroundJob Completed True localhost<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Get-Job -Id 10<\/p>\n<p style=\"padding-left: 30px\">Id Name PSJobTypeName State HasMoreData Location<\/p>\n<p style=\"padding-left: 30px\">&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">10 Job10 BackgroundJob Completed True localhost<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt;\nOnce you see that the job has completed, you can receive the job. The <strong>Receive-Job<\/strong> cmdlet returns the same information that returns if a job is not used. The Job1 output seen here (truncated to save space).<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Receive-Job -Name job10 <br \/>Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName <br \/>&#8212;&#8212;- &#8212;&#8212; &#8212;&#8211; &#8212;&#8211; &#8212;&#8211; &#8212;&#8212; &#8212; &#8212;&#8212;&#8212;&#8211; <br \/>62 9 1672 6032 80 0.00 1408 apdproxy <br \/>132 9 2316 5632 62 1364 atieclxx <br \/>122 7 1716 4232 32 948 atiesrxx <br \/>114 9 14664 15372 48 1492 audiodg <br \/>556 62 53928 5368 616 3.17 3408 CCC <br \/>58 8 2960 7068 70 0.19 928 conhost <br \/>32 5 1468 3468 52 0.00 5068 conhost <br \/>784 14 3284 5092 56 416 csrss <br \/>529 27 2928 17260 145 496 csrss <br \/>182 13 8184 11152 96 0.50 2956 DCPSysMgr <br \/>135 11 2880 7552 56 2056 DCPSysMgrSvc <br \/>&#8230; (truncated output)\nOnce a job has been received, that is it<span>&mdash;<\/span>the data is gone, unless you save it to a variable. The following code illustrates this concept.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Receive-Job -Name job10 <br \/>PS C:&gt;\nWhat can be confusing about this is that the job still exists, and the <strong>Get-Job<\/strong> cmdlet continues to retrieve information about the job. This is seen here.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Get-Job -Id 10 <br \/>Id Name PSJobTypeName State HasMoreData Location <br \/>&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; <br \/>10 Job10 BackgroundJob Completed False localhost\nAs a best practice, use the <strong>Remove-Job<\/strong> cmdlet to delete remnants of completed jobs when you are finished using the job object. This will avoid confusion regarding active jobs, completed jobs, and jobs waiting to be processed. After a job has been removed, the <strong>Get-Job<\/strong> cmdlet returns an error if you attempt to retrieve information about the job<span>&mdash;<\/span>because it no longer exists. This is illustrated here.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Remove-Job -Name job10 <br \/>PS C:&gt; Get-Job -Id 10 <br \/>Get-Job : The command cannot find a job with the job ID 10. Verify the value of the <br \/>Id parameter and then try the command again. <br \/>At line:1 char:1 <br \/>+ Get-Job -Id 10 <br \/>+ ~~~~~~~~~~~~~~ <br \/>+ CategoryInfo : ObjectNotFound: (10:Int32) [Get-Job], PSArgumentExcep <br \/>tion <br \/>+ FullyQualifiedErrorId : JobWithSpecifiedSessionNotFound,Microsoft.PowerShell. <br \/>Commands.GetJobCommand\nWhen working with the job cmdlets, I like to give the jobs their own name. A job that returns process objects via the <strong>Get-Process<\/strong> cmdlet might be called getProc. A contextual naming scheme works better than trying to keep track of names such as Job1 or Job2. Do not worry about making your job names too long, because you can use wildcard characters to simplify the typing requirement. When you receive the job, make sure you store the returned objects in a variable. This is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; Start-Job -Name getProc -ScriptBlock {get-process} <br \/>Id Name PSJobTypeName State HasMoreData Location <br \/>&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; <br \/>12 getProc BackgroundJob Running True localhost <br \/>PS C:&gt; Get-Job -Name get* <br \/>Id Name PSJobTypeName State HasMoreData Location <br \/>&#8212; &#8212;- &#8212;&#8212;&#8212;&#8212;- &#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; <br \/>12 getProc BackgroundJob Completed True localhost <br \/>PS C:&gt; $procObj = Receive-Job -Name get* <br \/>PS C:&gt;\nOnce you have the returned object in a variable, you can use the object with other Windows PowerShell cmdlets. One thing to keep in mind is that the object is deserialized. This is seen here where I use <strong>gm<\/strong> as an alias for the <strong>Get-Member<\/strong> cmdlet.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; $procObj | gm <br \/>TypeName: Deserialized.System.Diagnostics.Process\nThis means that not all the normal members from the System.Diagnostics.Process .NET Framework object are available. The normal methods are shown here (<strong>gps<\/strong> is an alias for the <strong>Get-Process<\/strong> cmdlet, <strong>gm<\/strong> an alias for <strong>Get-Member<\/strong>, and <strong>&ndash;m<\/strong> is enough of the<strong> &ndash;membertype<\/strong> parameter to distinguish it on the Windows PowerShell console line).<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; gps | gm -m method <br \/>TypeName: System.Diagnostics.Process <br \/>Name MemberType Definition <br \/>&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- <br \/>BeginErrorReadLine Method System.Void BeginErrorReadLine() <br \/>BeginOutputReadLine Method System.Void BeginOutputReadLine() <br \/>CancelErrorRead Method System.Void CancelErrorRead() <br \/>CancelOutputRead Method System.Void CancelOutputRead() <br \/>Close Method System.Void Close() <br \/>CloseMainWindow Method bool CloseMainWindow() <br \/>CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) <br \/>Dispose Method System.Void Dispose() <br \/>Equals Method bool Equals(System.Object obj) <br \/>GetHashCode Method int GetHashCode() <br \/>GetLifetimeService Method System.Object GetLifetimeService() <br \/>GetType Method type GetType() <br \/>InitializeLifetimeService Method System.Object InitializeLifetimeService() <br \/>Kill Method System.Void Kill() <br \/>Refresh Method System.Void Refresh() <br \/>Start Method bool Start() <br \/>ToString Method string ToString() <br \/>WaitForExit Method bool WaitForExit(int milliseconds), System.Void WaitForExit() <br \/>WaitForInputIdle Method bool WaitForInputIdle(int milliseconds), bool WaitForInputIdle()\nMethods from the deserialized object are shown here where I use the same command I used previously.<\/p>\n<p style=\"padding-left: 30px\">PS C:&gt; $procObj | gm -m method <br \/>TypeName: Deserialized.System.Diagnostics.Process <br \/>Name MemberType Definition <br \/>&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- <br \/>ToString Method string ToString(), string ToString(string format, System.IFormatProvider formatProvider) <br \/>PS C:&gt;\nJoin me tomorrow for a guest post by Microsoft MVP and Honorary Scripting Guy Don Jones on new year&rsquo;s resolutions.\nI invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.\n<strong>Ed Wilson, Microsoft Scripting Guy<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, shows an excerpt from his new step-by-step book about using Windows PowerShell jobs. Microsoft Scripting Guy, Ed Wilson, is here. Today I want to share a portion of my new Microsoft Press Windows PowerShell 3.0 Step by Step book. This book is available now for preorder. Using Windows PowerShell [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[85,3,4,220,45],"class_list":["post-4392","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-jobs","tag-scripting-guy","tag-scripting-techniques","tag-scripting-templates","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, shows an excerpt from his new step-by-step book about using Windows PowerShell jobs. Microsoft Scripting Guy, Ed Wilson, is here. Today I want to share a portion of my new Microsoft Press Windows PowerShell 3.0 Step by Step book. This book is available now for preorder. Using Windows PowerShell [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=4392"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4392\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=4392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=4392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=4392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}