如何在Go语言中在Windows上启动外部可执行文件

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

How to launch an external executable on windows in go

问题

我正在尝试使用Go在Windows上启动一个外部可执行文件(msi驱动程序安装程序)。它的相对路径是bin\launchme.msi

目前,我正在使用commander-cli/cmd库,并且它在其他外部可执行文件(尽管只是命令行可执行文件)上运行良好。

我的命令是:

c := cmd.NewCommand(`bin\launchme.msi`)
c.Execute()

可执行文件被启动,但显示以下内容:

写入安装信息到磁盘时发生错误。
请检查是否有足够的磁盘空间。

请参见此处的截图:

如何在Go语言中在Windows上启动外部可执行文件

让我感到困惑的是,正如您在截图中所看到的,msi安装程序在工作目录中创建了一个%SystemDrive%文件夹。
该文件夹又包含一个Program Files文件夹和一些其他子文件夹。

另外,如果我只是双击运行msi安装程序,一切都正常,不会出现错误。

非常感谢您对此的任何帮助。

英文:

I am trying to launch an external executable (msi driver installer) on windows with go. It is referred to with the relative path bin\launchme.msi

As of now, I am using the commander-cli/cmd library and it is working well with other external executable (though only command line ones).

My command is:

c := cmd.NewCommand(`bin\launchme.msi`)
c.Execute()

The executable is launched but displays the following:

An error occurred while writing installation information to disk. 
Check to make sure enough disk space is available."

See here:

如何在Go语言中在Windows上启动外部可执行文件

What is especially confusing to me is that, as you can see on the screenshot, the msi installer created a %SystemDrive% folder in the working directory.
This folder in turn contains a Program Files folder and some more subfolders.

Otherwise, if I simply launch the msi installer by double-clicking it, everything is fine, no error occurs.

Any help with this would be greatly appreciated.

答案1

得分: 2

可能是因为你的 .MSI 文件在后台使用了 cmd.exe。

如果在 cmd.exe 中输入 echo %my_env_var%,有两种情况可能发生:

  • 如果环境变量 my_env_var 被定义了,cmd.exe 的内置 echo 命令会打印出它的值。
  • 如果环境变量 my_env_var 没有被定义,cmd.exe 的内置 echo 命令会直接打印 %my_env_var%

每个进程都会继承其父进程的环境变量。如果一个进程是从(Windows)文件资源管理器(explorer.exe)或者从 Windows 的图形界面(也是 explorer.exe)启动的,那么它会继承系统的环境变量设置。

看起来你的库在从可执行文件 bin\launchme.msi 启动新进程时丢失了一些环境变量,比如 SystemDrive

尝试使用 Go 标准库中的 import("os/exec"),具体可以参考 https://pkg.go.dev/os/exec

关于 Microsoft Windows 中的环境变量的更多信息,请参考:https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables

提示:
你可以使用 Process Explorer (procexp.exe) 来查看正在运行的进程的环境变量,具体操作如下:

  • 打开 Process Explorer,获取正在运行的进程列表

  • 右键点击你感兴趣的进程,打开上下文菜单

  • 在上下文菜单中点击 Preferences

  • 在新窗口中点击 Environment 选项卡。

英文:

It could be, that your .MSI file is using cmd.exe in the background.

If you type echo %my_env_var% in cmd.exe, there are two cases what can happen:

  • If the environment variable my_env_var is defined, the built-in echo command of cmd.exe prints it’s value.
  • If the environment variable my_env_var is not defined, the built-in echo command of cmd.exe prints %my_env_var% literally.

Every process inherits the environment variables of it’s parent process. If a process is started from the (Windows) File Explorer (explorer.exe) or from the (graphical) shell of Windows (also explorer.exe), then it inherits the system settings for environment variables.

It seems like your library is dropping some environment variables like SystemDrive when starting a new process from the executable bin\launchme.msi.

Try to use import("os/exec") from the Go standard library https://pkg.go.dev/os/exec .

For more information about environment variable in Microsoft Windows see for example: https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables

Tip:
You can use Process Explorer (procexp.exe) to see the environment variables of running processes, by doing this:

  • Open Process Explorer, to get a list of running processes
  • Right-click on the process you are intrested in, to open the context menu
  • In the context menu click on Preferences
  • In the new window click on the Tab Environment.

答案2

得分: 0

一个解决方法,用于测试,是将该Go程序在C:\作为工作目录启动:

// captured是所有执行的源代码的输出结果
// fnResult包含执行函数的结果
captured, fnResult := cmd.CaptureStandardOut(func() interface{} {
    c := NewCommand("C:\path\to\bin\launchme.msi", cmd.WithWorkingDir("C:\\"))
    err := c.Execute()
    return err
})

// 打印“hello”
fmt.Println(captured)
英文:

one workaround, for testing, would be to launch that Go program in C:\ as working directory:

// caputred is the captured output from all executed source code
// fnResult contains the result of the executed function
captured, fnResult := cmd.CaptureStandardOut(func() interface{} {
    c := NewCommand("C:\path\to\bin\launchme.msi", cmd.WithWorkingDir("C:\\")
    err := c.Execute()
    return err
})

// prints "hello"
fmt.Println(captured)

huangapple
  • 本文由 发表于 2021年12月8日 04:43:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/70266724.html
匿名

发表评论

匿名网友

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

确定