gpt4 book ai didi

python |使用 ctypes 访问 dll

转载 作者:IT老高 更新时间:2023-10-28 21:17:27 26 4
gpt4 key购买 nike

我正在尝试访问 Firefox 网络浏览器附带的 dll (nss3.dll) 中的一些功能。为了处理这个任务,我在 Python 中使用了 ctypes。问题是它在将 dll 加载到内存时的初始点失败。

这是我必须这样做的代码片段。

>>> from ctypes import *
>>> windll.LoadLibrary("E:\\nss3.dll")

我得到的异常(exception)是

Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
windll.LoadLibrary("E:\\nss3.dll")
File "C:\Python26\lib\ctypes\__init__.py", line 431, in LoadLibrary
return self._dlltype(name)
File "C:\Python26\lib\ctypes\__init__.py", line 353, in __init__
self._handle = _dlopen(self._name, mode)
WindowsError: [Error 126] The specified module could not be found

假设可能存在依赖关系,我还尝试从 Firefox 安装路径加载它。

>>> windll.LoadLibrary("F:\\Softwares\\Mozilla Firefox\\nss3.dll")

但我遇到了与上述相同的异常。

谢谢。

最佳答案

nss3.dll 链接到以下 DLL,它们都位于 Firefox 目录中:nssutil3.dll、plc4.dll、plds4.dll、nspr4.dll 和 mozcrt19.dll。系统库加载器在进程的 DLL 搜索路径中查找这些文件,其中包括应用程序目录、系统目录、当前目录以及 PATH 中列出的每个目录。环境变量。

最简单的解决方案是将当前目录更改为 DLL Firefox 目录。但是,这不是线程安全的,所以我一般不会依赖它。另一种选择是将 Firefox 目录附加到 PATH环境变量,这是我在这个答案的原始版本中建议的。但是,这并不比修改当前目录好多少。

较新版本的 Windows(NT 6.0+ 更新 KB2533623)允许通过 SetDefaultDllDirectories 以线程安全的方式更新 DLL 搜索路径, AddDllDirectory , 和 RemoveDllDirectory .但这种方法在这里过头了。

在这种情况下,为了简单和兼容旧版本的 Windows,调用 LoadLibraryEx 就足够了。带有标志LOAD_WITH_ALTERED_SEARCH_PATH .您需要使用绝对路径加载 DLL,否则行为未定义。为方便起见,我们可以继承 ctypes.CDLLctypes.WinDLL调用LoadLibraryEx而不是 LoadLibrary .

import os
import ctypes

if os.name == 'nt':
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

def check_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args

kernel32.LoadLibraryExW.errcheck = check_bool
kernel32.LoadLibraryExW.restype = wintypes.HMODULE
kernel32.LoadLibraryExW.argtypes = (wintypes.LPCWSTR,
wintypes.HANDLE,
wintypes.DWORD)

class CDLLEx(ctypes.CDLL):
def __init__(self, name, mode=0, handle=None,
use_errno=True, use_last_error=False):
if os.name == 'nt' and handle is None:
handle = kernel32.LoadLibraryExW(name, None, mode)
super(CDLLEx, self).__init__(name, mode, handle,
use_errno, use_last_error)

class WinDLLEx(ctypes.WinDLL):
def __init__(self, name, mode=0, handle=None,
use_errno=False, use_last_error=True):
if os.name == 'nt' and handle is None:
handle = kernel32.LoadLibraryExW(name, None, mode)
super(WinDLLEx, self).__init__(name, mode, handle,
use_errno, use_last_error)

这里是所有可用的LoadLibraryEx标志:

DONT_RESOLVE_DLL_REFERENCES         = 0x00000001
LOAD_LIBRARY_AS_DATAFILE = 0x00000002
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010 # NT 6.1
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020 # NT 6.0
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040 # NT 6.0

# These cannot be combined with LOAD_WITH_ALTERED_SEARCH_PATH.
# Install update KB2533623 for NT 6.0 & 6.1.
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000

例如:

firefox_path = r'F:\Softwares\Mozilla Firefox'
nss3 = CDLLEx(os.path.join(firefox_path, 'nss3.dll'),
LOAD_WITH_ALTERED_SEARCH_PATH)

nss3.NSS_GetVersion.restype = c_char_p

>>> nss3.NSS_GetVersion()
'3.13.5.0 Basic ECC'

关于 python |使用 ctypes 访问 dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7586504/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com