Powershell - if a process is not running, start it

前端 未结 4 1756
情深已故
情深已故 2021-02-03 23:37

Noob help please. I\'m trying to write a script that will check if a process is running, and if not, start it. If the process is running, it should do nothing. I\'ve come up wit

相关标签:
4条回答
  • 2021-02-04 00:24

    In the Get-Process cmdlet, the process name argument must be the name of the executable without the file extension. Try substituting $Prog = "C:\utilities\prog.exe" with $Prog = "prog".

    In my opinion, your script would be more readable if you filtered the process out using the Where-Object cmdlet instead. Here's an example:

    $programName = "prog"
    $isRunning = (Get-Process | Where-Object { $_.Name -eq $programName }).Count -gt 0
    
    if ($isRunning)
     # ...
    else
     # ...
    

    That way you can get rid of the -ErrorAction SilentlyContinue argument, which can be confusing to someone who is not aware of the fact that Get-Process throws an error if it can't find a process with the specified name.

    0 讨论(0)
  • 2021-02-04 00:28

    First of all, here's is what is wrong in your code. In your code, the process is created before you evaluate whether your program is already running

    $Prog = "C:\utilities\prog.exe"
    $Running = Get-Process prog -ErrorAction SilentlyContinue
    $Start = ([wmiclass]"win32_process").Create($Prog) # the process is created on this line
    if($Running -eq $null) # evaluating if the program is running
    {$Start}
    

    It is possible to create a block of code that should be evaluated further in your code by wrapping it in {} (a scriptblock):

    $Prog = "C:\utilities\prog.exe"
    $Running = Get-Process prog -ErrorAction SilentlyContinue
    $Start = {([wmiclass]"win32_process").Create($Prog)} 
    if($Running -eq $null) # evaluating if the program is running
    {& $Start} # the process is created on this line
    

    However, if you're looking for a short one-liner to solve your problem:

    if (! (ps | ? {$_.path -eq $prog})) {& $prog}
    
    0 讨论(0)
  • 2021-02-04 00:31
    $path = "C:\utilities\prog.exe"        
    $list = get-process | where-object {$_.Path -eq $path }     
    if ($list -eq $null) { start-process -filepath $path }
    

    Or

    $path = "C:\utilities\prog.exe"
    get-process | where-object {$_.Path -eq $path } | measure-object | where-object { $_.Count -eq 0} | foreach-object {start-process -filepath $path }
    

    This will save you the if statement and one variable declaration. It can be a one line command as well:

    1. Get processes
    2. Pick the ones with the path you are interested in
    3. Use measure object to get the stats about the list you have
    4. Continue the piping only if the count value of stats is 0
    5. Start process

    Don't let the foreach at the end put you off. The measure object will return only one item the where will return one or zero. The foreach is only used to execute if the result is zero. It won't start more then one processes. :)

    0 讨论(0)
  • 2021-02-04 00:37

    Keep in mind that PowerShell handles objects and not just text. While in normal batch files you could set a variable to a string and then just use it as a command:

    set Foo=dir /b
    %Foo%
    

    ... this doesn't work in PowerShell. Thus your assignment of $Start already creates the new process since the command after the = is run and its result assigned to $Start.

    Furthermore you're complicating things needlessly. I'd suggest the following instead:

    $Running = Get-Process prog -ErrorAction SilentlyContinue
    if (!$Running) { Start-Process C:\utilities\prog.exe }
    

    Since Get-Process returns an object (which evaluates to $true) or $null (which evaluates to $false) you can simplify the check like shown above. This is called type coercion, since the if statement expects a boolean value and the rules on what will be treated as $true and $false are very consistent in such cases as above. And it reads nicer.

    I also used the Start-Process cmdlet instead of WMI to create the new process. You could even use the following:

    if (!$Running) { C:\utilities\prog.exe }
    

    if the application is not a console application (and thus would block the PowerShell script until it exits). PowerShell is still a shell, so starting programs is something that works natively very well :-)

    You could even inline the $running variable, but I guess a comment would be in order to clarify what you do, then.

    0 讨论(0)
提交回复
热议问题