Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C“获取/设置注册表ACL时出现随机异常”;“安全特权”;_C#_.net_Exception_Permissions_Registry - Fatal编程技术网

C# C“获取/设置注册表ACL时出现随机异常”;“安全特权”;

C# C“获取/设置注册表ACL时出现随机异常”;“安全特权”;,c#,.net,exception,permissions,registry,C#,.net,Exception,Permissions,Registry,我得到了一个完全随机的异常,我可以运行同一组代码1000次(每次“运行”都是程序的完整结束,因此从命令行开始作为自己的进程,然后就存在了),并且失败一次,甚至150次。我的意思是,我可以一遍又一遍地运行它,它将完全随机地失败 System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is requir

我得到了一个完全随机的异常,我可以运行同一组代码1000次(每次“运行”都是程序的完整结束,因此从命令行开始作为自己的进程,然后就存在了),并且失败一次,甚至150次。我的意思是,我可以一遍又一遍地运行它,它将完全随机地失败

System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.
at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType resourceType, String name, SafeHandle handle, AccessControlSections accessControlSections, RawSecurityDescriptor& resultSd)
at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.RegistrySecurity..ctor(SafeRegistryHandle hKey, String name, AccessControlSections includeSections) 
at Microsoft.Win32.RegistryKey.GetAccessControl(AccessControlSections includeSections)
我无法让它在调试时失败,所以我在尝试了解它随机决定失败的原因时遇到了问题。由于它在
(RegistryKey).GetAccessControl(AccessControlSections.All)
方法中失败,我很难确定下一步应该尝试什么

此外,我循环使用多个键,如果它决定在一个上使用此权限异常失败,则它们都会在该过程中失败

我从命令行运行(作为管理员,UACed-in),启动流程,然后它就存在了。我从同一个命令行再次启动该进程,它将随机失败

我正在加载用户配置单元,并确保注册表权限已提升,并且除了此随机错误外,它也能正常工作


此外,该问题发生在多台计算机上(始终在本地运行,而不是远程运行),包括系统(psexec)帐户和管理员帐户。

我认为系统帐户没有启用SeSecurityPrivilege,也没有管理员

不要使用
(RegistryKey).GetAccessControl(AccessControlSections.All)
,而应尝试:
(RegistryKey).GetAccessControl(AccessControlSections.Access)

这仍然会给你错误吗?但是,您将无法使用
访问权限获取SACL

编辑:我从pinvoke那里获取了一些代码,用于调整访问令牌中的权限,您需要管理员权限才能做到这一点;我修改它是为了获得SeSecurityPrivilege,一旦调用“SetPriv();”,您现在应该能够使用
(RegistryKey).GetAccessControl(AccessControlSections.All)
,而不会出现任何错误。通过使用Process Hacker 2并在启用SeSecurityPrivilege之前和之后检查令牌,我能够验证它是否正常工作:

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    internal static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
    phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name,
    ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
    internal const int TOKEN_QUERY = 0x00000008;
    internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    internal const string SeSecurity = "SeSecurityPrivilege";

    private bool SetPriv()
   {
       try
       {
           bool retVal;
           TokPriv1Luid tp;
           IntPtr hproc = GetCurrentProcess();
           IntPtr htok = IntPtr.Zero;
           retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
           tp.Count = 1;
           tp.Luid = 0;
           tp.Attr = SE_PRIVILEGE_ENABLED;
           retVal = LookupPrivilegeValue(null, SeSecurity, ref tp.Luid);
           retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
           return retVal;
       }
       catch (Exception ex)
       {
           throw;
           return false; 
       }

   }

我认为系统帐户没有启用SeSecurityPrivilege,或者没有管理员

不要使用
(RegistryKey).GetAccessControl(AccessControlSections.All)
,而应尝试:
(RegistryKey).GetAccessControl(AccessControlSections.Access)

这仍然会给你错误吗?但是,您将无法使用
访问权限获取SACL

编辑:我从pinvoke那里获取了一些代码,用于调整访问令牌中的权限,您需要管理员权限才能做到这一点;我修改它是为了获得SeSecurityPrivilege,一旦调用“SetPriv();”,您现在应该能够使用
(RegistryKey).GetAccessControl(AccessControlSections.All)
,而不会出现任何错误。通过使用Process Hacker 2并在启用SeSecurityPrivilege之前和之后检查令牌,我能够验证它是否正常工作:

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    internal static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
    phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name,
    ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
    internal const int TOKEN_QUERY = 0x00000008;
    internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    internal const string SeSecurity = "SeSecurityPrivilege";

    private bool SetPriv()
   {
       try
       {
           bool retVal;
           TokPriv1Luid tp;
           IntPtr hproc = GetCurrentProcess();
           IntPtr htok = IntPtr.Zero;
           retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
           tp.Count = 1;
           tp.Luid = 0;
           tp.Attr = SE_PRIVILEGE_ENABLED;
           retVal = LookupPrivilegeValue(null, SeSecurity, ref tp.Luid);
           retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
           return retVal;
       }
       catch (Exception ex)
       {
           throw;
           return false; 
       }

   }


我想我们需要一些代码来帮助您。@TonyHopkinson您到底想看什么?它在
(RegistryKey)中失败。GetAccessControl(AccessControlSections.All)
调用很难说。假设它是间歇性的,并且在调试中不会发生。我认为这可能是GC的一个终生问题,或者类似的资源问题。一种指向这一点的方法是通过条目在循环中设置睡眠。只是胡乱猜测,我现在的线索比你还少。另一个同样令人讨厌的修复方法,可能是捕获异常并重试…@TonyHopkinson是的,我尝试过用一次尝试捕获它,然后休眠10秒,然后重试,但仍然出错。。。奇怪的是,它要么在进程生命周期的所有尝试中100%有效,要么在进程生命周期的所有尝试中100%失败。。。。因此,我可以运行“开始”->“结束”流程,它要么对流程需要更新的每个键都有效,要么不对:(我想我们需要一些代码来帮助您。@TonyHopkinson您希望看到什么?它在
(RegistryKey)中失败。GetAccessControl(AccessControlSections.All)
call很难说。考虑到它是间歇性的,并且在调试过程中不会发生。我认为这可能是GC的一个终生问题,或者类似的资源问题。指出这一点的一种方法是通过条目在循环中设置睡眠。只是粗略地猜测,我现在的线索比你更少。可能还有另一个同样糟糕的修复方法要捕获异常并重试…@TonyHopkinson是的,我尝试过捕获异常,然后休眠10秒,然后重试,但它仍然出错…奇怪的是,它要么在进程生命周期的所有尝试中100%工作,要么在进程生命周期的所有尝试中100%失败…所以我可以运行进程start->en它要么有效,要么不适用于流程需要更新的每个关键点:(为什么它大部分时间都有效?就像我说的,我只是随机得到这个错误,所以虽然它90%的时间有效,但它会出错10%(即使在返回时)我无法解释这一点,也许其他人可以。据我所知,使用
Access
永远不需要安全特权,因此使用
Access
不应该出现错误。因此,除非您需要
All
访问
Access
无法访问的内容,否则我会尝试使用
Access
并查看您是否停止获取是的,我尝试了
Access
,但是如果它无法读取
所有的
,那么它就起作用了,不知道为什么它会失败,也许其他人可以回答这个问题,如果没有
Access
解决方案会起作用,只是不确定它会有什么副作用。我用代码编辑了我的答案,启用了安全特权,哟您现在应该能够使用
All
,并且在启用权限后不会出现任何错误。感谢您的帮助,我还没有尝试您最新的代码更新,但它正在使用
All
fallin