PowerShell- cockemainwindow为所有人工作吗?

发布于 2025-01-20 02:55:09 字数 822 浏览 3 评论 0原文

我正在寻找一种方法来优雅地关闭/退出在 GoogleDriveFS 进程下运行的 GoogleDrive 应用程序。

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

像 Process.CloseMainWindow 方法适合这个吗?或者有更好的方法来确保应用程序不运行?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甚是思念 2025-01-27 02:55:09

tl;dr

System.Diagnostics.Process.CloseMainWindow()不起作用,原因在底部部分解释。

注意:

  • 如果目标进程不是从您自己的用户帐户启动的,您将需要从提升(以管理员身份运行)会话运行以下命令。

您可以尝试以下方法来实现优雅终止,但不能保证它会起作用:

# Asks all GoogleDriveFS processes to terminate, which they may or may not do.
# A status line is output to stdout for each targeted process, 
# indicating whether the termination request was successfully *sent*.
# Note: ".exe" must be used, whereas it mustn't be 
#       with PowerShell's *-Process cmdlets.
taskkill.exe /im GoogleDriveFS.exe

如果不起作用t,强制终止是您唯一的选择,最容易通过以下方式完成:

# !! Forcefully terminates all GoogleDriveFS, without cleanup.
Stop-Process -Force -Name GoogleDriveFS

注意:如下所述,Stop-Process < em>总是强行终止。 -Force 开关的唯一功能是抑制当您尝试终止属于不同用户的进程时出现的潜在确认提示(仅适用于提升)。

这是一个 < strong>首先尝试优雅终止,然后在指定的超时后回退到强制终止的片段:

$processName = 'GoogleDriveFS'
$timeOutSecs = 2

# Get all existing processes of interest.
$processes = Get-Process -ErrorAction Ignore -Name $processName

if (-not $processes) {
  Write-Verbose -Verbose "No $processName processes running."
} else {
  # Ask the processes to terminate, which they may or may not do.
  taskkill.exe /im "$processName.exe" *>$null 
  try { 
   # Wait for up to $timeOutSecs seconds for the processes to - 
   # potentially - terminate gracefully.
   $processes | Wait-Process -ErrorAction Stop -Timeout $timeOutSecs
  } catch {
    Write-Warning "Forcefully terminating (remaining) $processName processes..."
    # Note: This assumes that you don't care about any new 
    #       processes that may have launched since Get-Process was called.
    $processes | Stop-Process -Force
  }
}

  • 在 Windows 上,优雅终止基本上只是 GUI 的一个选项 -子系统应用程序,即具有主窗口(无论是否可见)的进程,因此具有可以将 WM_CLOSE 消息发布到的消息循环

    • 换句话说:您无法要求 Windows 上的控制台应用程序正常终止(除非它们实现了某种特定于应用程序的自定义机制,其他进程可以通过该机制请求终止)。

    • 对于支持的应用程序,有重要注意事项

      • 终止无法保证,即使确实发生,其时机也无法保证:

        • 目标进程可能处于无法处理 WM_CLOSE 消息的状态,例如当时恰好正在显示模式对话框或恰好被卡住。
        • 目标进程可能会悄悄拒绝终止。
        • 目标进程可能会弹出一个模式对话框来确认终止意图,特别是在尝试关闭打开了未保存文档的类似编辑器的应用程序时。
      • 因此,如果您需要确保终止,您必须在事后监控实际终止的流程,并可能会终止它< em>在适当的超时时间后强制

  • 在 Windows API 级别,目标主窗口是否可见并不重要,因此即使是按设计运行的(GUI 子系统)进程也不可见 - as GoogleDriveFS.exe 似乎是 - 可以用WM_CLOSE 消息。

    • 虽然System.Diagnostics.Process.CloseMainWindow()旨在通过发送WM_CLOSE 消息到其主窗口,不幸的是找不到该窗口如果它碰巧不可见(隐藏)(仍然适用.NET 6.0)

    • 相比之下,taskkill.exe 实用程序没有有此限制

    • 两种方法共有的一个限制是无法定位UWP/Microsoft Store 应用程序

      • 但是,这仅适用于“纯”UWP 应用(例如“设置”、“计算器”),而不适用于打包为 UWP 应用的桌面应用(例如 Windows 终端) 、Microsoft Edge)。
      • 原因是这两种方法都依赖于 EnumWindows WinAPI方法,仅支持桌面应用程序。
      • 但是,手动通过FindWindowEx 并向其发布 WM_CLOSE可能的。

tl;dr

System.Diagnostics.Process.CloseMainWindow() will not work, for the reasons explained in the bottom section.

Note:

  • If the target processes weren't started from your own user account, you'll need to run the following from an elevated (run as admin) session.

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

# Asks all GoogleDriveFS processes to terminate, which they may or may not do.
# A status line is output to stdout for each targeted process, 
# indicating whether the termination request was successfully *sent*.
# Note: ".exe" must be used, whereas it mustn't be 
#       with PowerShell's *-Process cmdlets.
taskkill.exe /im GoogleDriveFS.exe

If it doesn't, forceful termination is your only option, which is most easily accomplished with:

# !! Forcefully terminates all GoogleDriveFS, without cleanup.
Stop-Process -Force -Name GoogleDriveFS

Note: As discussed below, Stop-Process always terminates forcefully. The only function of the -Force switch is to suppress a potential confirmation prompt that is presented when you attempt to terminate processes belonging to a different user (only works with elevation).

Here's a snippet that first tries graceful termination, then falls back to forceful termination after a specifiable timeout:

$processName = 'GoogleDriveFS'
$timeOutSecs = 2

# Get all existing processes of interest.
$processes = Get-Process -ErrorAction Ignore -Name $processName

if (-not $processes) {
  Write-Verbose -Verbose "No $processName processes running."
} else {
  # Ask the processes to terminate, which they may or may not do.
  taskkill.exe /im "$processName.exe" *>$null 
  try { 
   # Wait for up to $timeOutSecs seconds for the processes to - 
   # potentially - terminate gracefully.
   $processes | Wait-Process -ErrorAction Stop -Timeout $timeOutSecs
  } catch {
    Write-Warning "Forcefully terminating (remaining) $processName processes..."
    # Note: This assumes that you don't care about any new 
    #       processes that may have launched since Get-Process was called.
    $processes | Stop-Process -Force
  }
}

  • On Windows, graceful termination is fundamentally only an option for GUI-subsystem applications, i.e. processes that have a main window (whether visible or not) and therefore 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.

      • However, this applies only to "pure" UWP applications (e.g, Settings, Calculator), and not to desktop applications packaged as UWP apps (e.g., Windows Terminal, Microsoft Edge).
      • The reason is that both methods rely on the EnumWindows WinAPI method, which only supports desktop applications.
      • However, manually finding a UWP application's main window via FindWindowEx and posting WM_CLOSE to it, is possible.
ゃ人海孤独症 2025-01-27 02:55:09

您可以做类似的事情:

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)

但是,这将提示用户确认关闭。

您也可以使用CLOSE()方法避免提示用户或kill()立即发布所有资源。

cockemainwindow()
通过向其主窗口发送密闭消息来关闭具有用户界面的过程。

close()释放与此组件相关的所有资源。

kill()立即停止相关过程。

通过

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://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=net-6.0#methods

少女七分熟 2025-01-27 02:55:09

您可以使用 GoogleDriveFS.exe--quit 参数:

"C:\Program Files\Google\Drive File Stream\64.0.4.0\GoogleDriveFS.exe" --quit

但每次软件更新后它都会中断,因此运行这个 bat 文件应该会更好  :

"%ProgramFiles%\Google\Drive File Stream\launch.bat" --quit

此 bat 文件查找最新的 GoogleDriveFS.exe 并使用与脚本相同的参数运行它。

以及来自 Powershell 的:

Start-Process -FilePath "${env:ProgramFiles}\Google\Drive File Stream\launch.bat" -ArgumentList '--quit' -Wait -NoNewWindow

You could use the --quit argument of GoogleDriveFS.exe :

"C:\Program Files\Google\Drive File Stream\64.0.4.0\GoogleDriveFS.exe" --quit

But it will break after each software update so running this bat file should be better :

"%ProgramFiles%\Google\Drive File Stream\launch.bat" --quit

This bat file looks up the latest GoogleDriveFS.exe and runs it with the same arguments as the script.

And from Powershell :

Start-Process -FilePath "${env:ProgramFiles}\Google\Drive File Stream\launch.bat" -ArgumentList '--quit' -Wait -NoNewWindow
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文