Link to home
Start Free TrialLog in
Avatar of Robb Hill
Robb HillFlag for United States of America

asked on

Powershell script to Recycle processes all at once ( cleanly)

Lets say I have a process.exe.

Lets say I have any where from 4 to 6 processes running with the proc name.

I need to close and restart each process.

My issue is if the process is in use...I need the script to close this process cleanly..

How would I do that.

I have dont this before...but not sure about makign it close clean.

I dont want to just kill it.
Avatar of Qlemo
Qlemo
Flag of Germany image

You can't, without knowing more about the process.

Is there a window? If yes, trying to send a WM_Close window message to that window is what should be used, but might get ignored (busy, prompting for input or confirrmation, ...).
If no, you need a very specific way to communicate with the process. Self-written apps might poll for a signal file in a specific path, listen to tailored TCP/UDP packets, or something like that.
Avatar of Robb Hill

ASKER

The program is and old form written in vs FoxPro.  

It is just an exe.  It can run in forground or background.  

When running in forground it is intetactive and has an exit button.

Does that help?
What about using something like this example with IE.

powershell -Command "while ($true){Try{$process=Get-Process iexplore -ErrorAction Stop}Catch [Microsoft.PowerShell.Commands.ProcessCommandException]{break;}if ($process) {$whateva=$process.CloseMainWindow()}else {break;}Start-Sleep -m 500}"
That could work while the exe is running in foreground.
THis is not working:(   It removed one of the 4 items in the foreground...but you could still see the 4 items in the background.

The program was no longer responsive though even though you could see the exe running in the task manager.

Not sure what to do.

Perhaps there is a better way
That script only works for a single window per iteration, so it should close one window each 0.5 seconds.
You should also check if Get-Process YourProcessName really results in all N objects you would expect it to be.
So here is a live example:

I have a process called "Process"

There are 4 instances running...so 4 different PIDs.

3 PIDs have 0 cpu and 1 has 50 on the cpu.

What I need to happen is the following.

Close the 3 pid's with 0...
when if finds the run that is still running....thus the CPU...wait for x amount of time...or until cpu is 0..would be nice if it could have a double check...
Then kill it...

So keep checking until cpu is 0 else after x amount of time just kill this PID as well.


Would that work?


The CPU would only be idel for a millisecond ..so that may be hard to capture...I just dont see any other way of knowing that its running or not.

The EXE is running regardless if the CPU is 0.  Its just when its 0 ...its not queuing any commands.


These "PROCESS"'s really are just forms showing commands sent to them continuously.


If it happens that a command has been sent when I am trying to close it...I dont want to ( stop the command it is running)

I see  know what to interact with it...so I think we have to trick it...
Or just say its been running too long.
Too much "guessing logic" in that. You should also not rely on the momentary 0 CPU load - we need some kind of average, say 5 samples in 5 seconds, and only if all are zero we can assume there is no activity with some reliability.
Or use something like:
$init = Get-Process "Process"
start-sleep 5
Get-Process "Process" |
  % {
    $pid = $_.ID
    $proc = $init | ? { $_.ID -eq $pid }
    if ($_.TotalProcessorTime.TotalMilliseconds - $proc.TotalProcessorTime.TotalMilliseconds -lt 100)
    {
      stop-process $_
    }
  }

Open in new window

This allows for some idle cycling, but no real work.
The final kill (the processes still doing some work) could then be killed with another loop following, or doing above for 5 iterations again, or whatever. In the end you will have to just kill what is left.
You may incorporate the restart code even into the Visual FoxPro program:
DECLARE INTEGER ShellExecute IN SHELL32.dll ;
    INTEGER nWinHandle, ;
    STRING cOperation, ;
    STRING cFileName, ;
    STRING cParameters, ;
    STRING cDirectory, ;
    INTEGER nShowWindow

LOCAL lnResult1, loEx AS Exception, llError
STORE -1 TO lnResult1
LOCAL lcMyself, lcParams
lcMyself = SYS(16,0)
lcParams = '""'  && Possible command line parameters

TRY
  
  lnResult1 = ShellExecute(0, "Open", ;
      m.lcMyself, m.lcParams, JustPath(m.lcMyself), 1)
  *-- Possible test of the result here
CATCH TO loEx
  *-- Log error to a file... etc.
  llError = .T.
ENDTRY

*-- Stop myself
IF m.lnResult1 > 32 AND !m.llError
  ON ERROR *
  ON SHUTDOWN QUIT
  QUIT
ENDIF

Open in new window

You'll know where and when to call the above code probably.
Qlemo:

Ok so in this case lets say the transactions are so fast so nothing ever realy gets caught with a zero cpu.  if you have 1000 users hitting this process its highly unlikly to be on zero if not for a miliscond.

This is the error I get:

PS C:\Users\ichannel> $init = Get-Process "Cadoc"
start-sleep 5
Get-Process "Cadoc" |
  % {
    $pid = $_.ID
    $proc = $init | ? { $_.ID -eq $pid }
    if ($_.TotalProcessorTime.TotalMilliseconds - $proc.TotalProcessorTime.TotalMilliseconds -lt 100)
    {
      stop-process $_
    }
  }
Cannot overwrite variable PID because it is read-only or constant.
At line:5 char:5
+     $pid = $_.ID
+     ~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (PID:String) [], SessionStateUnautho
   rizedAccessException
    + FullyQualifiedErrorId : VariableNotWritable
 
Cannot overwrite variable PID because it is read-only or constant.
At line:5 char:5
+     $pid = $_.ID
+     ~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (PID:String) [], SessionStateUnautho
   rizedAccessException
    + FullyQualifiedErrorId : VariableNotWritable
 
Cannot overwrite variable PID because it is read-only or constant.
At line:5 char:5
+     $pid = $_.ID
+     ~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (PID:String) [], SessionStateUnautho
   rizedAccessException
    + FullyQualifiedErrorId : VariableNotWritable


Now this is a slow part of the day but

this exe file...litterally is sending request and responses out of it at the millisecond....unless its a long request...which could take a while.

But the typically tranasactions are flowing through here extremely fast.  So in a normal day I would expect the cup to never be 0...unless it goes to 0 between one request to the next...but we are talking about such a tiny part of time you woudl not notice it with the visible eye.

I really am confused..lol

At the end of the day. ..I need to exit these process.exe ...and just make sure that whateve the current item that is running is given some amount of time to finish..and fine .if it doenst change then I will kill it....( this bandaids a long running memory leak)

If I just look at the CPU being some number or not..I would not know if its the same or new transaction (requests)  because its still on the same PID.

Does that make sense  to you?
I dont think I can just change this in Fox pro due to requirements here...but I was not expecting a Fox Pro answer...That was great:)  Thanks for sharing.  I thought I might be the only one plagued in a Fox pro world as .Net developer:)
You cannot act on something you cannot measure. Stopping a process from processing new requests is only feasible on the application level - this means code.
If there is a broker service (distributing requests to worker threads or processes) then you can stop that. Basically you need to remove whatever tells the requester what to contact.
Other than that, all you can do is to repeatedly try to close the window, and finally kill the processes.
I am hearing you...Let me think on this and see if I there is anything else to add.   I need to be able to do this..but am not seeing how.
can we try a different approach.


the real issue here is these processes have a memory leak and overtime consume too much memory thus the reason i restart them.   this releases the memory and they work ok again.  


now i run these on many different server configs so cpu,, memory os. etc is always a variable.  

can i run a script that will sum all these pids up, determine mathmatically that they are using too much memory and then close them from  there.  

maybe i could close them testing if they are responding or not then kill.  something like that.   checking if in use and killing ...etc
ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany 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