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.
- The target process may be in a state where it cannot process the
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.
taskkill.exe
offers forceful termination via its/f
option.- .NET offers forceful termination via
System.Diagnostics.Process.Kill()
- As an aside: As of PowerShell 7.2.x, the
Stop-Process
cmdlet invariably uses this method, i.e. invariably terminates processes forcefully - allowing requesting graceful termination on an opt-in basis is the subject of GitHub issue #13664.
- As an aside: As of PowerShell 7.2.x, the
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 aWM_CLOSE
message.While
System.Diagnostics.Process.CloseMainWindow()
is designed to request graceful termination of a given process by sending aWM_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 postingWM_CLOSE
to it, is possible.
- The reason is that both methods rely on the