首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Python中从SXS加载C DLL?

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

Stack Overflow用户
提问于 2014-12-09 21:31:31
回答 1查看 1.2K关注 0票数 2

这通常通过在驻留在可执行文件中的清单文件中指定DLL依赖项来完成。但是,我不知道如何用Python实现这一点。加载DLL不是问题,而是在SXS中找到要加载的适当DLL才是问题。

是否有指定在何处找到DLL的标准过程?对于这个例子,让我们假设它存在于这里:

代码语言:javascript
复制
c:\windows\winsxs\amd64_my_handy_lib_<public_key_token>_1.0.0.0_none_<some_ID>

是否真的需要手动搜索c:\windows\winsxs目录,按名称查找DLL,然后检查父目录是否包含正确的版本?

我只是没有做足够的Python项目来了解实现这个目标的适当方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-10 02:23:49

下面是一个从WinSxS目录加载CRT的示例。

actctx.manifest:

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
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)

输出:

代码语言:javascript
复制
C:\Windows\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_08e61857a83bc251\msvcr90.DLL

这在Python3.4.2下进行了测试,它使用VS 2010构建,并使用msvcr100.dll进行链接。因此,至少在这种情况下,真正需要设置激活上下文,否则在ERROR_MOD_NOT_FOUND中加载msvcr90.dll就会失败。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27389227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档