2015-02-07 3 views
21

관리 패키지의 C#에서 구현할 수있는 코드로 Inno-Setup 스크립트를 확장하고 있습니다. 관리되지 않는 프로세스에서 사용할 함수로 관리되는 DLL에서 메서드를 내보내는 방법을 이미 알고 있습니다. 그것은 IL 직물 수행 할 수 있으며,이를 자동화 할 수있는 도구가 있습니다 :관리되지 않는 프로세스에서 .NET DLL 언로드

그래서 보낸 후, 나는 파스칼 스크립트에서 내 함수를 호출 할 수는 Inno-Setup 인스톨러에서. 하지만 한 가지 문제가 있습니다. DLL을 더 이상 언로드 할 수 없습니다. Inno-Setup의 UnloadDLL(...)을 사용하면 아무 효과가 없으며 설치 프로그램을 종료 할 때까지 파일이 잠긴 상태로 유지됩니다. 이 때문에 설치 프로그램이 2 초 동안 기다린 다음 temp 디렉터리 (또는 설치 디렉터리)에서 DLL 파일을 삭제하지 못합니다. 실제로 누군가가 드라이브를 정리할 때까지 실제로 거기에 있습니다.

전체 AppDomain이 종료되지 않으면 (프로세스가 종료되지 않는 한) 관리되는 어셈블리를 AppDomain에서 더 이상 언로드 할 수 없다는 것을 알고 있습니다. 그러나 관리되지 않는 호스트 프로세스는 무엇을 의미합니까?

로드 및 사용 후 Inno-Setup에서 내 DLL 파일을 언로드하거나 삭제할 수있는 더 좋은 방법이 있습니까?

+1

작은 감자는 제거에 비해 ... DLL이 코드가 같은 모습입니다.NET 버전을 사용하여 설치 프로그램을 설치해야합니다. 예외를 디버깅하는 방법을 모르는 경우 해당 질문을 대신 요청하십시오. –

+2

어쨌든 설치된 응용 프로그램에는 .NET 런타임이 필요하므로 다시 설치되지 않습니다. – ygoe

+0

BTW, .NET은 현재 Windows 운영 체제 구성 요소이며, 최신 버전 만 지원됩니다. 그래서 .NET은 이미 거기에 있어야하고, 없어지지 않아야하며 심지어 Windows에서 유비쿼터스로 간주 될 수도 있습니다. – ygoe

답변

1

질문에 대한 답변이 정확하지는 않지만 다음에 컴퓨터를 다시 시작할 때 삭제할 DLL을 표시 할 수는 없습니까?

+7

만약 ' 오해하지 마시고,이 질문을 직접 질문에 덧붙여주십시오. –

+0

이것이 가능한 해결 방법이지만, 이상적이지는 않습니다. 질문에 대답하지 않아서 DLL 언로드가 실패한 이유를 설명하지 못합니다 . – caesay

+0

@caesay 어쩌면 당신은 당신이 원하는주의를 얻기 위해 관리되지 않는 호스트 프로세스에서 AppDomain을 언로드 할 때 새로운 일반 (= Inno Setup에만 해당) .NET/COM 전용 질문을 시작해야 할 것입니다. –

1

설치가 끝날 때 파일을 삭제할 수있을 때까지 기다리고 삭제할 배치 스크립트 (cmd -c 실행)를 추가 할 수 있습니다. (단지 INO 옵션을 설정하여 cmd 프로세스가 완료 될 때까지 기다리지 말것)

또한 설치된 프로그램이 처음 실행될 때 감지하여 삭제할 수 있습니다. 이 코드 프로젝트 문서에서 제안한 것처럼

1

: https://www.codeproject.com/kb/threads/howtodeletecurrentprocess.aspx

호출 아래 그림과 같이 인수 cmd를.

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

기본적으로 @Sean이 제안 했으므로 스크립트에서 cmd.exe가 종료 될 때까지 기다리지 마십시오.

+0

신뢰할 수 있으려면 설치 프로그램 프로세스가 완료 될 때까지 기다려야합니다. 고정 된 시간을 기다리는 것은 거의 신뢰할 수 없습니다. –

1

다른 답변에서 제안 된대로 설치 프로세스가 완료된 후 정리를 처리 할 설치 마지막 단계에서 별도의 프로세스를 시작할 수 있습니다.

간단한 해결책은 DLL 파일을 삭제할 때까지 반복되는 임시 배치 파일을 만든 다음 (현재 비어있는) 임시 폴더와 자체도 삭제합니다.

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; 
-1

원하는대로 쉽게 할 수있는 방법은 AppDomain을 사용하는 것입니다. 은 초기 응용 프로그램이 아닌 AppDomain을 언로드 할 수 있습니다. 그래서 해결책은 새로운 AppDomain을 만들고, 그 안에 관리되는 DLL을로드 한 다음 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); 

namespace MyManagedDll 
{ 
    public class MyManagedClass 
    { 
     public double Calculate(double a, double b) 
     { 
     return a + b; 
     } 
    } 
} 
+1

OP와 관련이 없습니다. OP는 .NET에서 기존의 관리되지 않는 응용 프로그램에 대한 확장을 구현하려고합니다. OP는 DLL로드 프로세스를 제어하지 않으므로 새 AppDomain을 만들 수 없습니다. –

+0

실제로 관련성이 있습니다. 그는 관리되는 DLL을 사용할 수 있습니다. 관리되는 DLL은 단순히 앱 도메인을 만들고 다른 관리 DLL을로드 한 다음 언로드됩니다. 그래서 내 대답은 2 개의 관리되는 DLL이 필요하다는 것에서 빠져있었습니다. 간단히 생각했습니다. – AQuirky

+0

예, 분명했습니다. 그러나 OP가 가진 문제는 다음과 같습니다 : "DLL을 더 이상 언로드 할 수 없습니다 Inno-Setup의 UnloadDLL (...)을 사용하면 아무 효과가 없으며 파일이 설치 프로그램이 종료 될 때까지 잠긴 상태로 유지됩니다. 2 초 동안 기다린 다음 temp 디렉토리 (또는 디렉토리 설치)에서 DLL 파일을 삭제하지 못합니다. 실제로 누군가가 드라이브를 정리할 때까지 실제로 그대로 있습니다. "* - 귀하의 대답으로는 문제를 해결할 수 없습니다. –

관련 문제