英文:
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()
可执行文件被启动,但显示以下内容:
写入安装信息到磁盘时发生错误。
请检查是否有足够的磁盘空间。
请参见此处的截图:
让我感到困惑的是,正如您在截图中所看到的,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:
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-inecho
command of cmd.exe prints it’s value. - If the environment variable
my_env_var
is not defined, the built-inecho
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论