Reputation: 1
This is my code:
var command = "ping 127.0.0.1 && exit"
var sI syscall.StartupInfo
var pI syscall.ProcessInformation
argv := syscall.StringToUTF16Ptr(os.Getenv("windir")+"\\system32\\cmd.exe /C " + command)
syscall.CreateProcess(
nil,
argv,
nil,
nil,
true,
0x08000000,
nil,
nil,
&sI,
&pI)
Now I want get output result of executed code. Is there anyway?
Upvotes: 0
Views: 974
Reputation: 438
As said in the comments of the question, the best way to execute a process is to use the os/exec
package. But, if you need something very specific on windows, you can use the sys/windows
package.
In order for your child process to communicate with you parent process, you must establish a piped communication. You can find explanations about this in this C++ answer for quite the same issue : How to read output from cmd.exe using CreateProcess() and CreatePipe()
Here is the solution in go to get your child process output.
func main() {
var command = "ping 127.0.0.1 && exit"
var (
sI syscall.StartupInfo
pI syscall.ProcessInformation
stdOutPipeRead windows.Handle
stdOutPipeWrite windows.Handle
stdErrPipeRead windows.Handle
stdErrPipeWrite windows.Handle
stdInPipeRead windows.Handle
stdInPipeWrite windows.Handle
)
sa := windows.SecurityAttributes {
Length: uint32(unsafe.Sizeof(windows.SecurityAttributes{})),
SecurityDescriptor: nil,
InheritHandle: 1, //true
}
windows.CreatePipe(&stdOutPipeRead, &stdOutPipeWrite, &sa, 0)
windows.CreatePipe(&stdErrPipeRead, &stdErrPipeWrite, &sa, 0)
windows.CreatePipe(&stdWritePipeRead, &stdWritePipeWrite, &sa, 0)
sI.Flags = windows.STARTF_USESTDHANDLES
sI.StdErr = stdErrPipeWrite
sI.StdOutput = stdOutPipeWrite
sI.StdInput = stdOutPipeRead
argv := windows.StringToUTF16Ptr(os.Getenv("windir")+"\\system32\\cmd.exe /C " + command)
windows.CreateProcess(
nil,
argv,
nil,
nil,
true,
0x08000000,
nil,
nil,
&sI,
&pI)
windows.CloseHandle(stdOutPipeWrite)
windows.CloseHandle(stdErrPipeWrite)
windows.CloseHandle(stdInPipeWrite)
stdErr := readPipe(stdErrPipeRead)
stdOut := readPipe(stdOutPipeRead)
windows.CloseHandle(stdOutPipeRead)
windows.CloseHandle(stdErrPipeRead)
windows.CloseHandle(stdInPipeWrite)
}
func readPipe(pipe windows.Handle) string {
result := ""
buf := make([]byte, 1024+1)
var read int = 0
err := windows.ReadFile(pipe, &buf[0], 1024, &read), 0)
// read until you receive a broken pipe error
for err == nil {
result += string(buf[:read])
err = windows.ReadFile(pipe, &buf[0], 1024, &read), 0)
}
return result
}
Upvotes: 4