加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 尝试打开互斥体时UnauthorizedAccessException

发布时间:2020-12-15 04:16:49 所属栏目:百科 来源:网络整理
导读:当尝试打开互斥体时,我会收到这个异常(仅有时会发生这种情况;大多数调用成功): System.UnauthorizedAccessException: Access to the path 'Global4c7cddf7-e729-43b6-a75c-43f54a0ac6ac' is denied. at System.IO.__Error.WinIOError(Int32 errorCode,Stri
当尝试打开互斥体时,我会收到这个异常(仅有时会发生这种情况;大多数调用成功):
System.UnauthorizedAccessException: Access to the path 'Global4c7cddf7-e729-43b6-a75c-43f54a0ac6ac' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode,String maybeFullPath)
   at System.Threading.Mutex.OpenExisting(String name,MutexRights rights)

我用于使用互斥体的代码:

public class MutexLocker : IDisposable
{
    public MutexLocker(string id)
    {
        var doesNotExist = false;
        var unauthorized = false;

        try
        {
            _mutex = Mutex.OpenExisting(id,MutexRights.Synchronize | MutexRights.Modify);
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            doesNotExist = true;
        }
        catch (UnauthorizedAccessException ex)
        {
            unauthorized = true;
        }

        if (doesNotExist)
        {
            _mutex = new Mutex(false,id);

            var allowEveryoneRule = new MutexAccessRule(
                new SecurityIdentifier(WellKnownSidType.WorldSid,null),MutexRights.FullControl,AccessControlType.Allow);
            var securitySettings = new MutexSecurity();
            securitySettings.AddAccessRule(allowEveryoneRule);
            _mutex.SetAccessControl(securitySettings);
        }
        else if (unauthorized)
        {
            var tempMutex = Mutex.OpenExisting(id,MutexRights.ReadPermissions | MutexRights.ChangePermissions);
            var securitySettings = tempMutex.GetAccessControl();

            var user = Environment.UserDomainName + "" + Environment.UserName;

            // the rule that denied the current user the right to enter and release the mutex must be removed
            var rule = new MutexAccessRule(user,MutexRights.Synchronize | MutexRights.Modify,AccessControlType.Deny);
            securitySettings.RemoveAccessRule(rule);

            // Now grant the correct rights
            var allowEveryoneRule = new MutexAccessRule(
                new SecurityIdentifier(WellKnownSidType.WorldSid,AccessControlType.Allow);
            securitySettings.AddAccessRule(allowEveryoneRule);
            tempMutex.SetAccessControl(securitySettings);

            _mutex = Mutex.OpenExisting(id,MutexRights.Synchronize | MutexRights.Modify);
        }

        var success = _mutex.WaitOne(TimeSpan.FromSeconds(10),false);
        if (success == false)
        {
            _mutex.Dispose();
            _mutex = null;
            throw new ApplicationException(string.Format("Can't lock mutex (timed out): {0}",id));
        }
    }

    public void Dispose()
    {
        if (_mutex != null)
        {
            try
            {
                _mutex.ReleaseMutex();
            }
            catch (Exception exc)
            {
                Trace.WriteLine(exc);
            }

            _mutex.Dispose();
        }
    }

    private readonly Mutex _mutex;
}

互斥体“id”是一个guid,名称冲突是不可能的.
这是唯一可以创建互斥体的代码,并且它为所有用户授予了完全访问权限(我的进程可以在不同的用户凭据下运行).

任何想法,为什么这种未经授权的访问错误可能发生

解决方法

这个课程应该解决你的问题:
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,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构造函数,它将尝试创建互斥(通过调用Win32的CreateMutex()),将所提供的安全描述符立即分配给命名对象.如果CreateMutex调用失败,框架将尝试使用OpenMutex打开请求SYNCHRONIZE和MUTEX_MODIFY权限的命名互斥体.

您所看到的问题是创建互斥体和分配安全描述符之间的简单竞争条件(至少在我注意到的情况下).使创建和安全描述符赋值为原子将解决该问题.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读