Prevent Escaping exec.Command Arguments in Go
In Go, I was trying to add the ability to run administrative installations in my project on GitHub: Portable App Creator.
The actual command I need the Go application to run on Windows is:
msiexec /a "package.msi" TARGETDIR="C:\test folder"
Edit on 5/6/2016: It looks like there are applications that parse arguments differently depending on the compiler. Source. The application, msiexec.cmd (and cmd.exe), handle spaces and quotes differently than how Go escapes them.
In Go, the exec package references the syscall package that escapes the arguments using this func: EscapeArg().
Luckily, there is a way around that escape func. Look at the note for SysProcAttr.CmdLine:
type SysProcAttr struct {
HideWindow bool
CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
CreationFlags uint32
}
We can manually set CmdLine and then assign it to Cmd.SysProcAttr like this:
// Set the file and directory name
msiFile := `package.msi`
targetDir := `C:\test folder`
// Set to the misexec application, but don't pass command line arguments
cmd := exec.Command("msiexec")
// Manually set the command line arguments so they are not escaped
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: false,
CmdLine: fmt.Sprintf(` /a "%v" TARGETDIR="%v"`, msiFile, targetDir), // Leave a space at the beginning
CreationFlags: 0,
}
// Run the install
err := cmd.Run()
if err != nil {
log.Fatalln(err)
}
I submitted an issue to Go for clarification: 15566
Here are other articles for reference: