{"id":8771,"date":"2007-01-16T17:02:00","date_gmt":"2007-01-16T17:02:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2007\/01\/16\/managing-processes-in-powershell\/"},"modified":"2019-02-28T08:59:28","modified_gmt":"2019-02-28T16:59:28","slug":"managing-processes-in-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/managing-processes-in-powershell\/","title":{"rendered":"Managing Processes in PowerShell"},"content":{"rendered":"<p>Several people have asked recently about how to manage processes in PowerShell. This blog post should answer a number of those questions.<\/p>\n<p>As one might expect from the &#8220;shell&#8221; part of PowerShell, you don&#8217;t have to do special anything to start a process . In a programming language such as VBScript, you have to do something fairly complex like:<\/p>\n<pre class=\"lang:default decode:true \">strComputer = \u201c.\u201d\r\nSet objWMIService = GetObject(\u201cwinmgmts:\u201d _ \r\n&amp; \u201c{impersonationLevel=impersonate}!\\\\\u201d &amp; strComputer &amp; \u201c\\root\\cimv2\u201d) \r\nSet objStartup = objWMIService.Get(\u201cWin32_ProcessStartup\u201d) \r\nSet objConfig = objStartup.SpawnInstance_ \r\nSet objProcess = GetObject(\u201cwinmgmts:root\\cimv2:Win32_Process\u201d) \r\nobjProcess.Create \u201cNotepad.exe\u201d, Null, objConfig, intProcessID<\/pre>\n<p>&nbsp;<\/p>\n<p>but in shells ( PowerShell, cmd.exe, bash, etc.) you can simply start a program like notepad simply by typing &#8220;notepad&#8221; as shown.<\/p>\n<pre class=\"lang:default decode:true\">PS (1) &gt; notepad\r\n\r\n<\/pre>\n<pre class=\"lang:default decode:true\">&lt;shell returns immediately&gt;<\/pre>\n<pre class=\"lang:default decode:true \">PS (2) &gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Now you&#8217;ll notice that when you do this the shell returns immediately and prompts for the next command. This is because notepad is a win32 GUI process and runs in the background. On the other hand, if you start a console application like &#8220;ping.exe&#8221;, PowerShell will wait until that process completes.<\/p>\n<p>But what if I do want to wait for the Win32 process? In cmd.exe, you&#8217;d do this with &#8220;start \/wait&#8221; but this command is not (directly) available in PowerShell. So what do we do?<\/p>\n<p>PowerShell directly runs executables. If it waits for the process to exit, then the exit code left in $LASTEXITCODE. Now if a Win32 executable is the last command in a pipeline and is not redirected, then the process will run in the background. However, if you <em>pipe its output into something, then PowerShell will wait for the command to exit<\/em><\/p>\n<pre class=\"lang:default decode:true\">PS (1) &gt; notepad foo.txt  | out-null\r\n<\/pre>\n<pre class=\"lang:default decode:true \">&lt;exit notepad&gt;\r\n<\/pre>\n<pre class=\"lang:default decode:true \">PS (2) &gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>So this is a simple (if not intuitive) wait to wait for a GUI process to exit.<\/p>\n<p>Alternatively, If the process is already running, then you can use Get-Process to get the necessary information back and then do a WaitForExit() on that object.<\/p>\n<pre class=\"lang:default decode:true \">PS (3) &gt; get-process notepad<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName\r\n\r\n\r\n-------  ------    -----      ----- -----   ------     -- -----------\r\n\r\n\r\n     46       2      900       3744    28     0.05   4140 notepad\r\n\r\n\r\nPS (4) &gt; $np = get-process notepad\r\n\r\n\r\nPS (5) &gt; $np.waitforexit()\r\n\r\n\r\n&lt;exit notepad&gt;\r\n\r\n\r\nPS (6) &gt;\r\n\r\n\r\n<\/pre>\n<p>Here is a somewhat more sophisticated example where we open a document instead of starting a process. This time we&#8217;ll find the process by window title instead of by the executable name<\/p>\n<pre class=\"lang:default decode:true \">PS (8) &gt; .\/foo.txt\r\n\r\n\r\nPS (9) &gt; $fp = gps | where {$_.mainwindowtitle -match \"foo.txt\"}\r\n\r\n\r\nPS (10) &gt; $fp.WaitForExit()\r\n\r\n\r\n\r\nPS (11) &gt;\r\n\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Unfortunately searching for a process always means that you may find the wrong process. Ideally you&#8217;d like to get the Process object directly. So for more precise process management, you will have to use the .NET class System.Diagnostics.Process and start the processes yourself. For example, you can use [diagnostics.process]::Start() to wait for a process:<\/p>\n<pre class=\"lang:default decode:true \">PS (12) &gt; $p = [diagnostics.process]::start(\"notepad.exe\", \"$pwd\\foo.txt\")\r\n\r\n\r\nPS (13) &gt; $p.WaitForExit()\r\n\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Notice the use of &#8220;$pwd\\foo.txt&#8221; to specify the full path to the file. This is because PowerShell maintains its own idea of the current directory. (This note applies to using any .NET API that accesses the file system \u2013 you need to give it an absolute path.)<\/p>\n<p>Now we&#8217;re starting to get back to the level of complexity that you find in a programming language. However, you also have all of the power of those languages. Here&#8217;s an example script &#8220;background.ps1&#8221; that will let you run a scriptblock detached in a separate window (or in the same window if you specify the \u2013inconsole parameter.<\/p>\n<pre class=\"lang:default decode:true\">param(\r\n    [scriptblock] $script,  # scriptblock to run\r\n    [switch] $inconsole\u00a0\u00a0\u00a0\u00a0  # don't create a new window\r\n)\r\n\r\n\r\n# break out of the script on any errors\r\ntrap { break }\r\n# encode the script to pass to the child process...\r\n$encodedString = [convert]::ToBase64String(\r\n    [Text.Encoding]::Unicode.GetBytes([string] $script))\r\n# create a new process\r\n$p = new-object System.Diagnostics.Process\r\n# create a startinfo object for the process\r\n$si = new-object System.Diagnostics.ProcessStartInfo\r\n$si.WorkingDirectory = $pwd\r\nif ($inconsole)\r\n{\r\n    $si.UseShellExecute = $false\r\n}\r\nElse\r\n{\r\n    $si.UseShellExecute = $true\r\n}\r\n# set up the command and arguments to run\r\n$si.FileName = (get-command powershell.exe).Definition\r\n$si.Arguments = \"-encodedCommand $encodedString\"\r\n# and start the powershell process\r\n[diagnostics.process]::Start($si)\r\n\r\n\r\n<\/pre>\n<p><span style=\"font-size: 1rem;\">This script let&#8217;s you do things in PowerShell that you can&#8217;t do from cmd.exe but can do from VBScript.<\/span><\/p>\n<p>Finally, here are two more ways of working with processes. Even though PowerShell doesn&#8217;t have a start command, cmd.exe does so you can do a start \/wait by doing<\/p>\n<pre class=\"lang:default decode:true \">PS (14) &gt; cmd \/c start \/wait notepad.exe\r\nPS (15) &gt;\r\n\r\n\r\n<\/pre>\n<p>And, last but not least, the PowerShell Community Extensions includes a Start-Process cmdlets. You can get a list of these features at:<\/p>\n<p><a href=\"http:\/\/www.codeplex.com\/PowerShellCX\/Wiki\/View.aspx?title=PSCX%20Features\">http:\/\/www.codeplex.com\/PowerShellCX\/Wiki\/View.aspx?title=PSCX%20Features<\/a><\/p>\n<p>-bruce<\/p>\n<p>Bruce Payette [MSFT]<\/p>\n<p>Windows PowerShell Tech Lead<\/p>\n<p>Visit the Windows PowerShell Team blog at: \u00a0 \u00a0<a href=\"http:\/\/blogs.msdn.com\/PowerShell\" target=\"_new\">http:\/\/blogs.msdn.com\/PowerShell<\/a><\/p>\n<p>Visit the Windows PowerShell ScriptCenter at: \u00a0<a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_new\">http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx<\/a><\/p>\n<p>My book: <a href=\"http:\/\/manning.com\/powershell\" target=\"_new\">http:\/\/manning.com\/powershell<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Several people have asked recently about how to manage processes in PowerShell. This blog post should answer a number of those questions. As one might expect from the &#8220;shell&#8221; part of PowerShell, you don&#8217;t have to do special anything to start a process . In a programming language such as VBScript, you have to do [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-8771","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>Several people have asked recently about how to manage processes in PowerShell. This blog post should answer a number of those questions. As one might expect from the &#8220;shell&#8221; part of PowerShell, you don&#8217;t have to do special anything to start a process . In a programming language such as VBScript, you have to do [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/8771","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=8771"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/8771\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=8771"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=8771"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=8771"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}