未以管理员

时间:2018-03-14 21:31:56

标签: c# permissions mutex

C#,. NET 4.5

我有两个进程访问共享资源,但尽管使用approach suggested here创建了一个Global Mutex;每个人都应该可以访问,我仍然得到一个System.UnauthorizedAccessException。

我可以通过使用提升的管理员权限运行有问题的进程来解决这种情况。这告诉我,第一个锁定过程不是使用正确的AccessRule和关联的SecurityIdentifier创建Mutex - 但它似乎是 - 它使用与上面相同的代码。

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\\{enter image description here}", 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();
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

那可能是您没有在Windows服务器上运行吗?在.NET 4.7.2的文档中,它说“在运行终端服务的服务器上”提供了以“全局”开头的互斥体。