Home > Blockchain >  Powershell - CloseMainWindow work for all?
Powershell - CloseMainWindow work for all?

Time:04-09

I'm looking for a way to gracefully close/quit the GoogleDrive app which runs under the process GoogleDriveFS.

get-process GoogleDriveFS

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    219      16    10796       5732       0.05   4392   1 GoogleDriveFS
    333      22    11820      32364       0.17   8424   1 GoogleDriveFS
    297      19    16528      34860       0.06  12036   1 GoogleDriveFS
    245      17    10472      23992       0.03  14296   1 GoogleDriveFS
    572      26    52256      82728       0.84  17788   1 GoogleDriveFS
    518      21    28668      68208       0.44  18460   1 GoogleDriveFS
   1024      59    47016      89396      27.95  19452   1 GoogleDriveFS

is something like Process.CloseMainWindow Method suitable for this ? or is there a better way to ensure the app isn't running?

CodePudding user response:

You can do something like this:

do {
    $running = try { Get-Process -Name GoogleDriveFS -ErrorAction Stop } catch { Write-Host "Error: $($PSItem.Exception.Message) " }
    $running | ForEach-Object {
        
        $_.CloseMainWindow()
        Write-Debug -Message "Closing ($_).pm "
    
    }
}
until ($running -eq $null)

However, this will prompt for the user to confirm the close.

You could also use the close() method to avoid prompting the user or kill() to immediately release all resources.

CloseMainWindow() Closes a process that has a user interface by sending a close message to its main window.

Close() Frees all the resources that are associated with this component.

Kill() Immediately stops the associated process.

via https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=net-6.0#methods

CodePudding user response:

tl;dr

You can try the following, but there's no guarantee it will work:

taskkill.exe /im GoogleDriveFS.exe

System.Diagnostics.Process.CloseMainWindow() will not work, for the reasons explained below.


  • On Windows, graceful termination is fundamentally only an option for GUI-subsystem applications, i.e. processes with windows that have a main window and a message loop to which the WM_CLOSE message can be posted.

    • In other words: you cannot ask console applications on Windows to terminate gracefully (unless they implement some application-specific custom mechanism through which other processes can request termination).

    • For supported applications, there are important considerations:

      • Termination isn't guaranteed, and even if it does happen, its timing isn't guaranteed:

        • The target process may be in a state where it cannot process the WM_CLOSE message, such as when it happens to be displaying a modal dialog at the time or happens to be stuck.
        • The target process may quietly refuse to terminate.
        • The target process may put up a modal dialog to confirm the intent to terminate, notably when trying to close an editor-like application that has an unsaved document open.
      • Therefore, if you need to ensure termination, you'll have to monitor the process for actual termination afterwards, and possibly terminate it forcefully after a suitable timeout period.

  • At the Windows API level, it doesn't matter if the targeted main window is visible or not, so that even (GUI-subsystem) processes that by design run invisibly - as GoogleDriveFS.exe appears to be - can be targeted with a WM_CLOSE message.

    • While System.Diagnostics.Process.CloseMainWindow() is designed to request graceful termination of a given process by sending a WM_CLOSE message to its main window, it unfortunately doesn't find that window if it happens to be invisible (hidden) (still applies as of .NET 6.0)

    • By contrast, the taskkill.exe utility does not have this limitation.

    • A limitation that BOTH methods share is the inability to target processes that are UWP / Microsoft Store applications.

      • The reason is that both methods rely on the EnumWindows WinAPI method, which only supports traditional desktop applications.
      • However, manually finding a UWP application's main window via FindWindowEx and posting WM_CLOSE to it, is possible.
  • Related