{"id":1869,"date":"2014-03-06T00:01:00","date_gmt":"2014-03-06T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/03\/06\/powershell-jobs-week-jobs-and-workflows\/"},"modified":"2014-03-06T00:01:00","modified_gmt":"2014-03-06T00:01:00","slug":"powershell-jobs-week-jobs-and-workflows","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/powershell-jobs-week-jobs-and-workflows\/","title":{"rendered":"PowerShell Jobs Week: Jobs and Workflows"},"content":{"rendered":"<p><b>Summary<\/b>: Richard Siddaway introduces you to using the Windows PowerShell job engine with your Windows PowerShell workflows.<\/p>\n<p>Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the fifth in a series of posts that, hopefully, will shine the spotlight on Windows PowerShell jobs, remind people of their capabilities, and encourage their greater adoption. The full series comprises:<\/p>\n<ol>\n<li><a href=\"\/b\/heyscriptingguy\/archive\/2014\/03\/02\/powershell-jobs-week-introduction-to-powershell-jobs.aspx\" target=\"_blank\">Introduction to PowerShell Jobs<\/a><\/li>\n<li><a href=\"\/b\/heyscriptingguy\/archive\/2014\/03\/03\/powershell-jobs-week-wmi-and-cim-jobs.aspx\" target=\"_blank\">WMI and CIM Jobs<\/a><\/li>\n<li><a href=\"\/b\/heyscriptingguy\/archive\/2014\/03\/04\/powershell-jobs-week-remote-jobs.aspx\" target=\"_blank\">Remote Jobs<\/a><\/li>\n<li><a href=\"\/b\/heyscriptingguy\/archive\/2014\/03\/05\/powershell-jobs-week-scheduled-jobs.aspx\" target=\"_blank\">Scheduled Jobs<\/a><\/li>\n<li>Jobs and Workflows (this post)<\/li>\n<li>Job Processes<\/li>\n<li>Jobs in the Enterprise<\/li>\n<\/ol>\n<p>The focus on this series has been on Windows PowerShell jobs, including learning about the core job cmdlets, using the<br \/><b>&ndash;AsJob<\/b> parameter, running jobs on remote machines, and figuring out how scheduled jobs work. Today, we are going to look at using the Windows PowerShell job engine with Windows PowerShell workflows.<\/p>\n<p>Workflows are another piece of the Windows PowerShell technology, which (as with Windows PowerShell jobs) is underused. Workflows have a reputation for being difficult to work with and understand. If you&rsquo;ve not experimented with workflows, I recommend that you read this series of Hey,Scripting Guy! Blog posts that I wrote in 2013:<\/p>\n<p>1. <a href=\"\/b\/heyscriptingguy\/archive\/2012\/12\/26\/powershell-workflows-the-basics.aspx\" target=\"_blank\">PowerShell Workflows: The Basics<\/a> &nbsp;<br \/> Introduces workflows, key concepts, and keywords.<\/p>\n<p>2. <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/powershell-workflows-restrictions\/\" target=\"_blank\">PowerShell Workflows: Restrictions<\/a> <br \/> Discusses cmdlets that are not available as workflow activities, using in-line script, and using variables.<\/p>\n<p>3. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/01\/09\/powershell-workflows-nesting.aspx\" target=\"_blank\">PowerShell Workflows: Nesting<\/a><br \/> Investigates how Windows PowerShell functions and Windows PowerShell workflows can be used inside other workflows.<\/p>\n<p>4. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/01\/16\/powershell-workflows-job-engine.aspx\" target=\"_blank\">PowerShell Workflow: Job Engine<\/a> <br \/> Investigates suspending, resuming, checkpoints, and recovery.<\/p>\n<p>5. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/01\/23\/powershell-workflows-restarting-the-computer.aspx\" target=\"_blank\">PowerShell Workflows: Restarting the Computer<\/a><br \/> Investigates how workflows can survive a reboot.<\/p>\n<p>6. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/01\/30\/powershell-workflows-using-parameters.aspx\" target=\"_blank\">PowerShell Workflows: Using Parameters<\/a><br \/> Investigates parameters that are available to workflows and activities, the options for connecting to remote computers, and the workflow cmdlets.<\/p>\n<p>7. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/02\/06\/powershell-workflows-design-considerations.aspx\" target=\"_blank\">PowerShell Workflows: Design Considerations<\/a><br \/> Investigates design considerations for Windows PowerShell workflows.<\/p>\n<p>8. <a href=\"\/b\/heyscriptingguy\/archive\/2013\/02\/13\/powershell-workflows-a-practical-example.aspx\" target=\"_blank\">PowerShell Workflows: A Practical Example<\/a><br \/>Pulls together the various strands of the series and presents the development of a workflow.<\/p>\n<p>In particular, you should read post 4 about workflows and the Windows PowerShell job engine. That post looked at things from the workflow point of view. Today we&rsquo;ll look at things from the job engine&rsquo;s perspective.<\/p>\n<p>Let&rsquo;s start with a simple workflow:<\/p>\n<p style=\"margin-left:30px\">workflow mysimpleworkflow<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Get-Process<\/p>\n<p style=\"margin-left:30px\">}&nbsp;<\/p>\n<p style=\"margin-left:30px\">mysimpleworkflow<\/p>\n<p>This produces a list of processes that are running on the computer. It&rsquo;s important to note that in a workflow, you aren&rsquo;t dealing with a Windows PowerShell cmdlet, but rather, a workflow activity that functions in a similar way to the cmdlet of the same name.<\/p>\n<p>If you look at the syntax of the workflow:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-Command mysimpleworkflow -Syntax<\/p>\n<p style=\"margin-left:30px\">mysimpleworkflow [&lt;WorkflowCommonParameters&gt;] [&lt;CommonParameters&gt;]<\/p>\n<p>It would have been nice if I could list the WorkflowCommonParameters, but there are a lot of them. You can read about them in the Help file <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/jj129719.aspx\" target=\"_blank\">about_WorkflowCommonParameters<\/a>. If you read the Help file (and I recommend reading all of the workflow-related Help files), you will see that <b>&ndash;AsJob<\/b> is the first common parameter and <b>&ndash;JobName<\/b> is the second.<\/p>\n<p>What about the workflow activities? Can we run those as a job? If you look at another Help file, <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/jj733585.aspx\" target=\"_blank\">about_ActivityCommonParameters<\/a>, you&rsquo;ll see that there aren&rsquo;t any job-related parameters for workflow activities. We&rsquo;ll come back to this in a while.<\/p>\n<p>What happens when we run our workflow as a job?<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0434.1.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0434.1.PNG\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>The workflow was run as a job:<\/p>\n<p style=\"margin-left:30px\">mysimpleworkflow -AsJob -JobName wftest<\/p>\n<p>I previously dot-sourced the Windows PowerShell script that contains the workflow. A job (Id 6) is started. This time, it&rsquo;s of type <b>PSWorkflowJob<\/b>. You can use the standard job cmdlets <b>Get-Job<\/b>, <b>Receive-Job<\/b>, and <b>Remove-Job<\/b> as shown in the screenshot. Apart from the type, the workflow job is behaving as a standard Windows PowerShell job. Isn&rsquo;t consistency lovely? Makes our job so much easier.<\/p>\n<p>You may remember that in Part 1 of this series, I mentioned that the <b>Suspend-Job<\/b> and <b>Resume-Job<\/b> cmdlets can only be used with workflow jobs. This is how you use them&hellip;<\/p>\n<p>Start by creating a new workflow.<\/p>\n<p style=\"margin-left:30px\">workflow mysuspenableworkflow<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Start-Sleep -Seconds 10<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Suspend-Workflow<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Get-Process<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p>The workflow will sleep for 10 seconds and then suspend itself. When it resumes, it calls the <b>Get-Process<\/b> activity as in our previous example.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/3056.2.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/3056.2.PNG\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Dot-source and run the workflow. It sleeps for 10 seconds and then suspends. When the workflow suspends itself, a job is created in a suspended state. Notice that the workflow was started without the <b>&ndash;AsJob<\/b> parameter. Suspending a workflow will create the job. The type is still PSWorkflowJob.<\/p>\n<p>You use the <b>Resume-Job<\/b> cmdlet to get the job running again. In Windows PowerShell&nbsp;4.0, resuming a suspended job shows the output in the screenshot with the job&rsquo;s <b>State<\/b> set to <b>Running<\/b>. In Windows PowerShell &nbsp;3.0, when you used <b>Resume-Job<\/b>, the <b>State<\/b> was still shown as <b>Suspended<\/b>, and you had to use <b>Get-Job<\/b> to see the true state. After the job has completed, you can view the data and remove it as normal.<\/p>\n<p>There&rsquo;s one really clever feature of suspending a workflow job: You can access it in a different Windows PowerShell session.&nbsp; Run the workflow again until the job suspends. When you see the message that the job has suspended, close your Windows PowerShell session.<\/p>\n<p>Yep, that&rsquo;s right. Just go ahead and shut it down.<\/p>\n<p>Open a new Windows PowerShell session (with elevated privileges) and run <b>Get-Job<\/b>. Your suspended job will be visible if you&rsquo;re using Windows PowerShell&nbsp;4.0. (In Windows PowerShell&nbsp;3.0, you have to import the PSWorkflow module first to be able to see the suspended jobs). You can resume the job and proceed.<\/p>\n<p>What happens if you use the <b>&ndash;AsJob<\/b> parameter on a workflow that&rsquo;s going to suspend?<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/6457.3.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/6457.3.PNG\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Start the workflow, but this time start it as a job:<\/p>\n<p style=\"margin-left:30px\">mysuspenableworkflow -AsJob -JobName suspendtest<\/p>\n<p>You immediately get a running job that suspends itself after the appropriate amount of time. You can resume the job and proceed as before.<\/p>\n<p>You can also suspend long running jobs from outside the job. Workflows are designed for long running tasks. You can simulate that by using a long sleep interval. This work flow will run for a while before it shows any output:<\/p>\n<p style=\"margin-left:30px\">workflow mylongworkflow<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Start-Sleep -Seconds 60<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Checkpoint-Workflow<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Get-Process<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p>In this case, we want to start the workflow as a job so that we can suspend it at will.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0172.4.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0172.4.PNG\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Suspend the job. Your job goes into a state of <b>Suspending<\/b>. This means that it will run until it hits the <b>CheckPoint-Workflow<\/b> activity which saves a copy of the job&rsquo;s state to disk and finally suspends the job.<\/p>\n<p>If you are suspending the workflow job from inside the workflow, use the <b>Suspend-Workflow<\/b> activity.&nbsp; If you are going to suspend the workflow job manually, ensure that you have <b>CheckPoint-Workflow<\/b> at suitable points in your workflow so that the workflow can create a checkpoint and suspend.<\/p>\n<p><b>Resume-Job<\/b> and the other cmdlets work as expected. You could resume the workflow job in a different Windows PowerShell session if required.<\/p>\n<p>We&rsquo;ve discussed running workflows as jobs. But what about running jobs inside workflows? This will start a job inside a workflow, and then run the workflow:<\/p>\n<p style=\"margin-left:30px\">workflow myjobflow<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Start-Job -ScriptBlock{Get-Process}<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/8422.5.PNG\"><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/8422.5.PNG\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>The workflow starts, and you can see that it shows a job is created. But if you try <b>Get-Job<\/b>,nothing is returned. The reason is that workflows aren&rsquo;t run by your Windows PowerShell session. They are handed off to the workflow engine to run in a different process. That process shuts down when the workflow finishes, and you lose the job. I don&rsquo;t really think there is any advantage to running jobs inside workflows because you have to handle checking that the job is complete, and then return any data from the job while the workflow is still running.<\/p>\n<p>The best strategy is to run the workflow as a job. Then you get the best of both worlds.<\/p>\n<p>That&rsquo;s it for today. Tomorrow you&rsquo;ll learn about the processes under which different job types run. Bye for now.<\/p>\n<p>~Richard<\/p>\n<p>Thanks, Richard. Looking forward to the final posts in this series.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">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=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Richard Siddaway introduces you to using the Windows PowerShell job engine with your Windows PowerShell workflows. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the fifth in a series of posts that, hopefully, will shine the spotlight on Windows PowerShell jobs, remind people of [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[193,189,4,45],"class_list":["post-1869","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-background-jobs","tag-richard-siddaway","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Richard Siddaway introduces you to using the Windows PowerShell job engine with your Windows PowerShell workflows. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the fifth in a series of posts that, hopefully, will shine the spotlight on Windows PowerShell jobs, remind people of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1869","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\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=1869"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1869\/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=1869"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=1869"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=1869"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}