nss3.dll está vinculado a las siguientes DLL, que están todas ubicadas en el directorio de Firefox: nssutil3.dll, plc4.dll, plds4.dll, nspr4.dll y mozcrt19.dll. El cargador de la biblioteca del sistema busca estos archivos en la ruta de búsqueda de DLL del proceso, que incluye el directorio de la aplicación, los directorios del sistema, el directorio actual y cada uno de los directorios enumerados en la variable de entorno PATH
.
La solución más simple es cambiar el directorio actual al directorio DLL Firefox. Sin embargo, eso no es seguro para subprocesos, por lo que no confiaría en él en general. Otra opción es agregar el directorio de Firefox a la variable de entorno PATH
, que es lo que sugerí en mi versión original de esta respuesta. Sin embargo, eso no es mucho mejor que modificar el directorio actual.
versiones más recientes de Windows NT 6.0 o superior (con la actualización KB2533623) permiten la ruta de búsqueda de DLL que se actualicen de forma segura para los subprocesos a través de SetDefaultDllDirectories
, AddDllDirectory
y RemoveDllDirectory
. Pero ese enfoque sería exagerado aquí.
En este caso, por razones de simplicidad y compatibilidad con las versiones anteriores de Windows, basta con llamar al LoadLibraryEx
con la bandera LOAD_WITH_ALTERED_SEARCH_PATH
. Debe cargar el archivo DLL con una ruta absoluta, de lo contrario, el comportamiento no está definido. Para mayor comodidad, podemos crear la subclase ctypes.CDLL
y ctypes.WinDLL
para llamar al LoadLibraryEx
en lugar de 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)
Aquí están todas las banderas LoadLibraryEx
disponibles:
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
Por ejemplo:
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'
¿Estás seguro de que es una DLL de Windows y no un archivo DLL de C? ¿Has probado 'cdll.LoadLibrary' de la biblioteca ctypes? –
Sí, lo olvidé por completo. – Switch