使用AppID在Windows中启动应用程序并获取进程ID。

huangapple go评论88阅读模式
英文:

Launch Applications in WIndows using AppID and get the pid

问题

我正在尝试使用应用程序的AppID(例如Microsoft.WindowsCalculator_8wekyb3d8bbwe!App)来启动Windows应用程序,我通过调用Get-StartApps来获取AppID。

目前我可以启动应用程序,但无法获取正确的PID。

cmd = exec.Command("powershell", "start", `shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App`)
err := cmd.Start()
fmt.Println(cmd.Process.Pid)

这将返回powershell的PID。

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe start shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App

有没有办法通过AppID启动应用程序并仍然获取正确的PID?

英文:

I'm trying to launch Windows applications using their AppID such as Microsoft.WindowsCalculator_8wekyb3d8bbwe!App which I get by calling Get-StartApps

Currently I can launch the applications but can't get the correct PID

cmd = exec.Command("powershell", "start", `shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App`)
err := cmd.Start()
fmt.Println(cmd.Process.Pid)

This returns the PID of powershell

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe start shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App

Is there a way to launch the application by the AppID and still get the correct PID?

答案1

得分: 3

tl;dr

// 让 PowerShell 不仅启动计算器,还要确定并输出其 PID,如下一节所述。
out, _ := 
        exec.Command(
          `powershell.exe`, 
          `-NoProfile`, 
          `-Command`, 
          `Start-Process -ErrorAction Stop calculator: ; (Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID`,
        ).Output()

// 将包含 PID 的 stdout 输出解析为整数
var pid int
fmt.Sscanf(string(out), "%d\n", &pid)

  • 原则上,你可以在 PowerShell 的 Start-Process (start) 命令中传递 -PassThru,它会返回一个包含启动进程 PID 的进程信息对象,并将其输出

  • 然而,对于特定的 UWP / AppX 应用程序,比如计算器,这种方法不起作用,这是底层 .NET API 的一个问题,至少在 .NET 6.0 之前如此 - 参见 GitHub 问题 #10996

你可以尝试以下 解决方法

  • 使用 Start-Process 启动 AppX 应用程序,这将间接创建一个名为 Calculator(Windows 10)/ CalculatorApp(Windows 11)的进程。

    • 如果你启动计算器后运行 (Get-Process *calc*).Name,你可以自己确定这个名称。Get-Process *calc* | Select-Object Name, Path 还会显示可执行文件路径,但请注意,这个可执行文件应该被视为实现细节,不能直接调用。
  • 返回该 Calculator / CalculatorApp 进程的 ID。计算器在给定的用户会话中只会创建一个这样的进程,这使得识别该进程变得容易。

    • 请注意,这意味着可能会返回一个 已存在的 计算器进程的 PID,然而,这是正确的,因为 Start-Process 启动的 临时 进程只是将创建新的计算器窗口的任务委托给现有进程。

    • 如果你想要识别新创建的 窗口,则需要更多的工作:你需要枚举进程的窗口,并识别最高 z-order 的窗口。

PowerShell 代码(注意:在 Windows 11 中,将 Calculator 替换为 CalculatorApp):

# 启动计算器 - 它可能会重用现有实例并仅创建一个新的 *窗口* - 并报告 PID。
Start-Process -ErrorAction Stop calculator:
(Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID

<sup>请注意,我使用了 URL 方案 calculator: 作为启动计算器的简单方法。</sup>

注意:

  • Where-Object SessionId -eq (Get-Process -ID $PID).SessionId 防止错误地将由_其他用户_在_他们自己的会话_中创建的潜在 Calculator 进程考虑在内(Get-Process 返回在本地机器上运行的_所有_进程,跨越所有用户会话)。通过 .SessionID 进行过滤,即通过活动用户会话(窗口站),可以解决这个问题。

作为 PowerShell CLI 调用:

powershell.exe -NoProfile -Command "Start-Process -ErrorAction Stop calculator: ; (Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID"
英文:

tl;dr

// Make PowerShell not only launch Calculator, but also
// determine and output its PID, as described in the next section.
out, _ := 
        exec.Command(
          `powershell.exe`, 
          `-NoProfile`, 
          `-Command`, 
          `Start-Process -ErrorAction Stop calculator: ; (Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID`,
        ).Output()

// Parse stdout output, which contains the PID, into an int
var pid int
fmt.Sscanf(string(out), &quot;%d\n&quot;, &amp;pid)

  • In principle, you can pass -PassThru to PowerShell's Start-Process (start) cmd, which returns a process-info object that has an .Id property containing the launched process' PID, and output the latter.

  • Unfortunately, with UWP / AppX applications specifically, such as Calculator, this does not work, which is a problem that exists in the underlying .NET APIs, up to at least .NET 6.0 - see GitHub issue #10996.

You can try the following workaround:

  • Launch the AppX application with Start-Process, which indirectly creates a process whose name is Calculator (Windows 10) / CalculatorApp (Windows 11).

    • You can identify this name yourself if you run (Get-Process *calc*).Name after launching Calculator. Get-Process *calc* | Select-Object Name, Path would show the executable path too, but note that this executable should be considered an implementation detail and can not be invoked directly.
  • Return the ID of that Calculator / CalculatorApp process. The fact that Calculator only ever creates one such process in a given user session actually makes identifying that process easy.

    • Note that this means that the PID of a preexisting Calculator process may be returned, which, however, is the correct one, because the transient process launched by Start-Process simply delegates creation of a new Calculator window to an existing process.

    • If you wanted to identify the newly created window, more work would be required: You'd have to enumerate the process' windows and identify the one with the highest z-order.

PowerShell code (note: in Windows 11, replace Calculator with CalculatorApp):

# Launch Calculator - which may reuse an existing instance and
# merely create a new *window* - and report the PID.
Start-Process -ErrorAction Stop calculator:
(Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID

<sup>Note that I've used the URL scheme calculator: as a simpler way to launch Calculator.</sup>

Note:

  • The Where-Object SessionId -eq (Get-Process -ID $PID).SessionId guards against mistakenly considering potential Calculator processes created by other users in their own sessions (Get-Process returns all processes running on the local machine, across all user sessions). Filtering by .SessionID, i.e. by the active user session (window station), prevents this problem.

As a PowerShell CLI call:

powershell.exe -NoProfile -Command &quot;Start-Process -ErrorAction Stop calculator: ; (Get-Process Calculator | Where-Object SessionId -eq (Get-Process -ID $PID).SessionId).ID&quot;

huangapple
  • 本文由 发表于 2022年9月12日 23:36:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/73691755.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定