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

文件占用异常求助:动态更新代码中File.Copy失败排查

问题描述

执行File.Copy时抛出异常:The process cannot access the file 'file path' because it is being used (unknown why)。通过资源监视器确认该DLL正被当前程序占用:

  • 仅包含File.Copy逻辑的静态版本代码在check_4_Update函数中可正常运行
  • 加入其他逻辑的动态版本触发文件占用异常
  • 程序通过Class.Constructor()实例化引用了目标DLL,怀疑System.Reflection.Assembly相关代码导致文件被锁定,需定位引发占用的函数

静态版本代码

string _Source = @"path1\file.ext";
string _Target = @"path2\file.ext";
            
if ( File.Exists( _Source ) ) {
    try { File.Copy(_Source,_Target,true); return true; }
    catch (Exception e) { MessageBox.Show(e.Message);  return false; }
}

动态版本代码

private static string getBackName( string inStr, [System.Runtime.CompilerServices.CallerMemberName] string _mN = "" ) { 
    return _mN.Split('_').Last(); 
}

private static Int64 getFileVersion( string versionOfFile ) {
    if ( !File.Exists( versionOfFile )) return 0;
    return Int64.Parse( FileVersionInfo.GetVersionInfo( versionOfFile ).FileVersion.ToString().Replace(".",""));
}       

private static string check_Update_dll( string _completePath  ) {
    string _fExt = "."+getBackName("");
    string[] files = Directory.GetFiles( _completePath , "*"+_fExt );
    switch ( files.Length ) {
        case 0 : return null;
        case 1 : return files[files.Length-1];
        default : return null;
    }
}

private static bool check_4_Update() {
    string _fName = (System.Reflection.Assembly.GetEntryAssembly().GetName().Name).Replace( new Class.Constructor().GetType().Name , "");
    string _uPath = "\\"+getBackName("")+"\\";
    string _rPath = Path.GetDirectoryName( Application.ExecutablePath );
    string _fExt = Path.GetExtension( check_Update_dll( _rPath + _uPath ) );
    if ( _fExt == null ) return false;
    
    string _Source = _rPath + _uPath + _fName + _fExt;
    Int64 _uFVer = getFileVersion( _Source );
    string _Target = _rPath + "\\" + _fName + _fExt;
    Int64 _oFVer = getFileVersion( _Target );
    if ( _oFVer >= _uFVer ) return false;
    
    if ( File.Exists( _Source ) ) {
        try { File.Copy(_Source,_Target,true); return true; }
        catch (Exception e) { MessageBox.Show(e.Message);  return false; }
    } else { return false; }
}
问题定位与解决建议

锁定来源定位

  • new Class.Constructor()实例化:这是核心原因。当你通过该代码创建对象时,CLR会加载对应的DLL并保持文件锁定,直到程序域卸载。静态版本未实例化该类,所以不会锁定DLL;动态版本的check_4_Update方法中调用了该代码,触发DLL加载,导致目标路径(_Target)的DLL被占用无法覆盖。
  • FileVersionInfo.GetVersionInfo:该方法通常不会长期锁定文件,结合静态版本对比,并非主要触发因素。

解决办法

  • 延迟实例化:将new Class.Constructor()的调用移到更新操作完成之后,避免在更新前加载目标DLL。
  • 无锁反射加载:若需提前访问DLL类型信息,可读取DLL字节流后通过Assembly.Load(byte[])加载,该方式不会锁定原始文件;或使用独立AppDomain加载DLL,加载完成后卸载程序域释放文件锁。
  • 重启替换:先将更新包复制到临时路径,更新完成后提示用户重启程序,在启动时替换原DLL文件。

内容的提问来源于stack exchange,提问作者beg-inner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:01:13