使用 syscall got "not a valid Win32 application" 调用 mono-2.0-sgen.dll

Call mono-2.0-sgen.dll with syscall got "not a valid Win32 application"

我想通过 Go 使用已发布的 Mono 框架执行 HelloWorldConsole.exe。

所以我想调用mono-2.0-sgen.dll函数"mono_main"来执行exe。 mono-2.0-sgen.dll 是 MS Windows, see.

的 PE32 可执行文件

但是我收到错误 "not a valid Win32 application"

_ = os.Setenv("MONO_PATH", `\mono\lib\mono.5;C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\Debug`)
_ = os.Setenv("MONO_CFG_DIR", `"C:\Program Files (x86)\Mono\etc"`)
_ = os.Setenv("MONO_CONFIG", `"C:\Program Files (x86)\Mono\etc\mono\config"`)

mono := `C:\Program Files (x86)\Mono\bin\mono-2.0-sgen.dll`
app := `C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\Debug\HelloWorldConsole.exe`

fmt.Println("Execute")

var mod = syscall.NewLazyDLL(mono)
var proc = mod.NewProc("mono_main")

ret, _, _ := proc.Call(0,
    uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("mono.exe"))),
    uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(app)))  )

windows.NewLazySystemDLL

相同的行为
dll := windows.NewLazySystemDLL(mono)
lazyProc := dll.NewProc("mono_main")
lazyProc.Call()

函数名称

完整错误:

panic: Failed to load C:\Program Files (x86)\Mono\bin\mono-2.0-sgen.dll: %1 is **not a valid Win32 application**.

%1 不是有效的 Win32 应用程序

错误 %1 is not a valid Win32 application 是 windows 本身对 Win32 错误代码的描述。

Win32 错误代码本身是 0x000000C1 ERROR_BAD_EXE_FORMAT,参见 docs.microsoft.com

BAD_EXE_FORMAT表示您在 x64 进程中调用 x86 dll。您必须使用 Go 的 x86 变体,例如go1.12.1.windows-386.zip 来自 https://golang.org/dl/.

现在必须将 GOROOT 和 PATH 更改为提取的 bin 文件夹,然后就可以开始了。

参数类型

当您调用 mono_main 时,您需要以正确的方式使用此函数。 如果你看一下 implementation you see that the signature is int mono_main (int argc, char* argv[]);. argc and argv is a widly used pattern, see here.

工作样本

func main() {
    _ = os.Setenv("MONO_PATH", `C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\x86\Debug\mono\lib\mono.5;C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\x86\Debug\`)
    _ = os.Setenv("MONO_CFG_DIR", `C:\DEV\HelloWorhpm.goldConsole\HelloWorldConsole\bin\x86\Debug\mono\etc`)
    _ = os.Setenv("MONO_CONFIG", `C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\x86\Debug\mono\etc\mono\config`)

    _ = os.Chdir(`C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\x86\Debug\`)

    mono := `C:\DEV\HelloWorldConsole\HelloWorldConsole\bin\x86\Debug\mono\bin\mono-2.0-sgen.dll`

    // https://github.com/mono/mono/blob/c5b88ec4f323f2bdb7c7d0a595ece28dae66579c/mcs/tools/mkbundle/template_main.c#L1
    dll := windows.NewLazySystemDLL(mono)
    lazyProc := dll.NewProc("mono_main")

    dotNetAssembly := []byte(`HelloWorldConsole.exe`)

    var argumentData [260]byte
    ptr := unsafe.Pointer(&argumentData)

    copy(argumentData[:], dotNetAssembly)

    args := [2]uintptr{0, uintptr(ptr)}

    _, _, _ = lazyProc.Call(2, uintptr(unsafe.Pointer(&args)))
}