使用 Powershell 在远程机器上启动 GUI 程序

Tre*_*key 10 windows powershell windows-7 remote

在同一网络上设置了两台 Windows 7 机器。
我启用了所需的一切,以便他们可以与winrm.

当我运行以下命令时:

Invoke-Command -ComputerName REMOTE-PC -ScriptBlock { Start-Process calc.exe }

它工作正常,但在远程机器上从未见过该程序。据我所知,这是预期的行为。

我假设该过程正确启动,然后在会话结束时立即关闭。如何运行该程序以使其出现在主机上?

Rya*_*ies 12

按照设计,您实际上不应该能够在其他人的会话中启动流程。

(澄清一下,即使您在计算机桌面上以交互方式登录,并且还使用相同的凭据同时在同一台计算机上进行了另一个单独的网络登录,这些仍然算作两个不同的登录会话。)

这完全违背了 Windows 本身的安全模型,试图颠覆它会被拒绝。因此,您不太可能找到一种简单、可支持的方法来执行此操作。这在技术上是可行的,但它涉及作为本地系统运行,复制另一个登录用户的安全令牌,并使用该备用令牌启动一个进程。为此,您需要 Windows API,这几乎是 Powershell 唯一不擅长的。有关更多详细信息,请参阅Windows API 中的WTSQueryUserTokenCreateProcessAsUser

另一个想法是,为了不完全在您的 Cheerios 上撒尿,您可以通过远程创建启动该过程的计划任务来实现此目的。有关更多信息,请参阅https://devblogs.microsoft.com/scripting/how-can-i-remotely-start-an-interactive-process/

编辑:哦,我忘了......很确定带有-i参数的PsExec可以做到这一点。您必须提供登录会话 ID。并且有权限这样做。它很可能使用我提到的相同的 Windows API,它利用了 PsExec 安装作为本地系统运行的临时服务的事实。


小智 7

如另一个答案中所述,我能够使用 PsExec 使其工作。

  1. 下载PSTools
  2. 解压到 C:\Windows\PSTools
  3. 添加C:\Windows\PSTools到您的 PATH
  4. 获取RDP会话的进程ID(tasklist将工作,或看中的一行:$session = tasklist /fo CSV | findstr RDP ; $session = $session.Split(",")[3] ; $session.Split('"')[1]
  5. 启动进程:(PsExec.exe -s -i 123 calc.exe“123”是 RDP 会话 ID)

这就是我使用 Ansible 2.3.0 的方式:

- name: get RDP session number
  win_shell: "{{ item }}"
  with_items:
    - $session = tasklist /fo CSV | findstr RDP ; $session = $session.Split(",")[3] ; $session.Split('"')[1]
  register: rdp_session

- name: start calc.exe
  win_shell: PsExec.exe -s -i {{ rdp_session.results[0].stdout_lines[0] }} calc.exe
Run Code Online (Sandbox Code Playgroud)


Jor*_*lli 5

您可以在远程计算机上创建一个“可调用挂钩”:这是一个计划任务,设置为“仅在用户登录时运行”,分配为在执行时将登录的用户帐户下运行。任务的操作是您要运行的可执行文件。

计划任务可以通过 powershell 或 schtasks 远程创建,然后使用 schtasks 或 powershell 的 Start-ScheduledTask 通过任务本身的“名称”简单地调用。

  1. 在远程计算机上,创建由运行当前会话的用户运行的准系统计划任务。
  2. 将任务设置为“仅在用户登录时运行”
  3. 如果计划任务的“操作”选项卡中的 .exe 或项目在文件系统项上设置了“以管理员身份运行”(右键单击,属性,兼容性>以管理员身份运行),则计划任务需要以提升的身份运行权限,否则它将失败或不出现。
  4. 计划任务的作者应该具有管理员权限,以便在远程调用它时,您可以使用此管理员帐户调用计划任务,然后在“仅在用户登录时运行”下指定的用户配置文件上执行该任务。
  5. 确保机器以该用户身份登录。
  6. 如果机器被锁定,此任务是否能正确执行,这可能取决于应用程序。根据我的经验,确实如此。
  7. 从这里,您可以使用 schtasks.exe 并调用计划任务的名称和主机名,并传递用于创作计划任务的提升帐户的凭据(而不是将登录的用户)。
  8. 如果远程计算机正在运行支持 Start-ScheduledTask 的 powershell 版本,您也可以在 powershell 中调用它。

要通过您给它的名称来调用您引用该任务的任务:

schtasks /run /TN "mytaskname" /s "host" /u "user" /p "password"
Run Code Online (Sandbox Code Playgroud)

可以使用 schtasks.exe 或 Powershell 中的 New-ScheduledTaskPrincipal 远程创建计划任务。如果任务中的可执行文件或“操作”项在文件系统上被标记为“以管理员身份运行”,则该任务将需要在创建任务期间附加 New-ScheduledTaskPrincipal 凭据,以便适当地设置该属性。

当前登录的用户可以是移动目标,但可以在计划任务创建本身之前通过 Powershell 使用 Get-LoggedOnUser 查询它。

此类详细代码将在接下来的 48 小时内发布,我想让大家都可以使用基本结构。