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

多次调用GroupPolicy设置接口引发文件占用异常求助

组策略连续设置时的文件占用异常修复

问题场景

使用基于COM接口的组策略操作代码,单次调用SetPolicySetting方法修改GPO值时正常,但连续多次调用该方法时,抛出以下异常:

Exception: System.IO.FileLoadException: The process cannot access the file because it is being used by another process. (0x80070020)

问题根源

  1. COM资源未显式释放:IGroupPolicyObject是COM对象,原代码未实现资源释放逻辑,GC无法及时回收该对象,残留句柄会锁定GPO相关文件(如.pol文件)。
  2. 实例资源未主动释放:每次调用SetPolicySetting都会创建新的ComputerGroupPolicyObject实例,但实例未被主动销毁,连续调用时多个实例同时占用文件资源。
  3. 冗余文件写入操作:原代码Save方法同时保存Machine和User部分,即使只修改了其中一个,也会触发两次文件写入,延长了文件锁定的时间窗口。

修复方案

1. 为GroupPolicyObject添加IDisposable实现

修改抽象类GroupPolicyObject,显式释放COM实例:

public abstract class GroupPolicyObject : IDisposable
{
    // ... 原有代码 ...

    private bool _disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // 释放托管资源(如有)
            }

            // 强制释放COM对象
            if (Instance != null)
            {
                Marshal.ReleaseComObject(Instance);
                Instance = null;
            }

            _disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~GroupPolicyObject()
    {
        Dispose(false);
    }

    // ... 原有代码 ...
}

2. 在SetPolicySetting中用using包裹GPO实例

确保GPO实例被及时释放,避免资源泄漏:

public static void SetPolicySetting(string registryInformation, string settingValue, RegistryValueKind registryValueKind)
{
    string valueName;
    GroupPolicySection section;
    string key = Key(registryInformation, out valueName, out section);

    Exception exception = null;
    var t = new Thread(() =>
    {
        try
        {
            // 使用using自动释放GPO实例
            using (var gpo = new ComputerGroupPolicyObject())
            {
                using (RegistryKey rootRegistryKey = gpo.GetRootRegistryKey(section))
                {
                    if (settingValue == null)
                    {
                        using (RegistryKey subKey = rootRegistryKey.OpenSubKey(key, true))
                        {
                            if (subKey != null)
                            {
                                subKey.DeleteValue(valueName);
                            }
                        }
                    }
                    else
                    {
                        using (RegistryKey subKey = rootRegistryKey.CreateSubKey(key))
                        {
                            subKey.SetValue(valueName, settingValue, registryValueKind);
                        }
                    }
                }

                // 仅保存修改的Section,减少文件操作
                bool isMachineSection = section == GroupPolicySection.Machine;
                var result = gpo.Instance.Save(isMachineSection, true, RegistryExtension, LocalGuid);
                if (result != 0)
                {
                    throw new Exception($"Error saving {section} settings");
                }
            }
        }
        catch (Exception ex)
        {
            exception = ex;
        }
    });
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
    t.Join();

    if (exception != null)
        throw exception;
}

3. 优化Save方法(可选)

新增支持指定Section的Save方法,避免冗余操作:

public void Save(GroupPolicySection section)
{
    bool isMachine = section == GroupPolicySection.Machine;
    var result = Instance.Save(isMachine, true, RegistryExtension, LocalGuid);
    if (result != 0)
    {
        throw new Exception($"Error saving {section} settings");
    }
}

调用时替换为gpo.Save(section)即可。

验证效果

修改后连续调用SetPolicySetting方法,文件占用异常将不再出现——每次操作的GPO资源都会被及时释放,文件锁定时间被大幅缩短。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:09:19