Win32: How to get the process/thread that owns a mutex?
I'm working an application of which only one instance must exist at any given time. There are several possibilities to accomplish this:
The mutex option seems to me the most reliable and elegant.
However, before my second instance terminates, I want to post a message to the already running instance. For this, I need a handle to the thread (or the process) that owns the mutex.
However, there seems to be no API function to get the creator/owner of a given mutex. Am I just overlooking it? Is there another way to get to this thread/process? Is there another way to go about this?
Update: This guy simply broadcast a message to all running processes. I guess that's possible, but I don't really like it...
I don't think there is a trivial way to resolve the actual owner of a Mutex, but the process that owns it can create other secondary items whose lifetimes are tied to it. There are plenty of mechanisms that are suitable for calling back across-process without having a main window.
Here are reference links for the first two options.
This should get you started on the original request to get a process that owns a mutex.
It's in C#, but the Win32 calls are the same.
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("@ OffsettProcess IdtHandle IdtHandleType");
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);
}
}
I have never really understood the rational behind using a Mutex which has no signaling capability. I would instead create an event (using CreateEvent) which has the same properties as creating a mutex (ie with a name it can return that the object already existed) but you can set the event flag in the new process, as long as the original process is waiting on the event flag it can be notified when it needs to wake itself up.
链接地址: http://www.djcxy.com/p/51216.html上一篇: 具有相同名称的互斥体