Go: 解决"cannot use &cmdLine[0] (value of type *byte) as type *uint16" 错误
Go: 解决'cannot use &cmdLine[0] (value of type *byte) as type *uint16' 错误
在 Go 中使用 syscall.CreateProcess 函数创建进程时,可能会遇到以下错误:
..go:23:3: cannot use &cmdLine[0] (value of type *byte) as type *uint16 in argument to syscall.CreateProcess
这个错误通常是因为 cmdLine 的类型为 []byte,而 CreateProcess 函数需要的是 LPWSTR 类型,即以 NULL 结尾的 Unicode 字符串。[]byte 类型无法直接转换为 LPWSTR 类型,需要先将其转换为 []uint16 类型,再通过 unsafe.Pointer 进行类型转换。
解决方法
将 cmdLine 的类型从 []byte 改为 []uint16 即可解决该问题。修改后的代码如下:
package main
import (
"fmt"
"syscall"
"unsafe"
)
func DllMain() {
// 无用的代码
for i := 0; i < 100; i++ {
fmt.Println(i)
}
// 创建子进程
cmd := "cmd"
cmdArgs := []string{"\C", "echo", "hello world"}
cmdLine := []uint16(fmt.Sprintf("%s %s", cmd, cmdArgs))
startupInfo := &syscall.StartupInfo{}
processInformation := &syscall.ProcessInformation{}
err := syscall.CreateProcess(
nil,
(*uint16)(unsafe.Pointer(&cmdLine[0])),
nil,
nil,
false,
0,
nil,
nil,
startupInfo,
processInformation,
)
if err != nil {
fmt.Println(err)
return
}
// 等待子进程结束并获取返回值
var exitCode uint32
syscall.WaitForSingleObject(processInformation.Process, syscall.INFINITE)
syscall.GetExitCodeProcess(processInformation.Process, &exitCode)
// 无用的代码
for i := 0; i < 100; i++ {
fmt.Println(i)
}
}
func main() {
DllMain()
}
// 导出 DllMain 函数
var (
DllMainPtr = syscall.NewCallback(DllMain)
)
func init() {
// 将 DllMain 函数注册为 DLL 的入口点
handle, _ := syscall.LoadLibrary("kernel32.dll")
defer syscall.FreeLibrary(handle)
proc, _ := syscall.GetProcAddress(handle, "DllMain")
syscall.Syscall(proc, 0, 0, 1, uintptr(unsafe.Pointer(&DllMainPtr)))
}
总结
在 Go 中使用 syscall.CreateProcess 函数创建进程时,需要确保 cmdLine 的类型为 []uint16,以便正确转换为 LPWSTR 类型。
原文地址: https://www.cveoy.top/t/topic/lMQT 著作权归作者所有。请勿转载和采集!