Link to home
Start Free TrialLog in
Avatar of Jason Smith
Jason SmithFlag for United States of America

asked on

PowerShell: Start Service w/ Parameter In Background So Remainder of Script Will Run

Hello,

I'm a software tester for a small company that develops pharmacy management software.  I need a script that will kill off any running processes of our application, stop our application's Windows services, then launch our application's Windows services with a parameter or argument -Debug and then finally launch our application.  My problem is that I can launch the service with -Debug but it then blocks and no further part of the script will execute.  I need to be able to launch the main application after launching the service in debug mode.  Here is an example of what I have so far:

Write-Host "Seeking currently running MYAPP processes..."
$MYAPP Processes = Get-Process *MYAPP *

if ($MYAPP )
{
      $count = @($MYAPP Processes).Count
      if ($count -gt 0)
      {
            Write-Warning "MYAPP  processes found..."
            Write-Host
            
            # New Way
            while (Get-Process *MYAPP *)
            {
                  foreach ($process in (Get-Process *MYAPP *))
                  {
                        $processName = $process.Name
                        Write-Host "Attempting to close $MYAPP "
            
                        [Void] $process.CloseMainWindow()
                        Sleep 10
                        if (!$process.HasExited)
                        {
                              $process | Stop-Process -Force
                        }
                  }
                  
                  Sleep 10
            }
      }

      Write-Host
      Write-Host "Seeking currently running MYAPP  processes..."
      

      
      if (@(Get-Process *MYAPP *).Count -eq 0)
      {
            Write-Warning "All MYAPP  processes are terminated..."
            Write-Host
      }
      else
      {
            Write-Debug "MYAPP  processes still exist!"
            Write-Debug "Aborting script..."
            return
      }
}

Write-Host
Write-Host "Seeking status of MYAPP  service..."
$service = Get-Service MYAPP
$status = $service.Status

if ($status -ne "Stopped")
{
      Write-Host
      Write-Host "MYAPP  service is not stopped..."
      Write-Host "Attempting to stop the MYAPP  service..."
      $service.Stop
      Sleep 10
      $status = $service.Status
      if ($status -ne "Stopped")
      {
            Write-Host
            Write-Host "MYAPP  service is still not stopped..."
            Write-Host "Attempting to stop the MYAPP  service..."
            $service.Stop
            Sleep 10
            Write-Host "MYAPP  service is stopped..."
            Write-Host
      }
      
}
else
{
      Write-Host "MYAPP  service is stopped..."
}


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
PROBLEM IS HERE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Write-Host
Write-Warning "Launching MYAPP ..."
& 'C:\Program Files (x86)\New Leaf Rx\Server\MYAPP.exe' -debug  #This seems to block and rest of script won't run
Sleep 10
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
PROBLEM IS HERE
Tried using Start-Process but complains
Couldn't figure out how to use Start-Job
Any suggestions?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


Write-Host
Write-Warning "Launching MYAPP ..."
Start-Process -NoNewWindow 'C:\Program Files (x86)\New Leaf Rx\Client\MYAPP.exe'
Sleep 10

$process = Get-Process *MYAPP *
if ($process.Count -gt 0)
{
      Write-Warning "MYAPP  service is running with debug enabled..."
}

$process = Get-Process *MYAPP *
if ($process.Count -gt 0)
{
      Write-Warning "MYAPP  is running..."
}

Write-Host
Write-Host "Script is finished; exiting..."


Thanks you all in advance for your time and consideration!  :)

Sincerely,

Jason

EDIT1:  I was able to get background jobs to run by using:
Start-Job -ScriptBlock { 'C:\Program Files (x86)\New Leaf Rx\Client\NewLeafRxClient.exe -debug' }
but I notice now none of the debug info displays in the PowerShell console and the Client app never appears (I put both the service and the application in the background using the command above minus the -debug for the client line).
ASKER CERTIFIED SOLUTION
Avatar of Raheman M. Abdul
Raheman M. Abdul
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
> none of the debug info displays in the PowerShell console

If you're expecting the debug output from your process to appear in the PowerShell window it won't if you invoke another process (Start-Process) either.

If the exe doesn't immediately return (say like notepad.exe or calc.exe do) then you're a bit out a luck.

But.

You might be able to do something like this:
$psHost = [PowerShell]::Create()
$psHost.AddScript('C:\Program Files (x86)\New Leaf Rx\Client\MYAPP.exe -debug')
$psHost.BeginInvoke()

Open in new window

The output is still not visible, but all output streams are available via $psHost now. e.g.
$psHost.Streams

Open in new window

If your debug output is written to StdOut you'll need a slightly different approach again.
# Instantiate something we can synchronise across runspaces
$List = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
# Create a runspace
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('List', $List)
$psHost = [PowerShell]::Create()
$psHost.Runspace = $runspace
# Demonstrative stuff
# $null = $psHost.AddScript('1..20 | ForEach-Object { $List.Add($_); Start-Sleep -Seconds 10 } ')
$psHost.AddScript('C:\Program Files (x86)\New Leaf Rx\Client\MYAPP.exe -debug | ForEach-Object { $List.Add($_) } ')
$stateObject = $psHost.BeginInvoke()

Open in new window

Now you can periodically inspect $List to review the debug output. Depending on your usage there are a few other different object types that can be synchronised, including queues and hashtables.

Chris
One more note. If it produces a lot of output and you need it to run for a long time you might want something a little more complex in the async script, otherwise you're going to memory vanish into that background job where you can't easily release it (short of $psHost.Stop()).

In theory using a queue or stack, or removing entries from ArrayList as you consume them might work. That'll leave allocation for the garbage collector as normal, or I hope it will :)

Chris
Avatar of Jason Smith

ASKER

Thank you so much.  I'm just learning PowerShell and couldn't figure this out.  I added a -NoNewWindow parameter to the service launch line so it would stay all in one window.  You made it look so easy, and it works like a champ now!  I've released the script to my QA team to begin using.  Thanks again for your time!

  Sincerely,

  Jason
Chris,

I appreciate your insight as well.  I tried initially Raheman's solution and it got me exactly what I needed.  The debug output displays and stays in the same window.  Also, I am seeing the login prompt from the application which demonstrates the application is getting launched.  After logging in to the application, I do various things in the UI and I see the debug output scroll by.  I will certainly work to learn and understand what you have provided however.  Thank you for your detailed responses.  :)

Sincerely,

Jason
Marking your solution as the Best Solution as it was simple and did exactly what I wanted.  Thank you.