从非托管进程中卸载.NET DLL [英] Unload a .NET DLL from an unmanaged process

查看:185
本文介绍了从非托管进程中卸载.NET DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在扩展我的Inno-Setup脚本,使用我可以在托管DLL中用C#最好实现的代码。我已经知道如何将托管DLL中的方法导出为在非托管进程中使用的函数。可以通过IL编织来完成,并且有一些工具可以使它自动化:

I'm extending my Inno-Setup script with code that I can best implement in C# in a managed DLL. I already know how to export methods from a managed DLL as functions for use in an unmanaged process. It can be done by IL weaving, and there are tools to automate this:

  • NetDllExport (written by me)
  • UnmanagedExports

因此,导出后,我可以调用函数从Inno-Setup安装程序中的Pascal脚本中获取。但是,这里有一个问题:似乎无法再卸载DLL。使用Inno-Setup的 UnloadDLL(...)无效,文件保持锁定状态,直到安装程序退出。因此,安装程序将等待2秒钟,然后无法从temp目录(或安装目录)中删除我的DLL文件。实际上,它确实会一直存在,直到有人清理驱动器为止。

So after exporting, I can call my functions from Pascal script in an Inno-Setup installer. But then there's one issue: The DLL can't seem to be unloaded anymore. Using Inno-Setup's UnloadDLL(...) has no effect and the file remains locked until the installer exits. Because of this, the setup waits for 2 seconds and then fails to delete my DLL file from the temp directory (or install directory). In fact, it really stays there until somebody cleans up the drive.

我知道,除非已关闭整个AppDomain,否则无法再从AppDomain卸载托管程序集。该过程退出)。但是,这对非托管主机进程意味着什么?

I know that managed assemblies cannot be unloaded from an AppDomain anymore, unless the entire AppDomain is shut down (the process exits). But what does it mean to the unmanaged host process?

是否有更好的方法允许Inno-Setup在加载和使用它后卸载或删除我的DLL文件?

Is there a better way to allow Inno-Setup to unload or delete my DLL file after loading and using it?

推荐答案

如其他答案中所建议的那样,您可以在安装结束时启动一个单独的过程,以完成清理工作,在安装过程完成之后。

As suggested in other answers, you can launch a separate process at the end of the installation that will take care of the cleanup, after the installation processes finishes.

一个简单的解决方案是创建一个临时批处理文件,该批文件循环运行直到可以删除DLL文件,然后再删除(现在为空)

A simple solution is creating an ad-hoc batch file that loops until the DLL file can be deleted and then also deletes the (now empty) temporary folder and itself.

procedure DeinitializeSetup();
var
  FilePath: string;
  BatchPath: string;
  S: TArrayOfString;
  ResultCode: Integer;
begin
  FilePath := ExpandConstant('{tmp}\MyAssembly.dll');
  if not FileExists(FilePath) then
  begin
    Log(Format('File %s does not exist', [FilePath]));
  end
    else
  begin
    BatchPath :=
      ExpandConstant('{%TEMP}\') +
      'delete_' + ExtractFileName(ExpandConstant('{tmp}')) + '.bat';
    SetArrayLength(S, 7);
    S[0] := ':loop';
    S[1] := 'del "' + FilePath + '"';
    S[2] := 'if not exist "' + FilePath + '" goto end';
    S[3] := 'goto loop';
    S[4] := ':end';
    S[5] := 'rd "' + ExpandConstant('{tmp}') + '"';
    S[6] := 'del "' + BatchPath + '"';
    if not SaveStringsToFile(BatchPath, S, False) then
    begin
      Log(Format('Error creating batch file %s to delete %s', [BatchPath, FilePath]));
    end
      else
    if not Exec(BatchPath, '', '', SW_HIDE, ewNoWait, ResultCode) then
    begin
      Log(Format('Error executing batch file %s to delete %s', [BatchPath, FilePath]));
    end
      else
    begin
      Log(Format('Executed batch file %s to delete %s', [BatchPath, FilePath]));
    end;
  end;
end;

这篇关于从非托管进程中卸载.NET DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆