BluePointLilac/ContextMenuManager · error · PrivilegeNotHeldException
SeTakeOwnershipPrivilege
Error message
SeTakeOwnershipPrivilege
What it means
When a registry key is owned by TrustedInstaller or another privileged principal, write access fails. The code catches that failure and attempts to enable SeTakeOwnershipPrivilege via NativeMethod.TrySetPrivilege(NativeMethod.TakeOwnership, true). If enabling the privilege fails, it throws PrivilegeNotHeldException with the privilege name 'SeTakeOwnershipPrivilege'. This privilege grants the ability to take ownership of securable objects (registry keys, files) without being granted write access by the DACL.
Source
Thrown at ContextMenuManager/BluePointLilac.Methods/RegTrustedInstaller.cs:176
/// <remarks>将注册表项所有者改为当前管理员用户</remarks>
/// <param name="regPath">要获取权限的注册表完整路径</param>
public static void TakeRegKeyOwnerShip(string regPath)
{
if(regPath.IsNullOrWhiteSpace()) return;
RegistryKey key = null;
WindowsIdentity id = null;
//利用试错判断是否有写入权限
try { key = RegistryEx.GetRegistryKey(regPath, true); }
catch
{
try
{
//获取当前用户的ID
id = WindowsIdentity.GetCurrent();
//添加TakeOwnership特权
bool flag = NativeMethod.TrySetPrivilege(NativeMethod.TakeOwnership, true);
if(!flag) throw new PrivilegeNotHeldException(NativeMethod.TakeOwnership);
//添加恢复特权(必须这样做才能更改所有者)
flag = NativeMethod.TrySetPrivilege(NativeMethod.Restore, true);
if(!flag) throw new PrivilegeNotHeldException(NativeMethod.Restore);
//打开没有权限的注册表路径
key = RegistryEx.GetRegistryKey(regPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);
RegistrySecurity security = key.GetAccessControl(AccessControlSections.All);
//得到真正所有者
//IdentityReference oldId = security.GetOwner(typeof(SecurityIdentifier));
//SecurityIdentifier siTrustedInstaller = new SecurityIdentifier(oldId.ToString());
//使进程用户成为所有者
security.SetOwner(id.User);
key.SetAccessControl(security);
View on GitHub (pinned to 55507155dd)
Solutions
- Run the application elevated (Right-click > Run as administrator) to get a full token with SeTakeOwnershipPrivilege enabled
- Verify the privilege is assigned via Local Security Policy > Local Policies > User Rights Assignment > 'Take ownership of files or other objects'
- Run 'whoami /priv' in an elevated prompt to confirm SeTakeOwnershipPrivilege is present and Enabled
- If running under a service account, grant it the Take Ownership right via secpol.msc or group policy
Example fix
// before (fails when not elevated)
var key = RegistryEx.GetRegistryKey(regPath, true);
// after (guard before attempting)
using(var identity = WindowsIdentity.GetCurrent())
{
var priv = identity.Token.GetPrivileges()
.Any(p => p == "SeTakeOwnershipPrivilege");
if(!priv)
throw new InvalidOperationException(
"Run as Administrator to modify TrustedInstaller-owned keys.");
} Defensive patterns
Strategy: validation
Validate before calling
static bool CanTakeOwnership()
{
using(var identity = WindowsIdentity.GetCurrent())
{
return identity.Claims
.Any(c => c.Type == "privilege"
&& c.Value == "SeTakeOwnershipPrivilege");
}
}
// Or via P/Invoke token enumeration:
static bool HasPrivilege(string privilege)
{
return NativeMethod.TrySetPrivilege(privilege, false);
}
if(!HasPrivilege(NativeMethod.TakeOwnership))
throw new InvalidOperationException(
"Elevation required: SeTakeOwnershipPrivilege not available."); Try / catch
try
{
key = RegistryEx.GetRegistryKey(regPath, true);
}
catch(PrivilegeNotHeldException ex) when(ex.Privilege == "SeTakeOwnershipPrivilege")
{
// Prompt user to restart elevated
throw new InvalidOperationException(
"Run as Administrator to modify protected registry keys.", ex);
} Prevention
- Check for elevation with 'new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)' before attempting registry writes to protected paths
- Use 'whoami /priv' during development to verify SeTakeOwnershipPrivilege is present and Enabled
- Cache privilege availability at startup and disable TrustedInstaller operations if missing
- Wrap the entire ownership-change sequence (TakeOwnership + Restore) in a single privileged operation so failures surface early
When it happens
Trigger: The process attempts to modify a TrustedInstaller-owned registry key (common under HKLM\SOFTWARE\Classes\*) and is not running with an elevated token, or the user account lacks the 'Take ownership of files or other objects' user right. Also triggered when the token has the privilege but it is disabled and TrySetPrivilege fails to enable it (e.g., restricted/sandboxed token).
Common situations: Running ContextMenuManager as a standard user without elevation. Admin token filtered by UAC so SeTakeOwnershipPrivilege is present but only enabled on the full (elevated) token. Group policy explicitly removes the Take Ownership right from the user or group. Custom service account with a restricted token.
Related errors
AI-assisted analysis of BluePointLilac/ContextMenuManager@55507155dd (2026-08-13).
Data as JSON: /api/errors/b7a1dc2df78c9981.
Report an issue: GitHub.