【发布时间】:2018-08-23 14:02:53
【问题描述】:
C#、.NET 4.5
我有两个进程访问一个共享资源,但是尽管使用approach suggested here 创建了一个全局互斥锁;每个人都应该可以访问,但我仍然收到 System.UnauthorizedAccessException。
我可以通过使用提升的管理员权限运行有问题的进程来解决这种情况。这向我表明,第一个锁定过程不是使用正确的 AccessRule 和关联的 SecurityIdentifier 创建互斥锁 - 但它似乎是 - 它使用与上面相同的代码。
public class MutexLocker: IDisposable
{
private Mutex _mutex;
public MutexLocker ( string id )
{
bool createdNew;
MutexSecurity mutexSecurity = new MutexSecurity();
mutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
try
{
// attempt to create the mutex, with the desired DACL..
_mutex = new Mutex(false, id, out createdNew, mutexSecurity);
}
catch (WaitHandleCannotBeOpenedException)
{
// the mutex cannot be opened, probably because a Win32 object of a different
// type with the same name already exists.
throw;
}
catch (UnauthorizedAccessException)
{
// the mutex exists, but the current process or thread token does not
// have permission to open the mutex with SYNCHRONIZE | MUTEX_MODIFY rights.
throw;
}
}
public void Dispose ()
{
if (_mutex != null)
{
_mutex.ReleaseMutex();
_mutex.Dispose();
}
_mutex = null;
}
}
我可以确认我正在使用 Mutex 的构造函数,它在其中传递 AccessRule 以避免任何竞争条件。
我还尝试将 MutexAccessRule 设置为使用 MutexRights.FullControl 而行为没有改变。
编辑:尝试了其他代码 我也尝试过这种不同的实现,但行为相同:
var appGuid = "{6D7C8B75-01FC-471E-B5DE-97FAAE5D8BE7}";
string mutexId = string.Format( "Global\\{{{0}}}", appGuid );
// Need a place to store a return value in Mutex() constructor call
bool createdNew;
// edited by Jeremy Wiebe to add example of setting up security for multi-user usage
// edited by 'Marc' to work also on localized systems (don't use just "Everyone")
var allowEveryoneRule =
new MutexAccessRule( new SecurityIdentifier( WellKnownSidType.WorldSid
, null)
, MutexRights.FullControl
, AccessControlType.Allow
);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
// edited by MasonGZhwiti to prevent race condition on security settings via VanNguyen
using (var mutex = new Mutex(false, mutexId, out createdNew, securitySettings))
{
// edited by acidzombie24
var hasHandle = false;
try
{
try
{
// note, you may want to time out here instead of waiting forever
// edited by acidzombie24
// mutex.WaitOne(Timeout.Infinite, false);
hasHandle = mutex.WaitOne(5000, false);
if (hasHandle == false)
throw new TimeoutException("Timeout waiting for exclusive access");
}
catch (AbandonedMutexException)
{
// Log the fact that the mutex was abandoned in another process,
// it will still get acquired
hasHandle = true;
}
// Perform your work here.
}
finally
{
// edited by acidzombie24, added if statement
if(hasHandle)
mutex.ReleaseMutex();
}
}
有什么想法吗?
【问题讨论】:
-
@mjwills;很高兴把代码放在这里;但它会完全复制链接到答案;对我来说似乎是重复;但很高兴得到指导。
-
@mjwills;好的,很公平 - 将使用代码进行编辑。干杯。
标签: c# permissions mutex