Win32可执行文件dll依赖搜索规则

MSDN的dll搜索规则

这是来自MSDN的dll搜索规则表述: standard-search-order-for-desktop-applications
核心内容翻译一下:
从Windows XP SP2开始,SafeDllSearchMode默认是处于开启状态。如果想将该模式关闭,可以通过将注册表HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode值设置为0。如果使用 SetDllDirectory函数设置dll搜索路径,也会自动禁用SafeDllSearchMode。
当SafeDllSearchMode启用时,dll搜索规则如下:

  1. 应用程序所在目录。
  2. 使用GetSystemDirectory获得的路径,一般是C:\Windows\System32目录。
  3. 16位系统文件所在目录,一般是C:\Windows\System目录。
  4. 使用GetWindowsDirectory获得的路径,一般是 C:\Windows目录。
  5. 当前目录。(指应用程序启动时工作目录)
  6. PATH环境变量指定的路径,但不包含 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths中PATH的值。

当SafeDllSearchMode被禁用时,dll搜索规则如下:

  1. 应用程序所在目录。
  2. 当前目录。(指应用程序启动时工作目录)
  3. 使用GetSystemDirectory获得的路径,一般是C:\Windows\System32目录。
  4. 16位系统文件所在目录,一般是C:\Windows\System目录。
  5. 使用GetWindowsDirectory获得的路径,一般是 C:\Windows目录。
  6. PATH环境变量指定的路径,但不包含 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths中PATH的值。

其实比较下来会发现,SafeDllSearchMode是否启用只影响应用程序启动时工作目录的优先级,搜索路径不会变多或变少。

PATH环境变量的扩展思路

无论SafeDllSearchMode是否启动,第6条搜索顺序始终是来自于PATH环境变量。但是PATH环境变量来自于3个地方:系统级别环境变量,用户级别环境变量。具体为

 

但是还有一个地方隐藏的比较深。其实是进程自身维护的环境变量,这样修改进程自身环境变量不影响其他进程。
以下测试代码在win7和win10上测试通过:

package main

import (
    "fmt"
    "os"
    "syscall"
)

func main() {
    path := os.Getenv("PATH")
    newPath := fmt.Sprintf("%s;%s", "C:\\test", path )
    os.Setenv("PATH", newPath)
    //C:\test会被加入到dll搜索路径
    syscall.LoadLibrary("non-exist.dll")
}

SetDllDirectory函数

SetDllDirectory是另外一种不改变其他进程dll搜索规则的方案:
以下测试代码在win7和win10上测试通过:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func setDLLSearchDirectory(dir string) (err error) {
    kernel32, err := syscall.LoadLibrary("kernel32.dll")
    if err != nil {
        return
    }
    defer syscall.FreeLibrary(kernel32)
    procSetDllDirectoryW, err := syscall.GetProcAddress(kernel32, "SetDllDirectoryW")
    if err != nil {
        return
    }
    pathW,err := syscall.UTF16PtrFromString(dir)
    if err != nil {
        return
    }
    _, _, callErr := syscall.Syscall(procSetDllDirectoryW, 1, uintptr(unsafe.Pointer(pathW)), 0, 0)
    if callErr != 0 {
        err = fmt.Errorf("SetDllDirectoryW error", callErr)
    }
    return
}

func main() {
    err := setDLLSearchDirectory("C:\\test1")
    if err == nil {
        syscall.LoadLibrary("non-exist.dll")
    } else {
        fmt.Println("setDLLSearchDirectory error:", err.Error())
    }
}



作者:cracker_zhou
链接:https://www.jianshu.com/p/5df20de7be54
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将在 Windows 10 上运行的程序移植到 Windows 7 上可能会遇到 DLL 缺失的问题,这是因为不同版本的操作系统可能使用不同的 DLL 文件或版本。 在这种情况下,你可以尝试以下方法来解决 DLL 缺失问题: 1. 确认程序的兼容性:首先,确保你的程序是与 Windows 7 兼容的。检查程序的系统要求和兼容性说明,确保它可以在 Windows 7 上运行。 2. 安装程序的依赖项:有些程序需要额外的依赖项(如运行时库),这些依赖项中可能包含了特定的 DLL 文件。查找程序的官方网站或文档,找到与程序一起提供的依赖项,并按照说明进行安装。 3. 更新操作系统:确保你的 Windows 7 系统已经安装了最新的更新补丁。这可以帮助修复系统 DLL 文件的错误,并提供更好的兼容性。 4. 寻找并下载缺失的 DLL 文件:如果仍然缺少某些 DLL 文件,你可以尝试在互联网上搜索并下载这些缺失的 DLL 文件。但是,请务必小心,确保从可信的来源下载文件,并且文件与你的操作系统和程序版本兼容。 5. 使用兼容性模式:Windows 7 提供了兼容性模式,你可以尝试将程序设置为以 Windows 7 兼容模式运行。右键点击程序的可执行文件(.exe),选择 "属性",然后在 "兼容性" 选项卡中选择 "以兼容模式运行此程序",并选择 Windows 7。 6. 寻求专业帮助:如果上述方法仍无法解决问题,你可能需要寻求专业人士的帮助。他们可能能够提供更具体的解决方案或修复程序的兼容性问题。 请注意,移植程序到不同操作系统可能会涉及到更多的问题,例如系统架构的差异或其他兼容性问题。因此,在进行此类操作之前,最好对程序进行彻底的测试和验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值