Tho*_*mas 7 winapi multithreading mutex process single-instance
我正在处理一个应用程序,在任何给定时间只能存在一个实例.有几种可能性来实现这一目标:
互斥选项在我看来是最可靠和优雅的.
但是,在我的第二个实例终止之前,我想向已经运行的实例发布一条消息.为此,我需要一个拥有互斥锁的线程(或进程)的句柄.
但是,似乎没有API函数来获取给定互斥锁的创建者/所有者.我只是俯视它吗?有没有其他方法来到这个线程/进程?还有另一种方法可以解决这个问题吗?
更新:这个人只是向所有正在运行的进程广播一条消息.我想这是可能的,但我真的不喜欢它......
Gal*_*llo 10
这应该让您开始了原始请求,以获得拥有互斥锁的进程.
它在C#中,但Win32调用是相同的.
class HandleInfo
{
[DllImport("ntdll.dll", CharSet = CharSet.Auto)]
public static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, out int ReturnLength);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAlloc(IntPtr address, uint numBytes, uint commitOrReserve, uint pageProtectionMode);
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern bool VirtualFree(IntPtr address, uint numBytes, uint pageFreeMode);
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_HANDLE_INFORMATION
{
public int ProcessId;
public byte ObjectTypeNumber;
public byte Flags; // 1 = PROTECT_FROM_CLOSE, 2 = INHERIT
public short Handle;
public int Object;
public int GrantedAccess;
}
static uint MEM_COMMIT = 0x1000;
static uint PAGE_READWRITE = 0x04;
static uint MEM_DECOMMIT = 0x4000;
static int SystemHandleInformation = 16;
static uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
public HandleInfo()
{
IntPtr memptr = VirtualAlloc(IntPtr.Zero, 100, MEM_COMMIT, PAGE_READWRITE);
int returnLength = 0;
bool success = false;
uint result = NtQuerySystemInformation(SystemHandleInformation, memptr, 100, out returnLength);
if (result == STATUS_INFO_LENGTH_MISMATCH)
{
success = VirtualFree(memptr, 0, MEM_DECOMMIT);
memptr = VirtualAlloc(IntPtr.Zero, (uint)(returnLength + 256), MEM_COMMIT, PAGE_READWRITE);
result = NtQuerySystemInformation(SystemHandleInformation, memptr, returnLength, out returnLength);
}
int handleCount = Marshal.ReadInt32(memptr);
SYSTEM_HANDLE_INFORMATION[] returnHandles = new SYSTEM_HANDLE_INFORMATION[handleCount];
using (StreamWriter sw = new StreamWriter(@"C:\NtQueryDbg.txt"))
{
sw.WriteLine("@ Offset\tProcess Id\tHandle Id\tHandleType");
for (int i = 0; i < handleCount; i++)
{
SYSTEM_HANDLE_INFORMATION thisHandle = (SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(
new IntPtr(memptr.ToInt32() + 4 + i * Marshal.SizeOf(typeof(SYSTEM_HANDLE_INFORMATION))),
typeof(SYSTEM_HANDLE_INFORMATION));
sw.WriteLine("{0}\t{1}\t{2}\t{3}", i.ToString(), thisHandle.ProcessId.ToString(), thisHandle.Handle.ToString(), thisHandle.ObjectTypeNumber.ToString());
}
}
success = VirtualFree(memptr, 0, MEM_DECOMMIT);
}
}
Run Code Online (Sandbox Code Playgroud)
我不认为有一种简单的方法可以解决互斥锁的实际所有者,但是拥有它的进程可以创建其生命周期与其相关的其他次要项。有很多机制适合在没有主窗口的情况下跨进程回调。
以下是前两个选项的参考链接。