我正在try 使用它们的AppID启动Windows应用程序,例如我拨打Get-StartApps获得的Microsoft.WindowsCalculator_8wekyb3d8bbwe!App

目前我可以启动应用程序,但无法获得正确的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?

推荐答案

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), "%d\n", &pid)

  • In principle, you can pass 100 to PowerShell's 101 (102) cmd, which returns a process-info object that has an 103 property containing the launched process' PID,并输出后者.

  • Unfortunately, with UWP / AppX applications specifically, such as Calculator, this does not work, which is a problem that exists in the underlying .NET APIs,最低版本为.NET 6.0-参见GitHub issue #10996.

你可以try 以下workaround种方法:

  • 使用Start-Process启动appx应用程序,这会间接创建一个名为Calculator的进程.

    • 如果在启动Calculator后运行(Get-Process *calc*).Name,您可以自己识别此名称.Get-Process *calc* | Select-Object Name, Path也会显示可执行文件的路径,但请注意,该可执行文件应该被视为实现细节,并且可以直接调用not.
  • 返回这Calculator个进程的ID.事实上,Calculator在给定的用户会话中只创建one个这样的进程,这实际上使得识别该进程变得很容易.

    • 注意,这意味着可以返回preexisting计算器进程的ID,然而,这is是正确的,因为由Start-Process启动的transient进程只是将新计算器窗口的创建委托给现有进程.

    • 如果您想要标识新创建的window,则需要做更多的工作:您必须枚举进程的窗口,并标识具有最高z顺序的窗口.

PowerShell代码:

# 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

请注意,我使用URL方案calculator:作为启动计算器的更简单方法.

注:

  • Where-Object SessionId -eq (Get-Process -ID $PID).SessionId防止错误地认为other userstheir own sessions中创建了潜在的Calculator个进程(Get-Process跨所有用户会话返回在本地计算机上运行的all个进程).通过.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"

Go相关问答推荐

具有GRPC的RBAC(基于角色的访问控制)-网关生成的REST风格的API

由于索引器压缩比限制,扫描包含golang包的图像时,伪影XRAY失败

如何将GoFr筛选器用于查询参数?

如果第一次匹配条件,如何跳过切片中的值

在 GoLang 中对自定义 struct 体数组进行排序

无法从主域访问子域:无Access-Control-Allow-Origin

如何使用 GolangCI 删除未使用的导入

Go:如何在将 float64 转换为 float32 时判断精度损失

Get 请求在 Thunder 客户端/Postman 中返回数据,但在 Golang 代码中给出空白数据

如何确定作为函数参数传递的指针是否正在被修改或副本是否正在被修改?

go-echo中如何防止+转义

go:embed 文件扩展名模式

无法在 GORM 中排序

Go GCP 同时模拟两个服务帐户

golang 如何从字符串中查找表情符号?

Golang - 使用正则表达式提取链接

gob 解码器仅返回数组中的第一个元素

正则表达式处理数字签名的多个条目

Gin中测试模式有什么用

有没有一种方法可以确保传递的值具有使用泛型的某些字段?