简体   繁体   English

如何在Python中从SXS加载C DLL?

[英]How do I load a C DLL from the SXS in Python?

This is typically done by specifying the DLL dependency in a manifest file that resides with the executable. 通常,通过在与可执行文件一起存在的清单文件中指定DLL依赖关系来完成此操作。 However, I don't know how to accomplish this in Python. 但是,我不知道如何在Python中完成此操作。 Loading the DLL isn't an issue, but rather finding the appropriate DLL in the SXS to load is the problem. 加载DLL并不是问题,而是在SXS中找到合适的DLL进行加载是一个问题。

Is there a standard procedure for specifying where to find the DLL ? 是否有用于指定在哪里找到DLL的标准过程? For this example let's assume it lives here: 对于此示例,我们假设它位于此处:

c:\windows\winsxs\amd64_my_handy_lib_<public_key_token>_1.0.0.0_none_<some_ID>

Do I REALLY need to manually search the c:\\windows\\winsxs directory looking for my DLL by name, then check the parent directory to see if it contains the correct version? 我是否真的需要手动搜索c:\\windows\\winsxs目录以按名称查找我的DLL,然后检查父目录以查看其是否包含正确的版本?

I just don't do Python projects enough to know what the appropriate way to accomplish this. 我只是没有做足够的Python项目来知道什么合适的方法来完成此任务。

Here's an example that loads the CRT from the WinSxS directory. 这是一个从WinSxS目录加载CRT的示例。

actctx.manifest: actctx.manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.VC90.CRT"
                version="9.0.21022.8"
                processorArchitecture="amd64"
                publicKeyToken="1fc8b3b9a1e18e3b">
            </assemblyIdentity>
        </dependentAssembly>
    </dependency>
</assembly>

actctx.py: actctx.py:

from ctypes import *
from ctypes.wintypes import *

kernel32 = WinDLL("kernel32", use_last_error=True)

ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID = 0x001
ACTCTX_FLAG_LANGID_VALID = 0x002
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004
ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x008
ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x010
ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x020
ACTCTX_FLAG_HMODULE_VALID = 0x080
DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION = 1

INVALID_HANDLE_VALUE = HANDLE(-1).value
ULONG_PTR = WPARAM  # pointer-sized unsigned integer

class ACTCTX(Structure):
    _fields_ = (("cbSize", ULONG),
                ("dwFlags", DWORD),
                ("lpSource", LPCWSTR),
                ("wProcessorArchitecture", USHORT),
                ("wLangId", LANGID),
                ("lpAssemblyDirectory", LPCWSTR),
                ("lpResourceName", LPCWSTR),
                ("lpApplicationName", LPCWSTR),
                ("hModule", HMODULE))

    def __init__(self, *args, **kwds):
        super(ACTCTX, self).__init__(sizeof(self), *args, **kwds)

CreateActCtxW = kernel32.CreateActCtxW
CreateActCtxW.restype = HANDLE
CreateActCtxW.argtypes = (POINTER(ACTCTX),)
ReleaseActCtx = kernel32.ReleaseActCtx
ReleaseActCtx.restype = None
ReleaseActCtx.argtypes = (HANDLE,)
ActivateActCtx = kernel32.ActivateActCtx
ActivateActCtx.argtypes = (HANDLE, POINTER(ULONG_PTR))
DeactivateActCtx = kernel32.DeactivateActCtx
DeactivateActCtx.argtypes = (DWORD, ULONG_PTR)

if __name__ == "__main__":
    manifest_path = "actctx.manifest" # keep ref
    ctx = ACTCTX(lpSource=manifest_path)
    hActCtx = CreateActCtxW(byref(ctx))
    if hActCtx == INVALID_HANDLE_VALUE:
        raise WinError(get_last_error())

    cookie = ULONG_PTR()
    if not ActivateActCtx(hActCtx, byref(cookie)):
        raise WinError()
    msvcr90 = CDLL("msvcr90")
    if not DeactivateActCtx(0, cookie):
        raise WinError(get_last_error())

    ReleaseActCtx(hActCtx)

    # show DLL path
    hModule = HANDLE(msvcr90._handle)
    path = (c_wchar * 260)()    
    kernel32.GetModuleFileNameW(hModule, path, len(path))
    print(path.value)

output: 输出:

C:\Windows\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_08e61857a83bc251\msvcr90.DLL

This was tested under Python 3.4.2, which is built with VS 2010 and links with msvcr100.dll instead. 已在VS 2010内置的Python 3.4.2下进行了测试,而该链接与msvcr100.dll链接。 So at least in this case setting the activation context was really required, else loading msvcr90.dll would fail with ERROR_MOD_NOT_FOUND . 因此,至少在这种情况下,确实需要设置激活上下文,否则加载msvcr90.dll将会失败,并显示ERROR_MOD_NOT_FOUND

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM