You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以管理员身份用PowerShell 7和C#修改/删除TrustedInstaller所有注册表项

处理TrustedInstaller所有的注册表项:PowerShell 7与C#实现方案

一、PowerShell 7 实现步骤

要修改/删除TrustedInstaller拥有的注册表项,需先启用系统特权、夺取所有权、赋予自身权限,再执行操作。以下是完整脚本:

# 目标注册表项路径(示例)
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\some-default-item"

# 1. 定义P/Invoke类型用于启用系统特权
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class AdvApi32 {
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, ref IntPtr TokenHandle);
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
    [StructLayout(LayoutKind.Sequential)]
    public struct LUID {
        public uint LowPart;
        public int HighPart;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct LUID_AND_ATTRIBUTES {
        public LUID Luid;
        public uint Attributes;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct TOKEN_PRIVILEGES {
        public uint PrivilegeCount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public LUID_AND_ATTRIBUTES[] Privileges;
    }
}
public class Kernel32 {
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr hObject);
}
"@

# 2. 启用SE_RESTORE和SE_BACKUP特权(修改系统注册表必需)
$privilegeNames = @("SeRestorePrivilege", "SeBackupPrivilege")
foreach ($privName in $privilegeNames) {
    $tokenHandle = [IntPtr]::Zero
    try {
        if (-not [AdvApi32]::OpenProcessToken([System.Diagnostics.Process]::GetCurrentProcess().Handle, 0x0020, [ref]$tokenHandle)) {
            Write-Error "无法打开进程令牌: $([ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error())"
            continue
        }
        $luid = [AdvApi32+LUID]::new()
        if (-not [AdvApi32]::LookupPrivilegeValue($null, $privName, [ref]$luid)) {
            Write-Error "无法查找特权: $([ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error())"
            continue
        }
        $privileges = [AdvApi32+TOKEN_PRIVILEGES]::new()
        $privileges.PrivilegeCount = 1
        $privileges.Privileges = @([AdvApi32+LUID_AND_ATTRIBUTES]::new())
        $privileges.Privileges[0].Luid = $luid
        $privileges.Privileges[0].Attributes = 0x00000002 # SE_PRIVILEGE_ENABLED
        if (-not [AdvApi32]::AdjustTokenPrivileges($tokenHandle, $false, [ref]$privileges, 0, [IntPtr]::Zero, [IntPtr]::Zero)) {
            Write-Error "无法调整令牌特权: $([ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error())"
        }
    } finally {
        if ($tokenHandle -ne [IntPtr]::Zero) {
            [Kernel32]::CloseHandle($tokenHandle)
        }
    }
}

# 3. 获取当前管理员用户,修改注册表项所有权
$currentAdmin = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$acl = Get-Acl -Path $regPath
$owner = New-Object System.Security.Principal.NTAccount($currentAdmin)
$acl.SetOwner($owner)
Set-Acl -Path $regPath -AclObject $acl

# 4. 赋予当前管理员完全控制权限
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
    $currentAdmin,
    [System.Security.AccessControl.RegistryRights]::FullControl,
    [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit,
    [System.Security.AccessControl.PropagationFlags]::None,
    [System.Security.AccessControl.AccessControlType]::Allow
)
$acl.AddAccessRule($rule)
Set-Acl -Path $regPath -AclObject $acl

# 5. 删除注册表项(如需修改,替换为Set-Item等操作)
Remove-Item -Path $regPath -Recurse -Force

注意事项

  • 操作前必须备份目标注册表项,避免系统功能异常
  • 部分核心系统项修改后可能导致Explorer崩溃,需提示用户确认风险
  • 脚本需以管理员身份运行PowerShell 7

二、C# 实现步骤

C#需通过P/Invoke调用Windows API处理所有权和特权,.NET自带Registry类无法直接操作TrustedInstaller拥有的项。以下是完整实现:

using System;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using Microsoft.Win32;

public class RegistryTrustedInstallerHelper
{
    // Windows API 常量
    private const uint SE_PRIVILEGE_ENABLED = 0x00000002;
    private const int ERROR_SUCCESS = 0;
    private const uint REG_KEY_ALL_ACCESS = 0xF003F;
    private const int OWNER_SECURITY_INFORMATION = 0x00000001;
    private const uint SE_REGISTRY_KEY = 7;

    // P/Invoke 结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct LUID
    {
        public uint LowPart;
        public int HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LUID_AND_ATTRIBUTES
    {
        public LUID Luid;
        public uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct TOKEN_PRIVILEGES
    {
        public uint PrivilegeCount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public LUID_AND_ATTRIBUTES[] Privileges;
    }

    // P/Invoke 方法
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, IntPtr ReturnLength);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern uint SetNamedSecurityInfo(string pObjectName, uint ObjectType, uint SecurityInfo, IntPtr psidOwner, IntPtr psidGroup, IntPtr pDacl, IntPtr pSacl);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool ConvertStringSidToSid(string StringSid, out IntPtr Sid);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr hObject);

    // 启用指定系统特权
    private static bool EnablePrivilege(string privilegeName)
    {
        if (!OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle, 0x0020, out IntPtr tokenHandle))
            return false;

        bool result = false;
        try
        {
            if (!LookupPrivilegeValue(null, privilegeName, out LUID luid))
                return false;

            TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();
            tp.PrivilegeCount = 1;
            tp.Privileges = new LUID_AND_ATTRIBUTES[1];
            tp.Privileges[0].Luid = luid;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

            result = AdjustTokenPrivileges(tokenHandle, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            result &= Marshal.GetLastWin32Error() == ERROR_SUCCESS;
        }
        finally
        {
            CloseHandle(tokenHandle);
        }
        return result;
    }

    // 夺取所有权并修改/删除注册表项
    public static bool TakeOwnershipAndModify(string registryPath)
    {
        // 启用必需特权
        if (!EnablePrivilege("SeRestorePrivilege") || !EnablePrivilege("SeBackupPrivilege"))
            return false;

        // 获取当前管理员SID
        NTAccount currentAccount = new NTAccount(WindowsIdentity.GetCurrent().Name);
        SecurityIdentifier sid = (SecurityIdentifier)currentAccount.Translate(typeof(SecurityIdentifier));
        if (!ConvertStringSidToSid(sid.Value, out IntPtr sidPtr))
            return false;

        try
        {
            // 修改注册表项所有权为当前用户
            uint securityResult = SetNamedSecurityInfo(registryPath, SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION, sidPtr, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            if (securityResult != ERROR_SUCCESS)
                return false;

            // 打开注册表项并赋予完全控制权限
            using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registryPath, RegistryKeyPermissionCheck.ReadWriteSubTree, REG_KEY_ALL_ACCESS))
            {
                if (key == null)
                    return false;

                RegistrySecurity security = key.GetAccessControl();
                RegistryAccessRule rule = new RegistryAccessRule(
                    sid,
                    RegistryRights.FullControl,
                    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                    PropagationFlags.None,
                    AccessControlType.Allow
                );
                security.AddAccessRule(rule);
                key.SetAccessControl(security);

                // 执行删除操作(如需修改,替换为SetValue等逻辑)
                key.DeleteSubKeyTree("", true);
            }
            return true;
        }
        finally
        {
            Marshal.FreeHGlobal(sidPtr);
        }
    }
}

// 调用示例
class Program
{
    static void Main(string[] args)
    {
        // 目标注册表项路径(示例)
        string targetPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\some-default-item";
        bool success = RegistryTrustedInstallerHelper.TakeOwnershipAndModify(targetPath);
        Console.WriteLine(success ? "操作完成" : "操作失败");
    }
}

注意事项

  • 程序必须以管理员权限运行
  • 操作前务必备份注册表,防止破坏系统默认功能
  • 部分受系统保护的注册表项即使夺取所有权也无法删除,需提前告知用户风险

内容的提问来源于stack exchange,提问作者fmotion1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:24:56