#coding=utf-8
import ctypes
from ctypes import wintypes
#某些结构体可能会在Windows各个版本中有所差异,所以MSDN中并没有详述这些结构体。
#这里的定义都是在VS2008下找到的
class ACLStruct(ctypes.Structure):
_fields_ = [("AclRevision", wintypes.BYTE),
("Sbz1", wintypes.BYTE),
("AclSize", wintypes.WORD),
("AceCount", wintypes.WORD),
("Sbz2", wintypes.WORD)]
class SID_IDENTIFIER_AUTHORITYStruct(ctypes.Structure):
_fields_ = [("Value", wintypes.BYTE * 6)]
class SIDStruct(ctypes.Structure):
_fields_ = [("Revision", wintypes.BYTE),
("SubAuthorityCount", wintypes.BYTE),
("IdentifierAuthority", SID_IDENTIFIER_AUTHORITYStruct),
("SubAuthority", wintypes.DWORD * 1)]
class SECURITY_DESCRIPTORStruct(ctypes.Structure):
_fields_ = [("Revision", wintypes.BYTE),
("Sbz1", wintypes.BYTE),
("Control", wintypes.WORD),
("Owner", ctypes.POINTER(SIDStruct)),
("Group", ctypes.POINTER(SIDStruct)),
("Sacl", ctypes.POINTER(ACLStruct)),
("Dacl", ctypes.POINTER(ACLStruct))]
class SECURITY_ATTRIBUTESStruct(ctypes.Structure):
_fields_ = [("nLength", wintypes.DWORD),
("lpSecurityDescriptor", ctypes.POINTER(SECURITY_DESCRIPTORStruct)),
("bInheritHandle", wintypes.BOOL)]
try:
Dll_Advapi32 = ctypes.windll.LoadLibrary("Advapi32.dll")
_InitializeSecurityDescriptor = Dll_Advapi32.InitializeSecurityDescriptor
_InitializeSecurityDescriptor.argtypes = [ctypes.c_void_p, wintypes.DWORD]
_InitializeSecurityDescriptor.restype = wintypes.BOOL
_SetSecurityDescriptorDacl = Dll_Advapi32.SetSecurityDescriptorDacl
_SetSecurityDescriptorDacl.argtypes = [ctypes.c_void_p, wintypes.BOOL, ctypes.c_void_p, wintypes.BOOL]
_SetSecurityDescriptorDacl.restype = wintypes.BOOL
#如果name要是unicode,可以把这里改成CreateEventW,还要改参数类型
_CreateEvent = ctypes.windll.kernel32.CreateEventA
_CreateEvent.argtypes = [ctypes.c_void_p, wintypes.BOOL, wintypes.BOOL, wintypes.LPCSTR]
_CreateEvent.restype = wintypes.HANDLE
_WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
_WaitForSingleObject.argtypes = [wintypes.HANDLE, wintypes.DWORD]
_WaitForSingleObject.restype = wintypes.DWORD
_SetEvent = ctypes.windll.kernel32.SetEvent
_SetEvent.argtypes = [wintypes.HANDLE]
_SetEvent.restype = wintypes.BOOL
_CloseHandle = ctypes.windll.kernel32.CloseHandle
_CloseHandle.argtypes = [wintypes.HANDLE]
_CloseHandle.restype = wintypes.BOOL
except Exception, e:
logger.error("init win32 sync object interface fail, error[%s]", str(e))
raise
#Win32 Event的封装。name须为ANSI字符串。不可重入
class Win32SyncObject(object):
def __init__(self, name):
self.handle = None
try:
#设置安全属性是为了使服务中创建的锁也能在用户进程中访问,如果使用默认属性,会拒绝访问
#如果不需要考虑这个问题,则可以去掉上述相关结构体的定义和这段设置安全属性的代码,直接使用默认值None
sd = SECURITY_DESCRIPTORStruct()
if not _InitializeSecurityDescriptor(ctypes.byref(sd), 1):
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
if not _SetSecurityDescriptorDacl(ctypes.byref(sd), True, None, False):
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
sa = SECURITY_ATTRIBUTESStruct()
sa.nLength = 12
sa.lpSecurityDescriptor = ctypes.pointer(sd)
sa.bInheritHandle = False
self.handle = _CreateEvent(ctypes.byref(sa), False, False, name)
except Exception, e:
self.handle = None
raise
if not self.handle:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
raise ctypes.WinError(err_code, err_msg)
else:
if 0 == ctypes.GetLastError():#此时是创建
_SetEvent(self.handle)
def __del__(self):
pass
#应该关闭句柄,但是这个析构执行的时机有点奇怪,此时self.handle已经被释放了
#哪位大神能解释一下吗
#_CloseHandle(self.handle)
#self.handle = None
def acquire(self):
try:
ret = _WaitForSingleObject(self.handle, 0xFFFFFFFF)#永久等待
except Exception, e:
raise
if ret in (0, 0x80):
return True
else:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
return False
def release(self):
try:
ret = _SetEvent(self.handle)
except Exception, e:
raise
if not ret:
err_code = ctypes.GetLastError()
err_msg = ctypes.FormatError(err_code)
return False
else:
return True
#使用示例
#全局跨进程访问必须是Global命名空间下的
if_lock = Win32SyncObject(name = "Global\\CAA_{6A6B3EE2-8F6C-41f0-AA08-763AAE0C1D98}")
if_lock.acquire()
if_lock.release()
print "OK"