如何在Python中从SXS加载C DLL? [英] How do I load a C DLL from the SXS in Python?

查看:189
本文介绍了如何在Python中从SXS加载C DLL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这通常通过在驻留在可执行文件中的清单文件中指定DLL依赖关系来完成。但是,我不知道如何在Python中完成这个。加载DLL不是一个问题,而是在SXS中找到合适的DLL加载是问题。



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

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

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



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

解决方案



actctx.manifest:

 <?xml version =1.0encoding =UTF-8standalone =yes?> 
< assembly xmlns =urn:schemas-microsoft-com:asm.v1manifestVersion =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:


$ b $ c

kernel32 = WinDLL(kernel32)$ c
ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID = 0×001
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 =手柄(-1).value的
ULONG_PTR =#WPARAM指针大小的无符号整数

级ACTCTX(结构):
_fields_ =((CBSIZE,ULONG),
(dwFlags中DWORD),
(lpSource,LPCWSTR),
( wProcessorArchitecture,USHORT),
(符wLangidLANGID),
(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 =无
ReleaseActCtx.argtypes =(HANDLE,)
ActivateActCtx = kernel32.ActivateActCtx
ActivateActCtx.argtypes =(HANDLE,指针(ULONG_PTR))
DeactivateActCtx = kernel32.DeactivateActCtx
DeactivateActCtx.argtypes =(DWORD,ULONG_PTR)

如果__name__ ==__main__:
manifest_path =actctx名为.manifest#保持裁判
CTX = ACTCTX(lpSource = manifest_path)
hActCtx = CreateActCtxW(按地址(CTX))
如果hActCtx == INVALID_HANDLE_VALUE:
提高WinError()

cookie = ULONG_PTR()
如果不是ActivateActCtx(hActCtx,byref(cookie)):
raise WinError()
msvcr90 = CDLL(msvcr90)
如果不DeactivateActCtx(0,饼干):
提高WinError()

ReleaseActCtx(hActCtx)

#显示DLL的路径
HMODULE = HANDLE (msvcr90._handle)
path =(c_wchar * 260)()
kernel32.GetModuleFileNameW(hModule,path,len(path))
print(path.value)



输出

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






这是在Python 3.4.2下测试的,它是用VS 2010构建的,并与msvcr100.dll链接。所以至少在这种情况下设置激活上下文是真的需要,否则加载msvcr90.dll将失败,并且 ERROR_MOD_NOT_FOUND


This is typically done by specifying the DLL dependency in a manifest file that resides with the executable. However, I don't know how to accomplish this in Python. Loading the DLL isn't an issue, but rather finding the appropriate DLL in the SXS to load is the problem.

Is there a standard procedure for specifying where to find the 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?

I just don't do Python projects enough to know what the appropriate way to accomplish this.

解决方案

Here's an example that loads the CRT from the WinSxS directory.

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:

from ctypes import *
from ctypes.wintypes import *

kernel32 = WinDLL("kernel32")

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()

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

    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. So at least in this case setting the activation context was really required, else loading msvcr90.dll would fail with ERROR_MOD_NOT_FOUND.

这篇关于如何在Python中从SXS加载C DLL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆