使用依赖项不在System或System32中的LoadDLL函数。

huangapple go评论76阅读模式
英文:

go LoadDLL with dependencies not in System or System32

问题

我正在尝试在Windows上加载一个GO库:

citect, err := syscall.LoadDLL("C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)CtApi.dll")

问题是该库还有其他依赖项在同一目录中。结果是出现错误"找不到指定的模块"。我相当确定这是因为其他DLL中存在未满足的依赖关系导致的。

是否有一种方法可以通过syscall强制指定DLL搜索路径?

更新

我认为我遇到的问题是因为我指定了LOAD_LIBRARY_SEARCH_USER_DIRS,但我尝试加载的库还需要标准搜索路径。我添加了LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,现在它给我一个有意义的句柄。

func main() {
	fmt.Println("hello")
	dllPath := "C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)"

	kernel, _ := windows.LoadDLL("kernel32.dll")
	defer kernel.Release()

	sdd, err := kernel.FindProc("SetDefaultDllDirectories")
	if err != nil {
		panic(err)
	}
	r1, _, err := sdd.Call(windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
	if r1 == 0 {
		panic(err)
	}

	addd, err := kernel.FindProc("AddDllDirectory")
	if err != nil {
		panic(err)
	}
	chars := StringToWideCharPtr(dllPath)

	r1, _, err = addd.Call(uintptr(unsafe.Pointer(chars)))
	fmt.Printf("result of add dll directory: %d\n", r1)
	if r1 == 0 {
		panic(err)
	}

	h, err := windows.LoadLibraryEx("CtApi.dll", 0, 0)

	if err != nil {
		panic(err)
	}

	fmt.Printf("library: %v\n", h)

}
英文:

I am trying to load a library from GO on windows as:

citect, err := syscall.LoadDLL("C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)CtApi.dll")

The problem is that this library has dependencies also in that directory. The result is an error "The specified module could not be found." I am pretty sure it's failing because of unmet dependencies in other DLLs.

Is there some way from syscall to force the DLL search path?

UPDATE

I think the issue I was having was because I was specifying LOAD_LIBRARY_SEARCH_USER_DIRS but the library I am trying to load needs the standard search path as well. I added LOAD_LIBRARY_SEARCH_DEFAULT_DIRS and now it gives me a Handle that makes sense.

func main() {
	fmt.Println("hello")
	dllPath := "C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)"

	kernel, _ := windows.LoadDLL("kernel32.dll")
	defer kernel.Release()

	sdd, err := kernel.FindProc("SetDefaultDllDirectories")
	if err != nil {
		panic(err)
	}
	r1, _, err := sdd.Call(windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
	if r1 == 0 {
		panic(err)
	}

	addd, err := kernel.FindProc("AddDllDirectory")
	if err != nil {
		panic(err)
	}
	chars := StringToWideCharPtr(dllPath)

	r1, _, err = addd.Call(uintptr(unsafe.Pointer(chars)))
	fmt.Printf("result of add dll directory: %d\n", r1)
	if r1 == 0 {
		panic(err)
	}

	h, err := windows.LoadLibraryEx("CtApi.dll", 0, 0)

	if err != nil {
		panic(err)
	}

	fmt.Printf("library: %v\n", h)

}

答案1

得分: 2

尝试使用golang.org/x/sys/windows包中的LoadLibraryEx函数,该函数支持LOAD_LIBRARY_SEARCH_*标志(参见使用LOAD_LIBRARY_SEARCH标志的搜索顺序)。

package main

import (
	"golang.org/x/sys/windows"
)

func main() {
	name := "C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)CtApi.dll"
	h, err := windows.LoadLibraryEx(name, 0, windows.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)
	if err != nil {
		panic(err)
	}

	dll := &windows.DLL{
		Name:   name,
		Handle: h,
	}

	// 使用dll
}

请注意,LOAD_LIBRARY_SEARCH_*标志在所有Windows版本上都不可用。请参见此处的代码注释

英文:

Try to use LoadLibraryEx in the golang.org/x/sys/windows package, which supports the LOAD_LIBRARY_SEARCH_* flags (see Search order using LOAD_LIBRARY_SEARCH flags).

package main

import (
	"golang.org/x/sys/windows"
)

func main() {
	name := "C:\\Program Files (x86)\\AVEVA Plant SCADA\\Bin\\Bin (x64)CtApi.dll"
	h, err := windows.LoadLibraryEx(name, 0, windows.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)
	if err != nil {
		panic(err)
	}

	dll := &windows.DLL{
		Name:   name,
		Handle: h,
	}

	// use the dll
}

Please note that the LOAD_LIBRARY_SEARCH_* flags are not available on all windows versions. See code comments here.

huangapple
  • 本文由 发表于 2023年4月28日 22:59:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76130844.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定