[Inno Setup] cmd 실행 뒤에 프로세스가 종료 안 되는 이슈

Inno Setup 툴은 윈도 애플리케이션을 패키징하는 툴이고, 스크립트 언어로 파스칼(Pascal)을 사용한다. 이 툴을 사용해서 애플리케이션을 패키징 하는 스크립트에서 애플리케이션 파일들을 복사하기 전/후에 외부 애플리케이션을 실행할 수 있다.
간단하게 스크립트 파일의 일부를 살펴보자.

[Files]
 Source: {#DefaultAssetFolderName}\NLog.dll; DestDir: {app}; Flags: ignoreversion
 .
 .
 .
[Run]
 Filename: "{cmd}"; Parameters: "/c taskkill /f /im explorer.exe"; Flags:runhidden;
 Filename: "{cmd}"; Parameters: "/c explorer.exe & exit"; Flags:runhidden;
[UninstallRun]
 Filename: "{cmd}"; Parameters: "/c taskkill /f /im explorer.exe"; Flags:runhidden;
 Filename: "{cmd}"; Parameters: "/c explorer.exe & exit"; Flags:runhidden;
[UninstallDelete]
 Type: filesandordirs; Name: {app}
 .
 .

위 소스는 다음의 과정을 거치게 된다.
1. 설치
1.1 [Files] 부분에 있는 파일들을 복사한다.
1.2 [Run] 부분을 차례로 실행한다.

2. 삭제
2.1 [UninstallRun] 부분을 차례로 실행한다.
2.2 [UninstallDelete] 부분에 있는 폴더/파일을 삭제한다.

위의 1.2와 2.1에서는 외부 애플리케이션으로 cmd를 사용하고 있다. 이 과정을 거치다 보면 설치는 되는데 cmd 프로세스가 종료되지 않는 문제와 삭제 시에 [UninstallDelete]의 과정으로 진행하지 못하는 문제가 있다.

그래서 이 경우를 해결하기 위해서 C#으로 애플리케이션을 만들어서 위의 과정을 실행시켜야 한다.

// 5초뒤에 프로세스를 종료시키는 스레드 시작 
Thread newThread = new Thread(new ThreadStart(Program.Run));
newThread.Start();

// cmd 실행 
ProcessStartInfo cmd = new ProcessStartInfo();
Process process = new Process();
cmd.FileName = @"cmd";
cmd.WindowStyle = ProcessWindowStyle.Hidden;             // cmd창이 숨겨지도록 하기
cmd.CreateNoWindow = true;                               // cmd창을 띄우지 안도록 하기

cmd.UseShellExecute = false;
cmd.RedirectStandardOutput = true;         // cmd창에서 데이터를 가져오기
cmd.RedirectStandardInput = true;          // cmd창으로 데이터 보내기
cmd.RedirectStandardError = true;          // cmd창에서 오류 내용 가져오기

process.EnableRaisingEvents = false;
process.StartInfo = cmd;
process.Start();

process.StandardInput.Write(@"taskkill /f /im explorer.exe" + Environment.NewLine);
process.StandardInput.Write(@"explorer.exe & exit" + Environment.NewLine);

process.StandardInput.Close();

string result = process.StandardOutput.ReadToEnd();
sb = new StringBuilder();
sb.Append("[Result Info]" + DateTime.Now + "\r\n");
sb.Append(result);
sb.Append("\r\n");

// 10초 대기
process.WaitForExit(10 * 1000);

public static void Run()
{
    Thread.Sleep(5 *1000);
    Application.ExitThread();
    Environment.Exit(0);
}

위 소스로 간단하게 cmd_exec.exe 애플리케이션을 만들었다고 가정하고, 패키징 스크립트를 수정하고 실행하면 정상으로 실행된다. 위 패키징 스크립트를 아래와 같이 변경해서 {cmd}로 수행하는 과정을 애플리케이션으로 래핑해서 실행시키면 된다.

[Files]
 Source: {#DefaultAssetFolderName}\NLog.dll; DestDir: {app}; Flags: ignoreversion
 .
 .
 .
[Run]
 Filename: "{app}\cmd_exec.exe"; Flags: runhidden waituntilterminated
[UninstallRun]
 Filename: "{app}\cmd_exec.exe"; Flags: runhidden waituntilterminated
[UninstallDelete]
 Type: filesandordirs; Name: {app}
 .
 .

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.