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

如何在DeInitializeSetup阶段删除Inno Setup临时目录中的托管代码库

干净解决Inno Setup托管DLL卸载与临时目录删除问题

方案1:独立.NET辅助进程(最可靠,无孤儿进程)

编写一个无窗口的.NET控制台程序作为辅助工具,专门处理托管DLL的加载与执行,执行完成后自动退出,从根本上避免进程残留:

  • 辅助程序核心逻辑示例(C#):
using System;
using System.Reflection;

namespace UnloadHelper
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2) return;
            string dllPath = args[0];
            string methodName = args[1];
            
            // 加载DLL并执行目标方法
            Assembly asm = Assembly.LoadFrom(dllPath);
            Type type = asm.GetType("YourNamespace.YourClass");
            MethodInfo method = type.GetMethod(methodName);
            method.Invoke(null, null);
            
            // 主动触发GC,释放资源
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }
}
  • Inno Setup中调用方式:
[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
  HelperPath: string;
  DllPath: string;
  ResultCode: Integer;
begin
  if CurStep = ssPostUninstall then
  begin
    HelperPath := ExpandConstant('{tmp}\UnloadHelper.exe');
    DllPath := ExpandConstant('{tmp}\YourManaged.dll');
    // 同步执行辅助程序,等待其退出
    Exec(HelperPath, '"' + DllPath + '" YourMethod', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
    // 此时托管DLL已被释放,可安全删除临时目录
    DelTree(ExpandConstant('{tmp}'), True, True, True);
  end;
end;

方案2:自定义AppDomain卸载(精准控制加载域)

Inno Setup的LoadDll会将托管DLL加载到CLR默认AppDomain,不会自动创建新域,因此你可以安全创建独立AppDomain来隔离加载:

  • 实现步骤:
    • 在安装/卸载初始化阶段创建自定义AppDomain:
      var
        CustomDomain: Variant;
      begin
        CustomDomain := CreateOleObject('System.AppDomain');
        CustomDomain := CustomDomain.CreateDomain('InnoCustomDomain');
      end;
      
    • 通过自定义域加载并执行托管DLL操作,确保所有交互都在该域内完成,避免默认域引用。
    • 在DeInitialize阶段卸载自定义域:
      begin
        if not VarIsNull(CustomDomain) then
        begin
          CustomDomain.Unload(CustomDomain);
          CustomDomain := Unassigned;
          // 触发GC回收
          CreateOleObject('System.GC').Collect();
        end;
      end;
      
  • 注意:若托管DLL存在静态资源或未释放的非托管句柄,AppDomain卸载可能无法完全释放文件锁,需提前确保资源释放。

方案3:任务计划延迟删除(无进程残留,适合极端场景)

如果前两种方案仍有问题,可通过Windows任务计划实现无残留的延迟删除:

  • Inno Setup中注册一次性任务:
[Code]
procedure CurStepChanged(CurStep: TSetupStep);
var
  TempDir: string;
  TaskCommand: string;
  ResultCode: Integer;
begin
  if CurStep = ssPostUninstall then
  begin
    TempDir := ExpandConstant('{tmp}');
    // 创建一次性任务,系统空闲时删除临时目录,执行后自动删除任务
    TaskCommand := Format('/create /tn "CleanInnoTemp" /tr "cmd.exe /c rmdir /s /q ""%s""" /sc onidle /i 10 /f /rl highest /z', [TempDir]);
    Exec('schtasks.exe', TaskCommand, '', SW_HIDE, ewNoWait, ResultCode);
  end;
end;

关键注意事项

  • 所有方案都需确保托管DLL执行完成后,无未释放的文件句柄、数据库连接等资源,可通过Process Explorer的句柄查看功能验证。
  • 测试时多次卸载,检查任务管理器中是否有残留进程,确保无Win10任务栏异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:15:28