お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"アンインストールプログラム"

この発言に対し以下のコメントが寄せられています
#01402 牧原 博司   さん RE:アンインストールプログラム

アンインストール用プログラムです。 ファイルのコピーには、Delphi5\Demos\Doc\Filmanex にある FmxUtils.pas のCopyFileを使っています。 Uninst.exe(親プロセス) を実行すると、Windows ディレクトリにコピー し、コピーしたUninst.exe(子プロセス) を実行します。実行した Uninst.exe(子プロセス)が Uninst.exe(親プロセス)を停止・ファイル削除 し、Win9x では WinInit.ini を作成、WinNT では MoveFileEx で Windows 再 起動後にUninst.exe(子プロセス)を削除します。 nifty:FDELPHI/MES/16/1225 のTNさんの発言、「子プロセスに自分を殺さ せる」のコードを使用させていただきました。 ---------------------------------------------------------------------- program Uninst; uses Forms, Controls, Dialogs, Windows, ShlObj, FmxUtils, IniFiles, Classes, SysUtils, FileCtrl; {$R *.RES} // Windows ディレクトリを返す function GetWinDir: string; var Buffer: array[0..MAX_PATH - 1] of Char; begin SetString(Result, Buffer, GetWindowsDirectory(Buffer,SizeOf(Buffer))); end; // 自分自身を削除するための「WinInit.ini」を作成する procedure CreateWinInit; var Ini: TIniFile; begin Ini := TIniFile.Create(GetWinDir + '\WinInit.ini'); try Ini.WriteString('rename', 'NUL', Application.Exename); finally Ini.Free; end; end; // ファイルが存在したら、削除する function DelFile(FileName: string): boolean; begin Result := True; if not FileExists(FileName) then Exit; Result := DeleteFile(FileName); end; // ディレクトリが存在したら、削除する function DeleteDir(DirName: string): boolean; begin Result := True; try if DirectoryExists(DirName) then RmDir(DirName); except on EInOutError do Result := False; end; end; var SecAttr: TSecurityAttributes; S: string; Ph: THandle; St: TStringList; ReportList: TStringList; i: integer; // 子プロセスから親プロセスを殺せるように、継承ハンドルを // テキストファイルに保存して、CreateProcessを実行する procedure _CreateProcess(ExeFileName, HandleFileName: string); var Si: TStartupInfo; Pi: TProcessInformation; begin GetStartupInfo(Si); SecAttr.bInheritHandle := True; SecAttr.nLength := Sizeof(SecAttr); if Windows.CreateProcess( nil, PChar( ExeFileName ), @SecAttr, @SecAttr, True, CREATE_DEFAULT_ERROR_MODE, nil, PChar(GetCurrentDir), Si, Pi) then begin DuplicateHandle( GetCurrentProcess, GetCurrentProcess, Pi.hProcess, @Ph, 0, False, DUPLICATE_SAME_ACCESS ); St := TStringList.Create; try St.Add( InttoStr( Ph ) ); St.SaveToFile(HandleFileName); finally St.Free; end; end; end; // アンインストール処理 procedure Proc_Uninstall; begin { // ファイル削除の場合 if not DelFile(S) then ReportList.Add(S); // ディレクトリ削除の場合 if not DeleteDir(S) then ReportList.Add(S); // exeファイル(親プロセス)のあるディレクトリの削除は、 // もちろん、exeファイル(親プロセス)の削除です。 } end; begin Application.Initialize; Application.Title := 'Uninstall'; Application.Run; if (ParamCount=2) and (UpperCase(ParamStr(1))='/UNINSTALL') then begin ReportList := TStringList.Create; try // 元々の exe S := ParamStr(2) + '\' + ExtractFileName(Application.Exename); // Windows 再起動時に自分自身を削除する if Win32PlatForm=VER_PLATFORM_WIN32_NT then MoveFileEx(PChar(Application.Exename), nil, MOVEFILE_DELAY_UNTIL_REBOOT) else if Win32PlatForm=VER_PLATFORM_WIN32_WINDOWS then CreateWinInit; // アンインストール処理 Proc_Uninstall; // 親プロセス 停止 St := TStringList.Create; try St.LoadFromFile(GetWinDir + '\_Handle.Dat'); Ph := StrToInt( St[0] ); finally St.Free; end; TerminateProcess( Ph, 0 ); // テキストファイル(継承ハンドル)削除 if FileExists(GetWinDir + '\_Handle.Dat') then SysUtils.DeleteFile(GetWinDir + '\_Handle.Dat'); // exeファイル(親プロセス) 削除 if not DelFile(S) then ReportList.Add(S); if ReportList.Count=0 then S := 'アンインストールしました' else begin S := 'アンインストールしました' + #13 + '一部削除できませんでした' + #13#13; for i:=0 to ReportList.Count-1 do S := S + ReportList[i] + #13; end; finally ReportList.Free; end; end else begin SysUtils.Beep; if MessageDlg('アンインストールを実行してよろしいですか?', mtConfirmation,[mbYes,mbNo],0)=mrNo then Exit; // 自分自身をWindows ディレクトリにコピーする S := GetWinDir + '\' + ExtractFileName(Application.Exename); if Application.Exename=S then begin MessageDlg('Windows ディレクトリでは実行できません, mtError,[mbOK],0); Exit; end; FmxUtils.CopyFile(Application.Exename, S); // Windows ディレクトリにコピーした exe を実行する // 第一パラメータ = '/UNINSTALL' // 第二パラメータ = 実行したディレクトリ S := S +' /UNINSTALL "'+ ExtractFileDir(Application.Exename)+'"'; // コピーした exe を実行する // 子プロセスから親プロセスを殺せるように、継承ハンドルを // テキストファイルに保存して、CreateProcessを実行する _CreateProcess(PChar(S), GetWinDir + '\_Handle.Dat'); end; end. ---------------------------------------------------------------------- 牧原 博司 hiroshi.makihara@nifty.ne.jp - 2001/11/19 (Mon) 21:44 -  Original document by 牧原 博司   氏 ID:(QZS03450)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum