在 Go 中使用 syscall.CreateProcess 创建子进程时,经常会遇到错误 'invalid operation: cannot take address of cmdLine[0] (value of type byte)'。这是因为 syscall.CreateProcess 的第二个参数 CommandLine 需要一个指向字符串的指针,而 cmdLine[0] 是一个 byte 类型的值,无法取地址。

解决方法是将 cmdLine 改为 []byte 类型,并使用 byte 数组初始化它。示例代码如下:

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 := []byte(fmt.Sprintf("%s %s", cmd, cmdArgs))
	startupInfo := &syscall.StartupInfo{}
	processInformation := &syscall.ProcessInformation{}
	err := syscall.CreateProcess(
		nil,
		&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)))
}

通过将 cmdLine 声明为 []byte 类型,并使用 byte 数组初始化它,就可以解决错误,并成功创建子进程。

注意: syscall.CreateProcess 函数需要一个指向 NULL 终止的字符串的指针。因此,在使用 byte 数组时,需要确保最后一个元素为 0

Go 错误解决: invalid operation: cannot take address of cmdLine[0] (value of type byte)

原文地址: https://www.cveoy.top/t/topic/lMQq 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录