多次调用GroupPolicy设置接口引发文件占用异常求助
组策略连续设置时的文件占用异常修复
问题场景
使用基于COM接口的组策略操作代码,单次调用SetPolicySetting方法修改GPO值时正常,但连续多次调用该方法时,抛出以下异常:
Exception: System.IO.FileLoadException: The process cannot access the file because it is being used by another process. (0x80070020)
问题根源
- COM资源未显式释放:
IGroupPolicyObject是COM对象,原代码未实现资源释放逻辑,GC无法及时回收该对象,残留句柄会锁定GPO相关文件(如.pol文件)。 - 实例资源未主动释放:每次调用
SetPolicySetting都会创建新的ComputerGroupPolicyObject实例,但实例未被主动销毁,连续调用时多个实例同时占用文件资源。 - 冗余文件写入操作:原代码
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
相关产品推荐
相关产品推荐

