【问题标题】:Gracefully closing a process in a remote Session优雅地关闭远程会话中的进程
【发布时间】:2013-01-04 09:44:39
【问题描述】:

我目前正在编写一个小 PowerShell 脚本来重置远程计算机上的用户 Outlook 配置文件。

在完成必要的配置文件之前,我想检查 Outlook 是否已经在远程计算机上运行,​​如果是,请优雅地停止它。我不想终止该进程,以便它可以进行必要的清理和同步。

当我使用管理员用户连接到机器并执行以下命令时:

Enter-PSSession $remoteMachine
$outlookProcess = Get-Process outlook
$outlookProcess.CloseMainWindow()

我只会得到

False

作为“返回值”

终止进程:

Stop-Process $outlookProcess

有效。

我试图关闭的进程不是由我连接的管理用户启动的,所以起初我认为我可能不允许在这个用户上下文中进行操作,但是如果我在本地机器上做同样的事情(以“普通”用户启动进程,然后将 CloseMainWindow() 与管理用户一起使用)它会毫无问题地关闭进程。

所以我的问题是如何优雅地关闭这个远程进程?

【问题讨论】:

  • 在您的本地测试中,两个登录是否在同一个 Windows 会话中? (GUI 元素的范围——包括向窗口发送关闭消息——受会话限制。您可以通过在进程资源管理器中添加“会话”列或在任务管理器中添加“会话 ID”来查看哪个进程在哪个进程中。 )
  • 是的,我在切换用户后尝试了相同的操作,现在我收到了相同的错误消息。那么有什么方法可以关闭进程而不直接杀死它呢?
  • 答案是否定的,因为没有在与 Outlook 相同的会话中运行的东西。

标签: powershell process kill powershell-remoting


【解决方案1】:

要正常关闭 Windows 应用程序,请向应用程序发送 WM_CLOSE 消息。只要用户没有修改状态会导致应用弹出 UI 询问是否应保存更改,这应该可以工作。这是一个示例,展示了如何关闭记事本应用程序 - 只要没有未保存的更改即可再次关闭。

$src = @'
using System;
using System.Runtime.InteropServices;
public static class Win32 {
    public static uint WM_CLOSE = 0x10;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
}
'@

Add-Type -TypeDefinition $src
$zero = [IntPtr]::Zero
$p = @(Get-Process Notepad)[0]
[Win32]::SendMessage($p.MainWindowHandle, [Win32]::WM_CLOSE, $zero, $zero) > $null

【讨论】:

  • 这看起来与 $myProcess.CloseMainWindow() 提供的行为相同。遗憾的是,这也仅在运行这些命令的进程在同一个 Windows 会话中运行时才有效。如果我在远程会话中尝试此操作(并且不要将输出重新路由到 $null),我只会返回一个“0”,但记事本窗口仍然保持打开状态。 (我没有进行任何未保存的更改。)
猜你喜欢
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多