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", 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:WindowsWinSxSamd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_08e61857a83bc251msvcr90.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
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…