Unload a .NET DLL from an unmanaged process

后端 未结 5 722
时光取名叫无心
时光取名叫无心 2020-12-09 16:33

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

相关标签:
5条回答
  • 2020-12-09 16:55

    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.

    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;
    
    0 讨论(0)
  • 2020-12-09 16:57

    As suggested in this Code Project Article : https://www.codeproject.com/kb/threads/howtodeletecurrentprocess.aspx

    call a cmd with arguments as shown below.

     Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " +  Application.ExecutablePath);
    

    But basically as @Sean suggested, make sure you dont wait for the cmd.exe to exit in your script.

    0 讨论(0)
  • 2020-12-09 16:59

    You could add a batch script (in the form of running cmd -c) to be executed at the end of setup that waits for the file to be deletable and deletes it. (just make sure to set the inno option to not wait for the cmd process to complete)

    You could also make your installed program detect and delete it on first execution.

    0 讨论(0)
  • 2020-12-09 17:03

    The easy way to do what you want is through an AppDomain. You can unload an AppDomain, just not the initial one. So the solution is to create a new AppDomain, load your managed DLL in that and then unload the AppDomain.

            AppDomain ad = AppDomain.CreateDomain("Isolate DLL");
            Assembly a = ad.Load(new AssemblyName("MyManagedDll"));
            object d = a.CreateInstance("MyManagedDll.MyManagedClass");
            Type t = d.GetType();
            double result = (double)t.InvokeMember("Calculate", BindingFlags.InvokeMethod, null, d, new object[] { 1.0, 2.0 });
            AppDomain.Unload(ad);
    

    Here is what the DLL code looks like...

    namespace MyManagedDll
    {
       public class MyManagedClass
       {
          public double Calculate(double a, double b)
          {
            return a + b;
          }
       }
    }
    
    0 讨论(0)
  • 2020-12-09 17:21

    While not exactly an answer to your question, can't you just mark the DLL to be deleted next time the computer is restarted?

    0 讨论(0)
提交回复
热议问题