Last active
April 26, 2018 02:00
-
-
Save seraphy/8ce9084fa2074bb9fbca4be2f1de364f to your computer and use it in GitHub Desktop.
InnoSetupで、SHFileOperationを使った複数フォルダ/ファイルのコピーの例。 https://stackoverflow.com/questions/45244210/inno-setup-invoke-or-replicate-native-windows-file-copy-operation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; SHFileOperationまわりの定義を外部ファイルに分離している | |
#include "SHFileOperationModule.iss" | |
[Setup] | |
AppId=SHFileOperationExample | |
AppName=SHFileOperationExample | |
AppVersion=1.0.0 | |
VersionInfoVersion=1.0.0 | |
VersionInfoDescription={#SetupSetting("AppName")} Installer | |
OutputBaseFilename={#SetupSetting("AppName")}_{#SetupSetting("AppVersion")} | |
DefaultDirName={sd}\{#SetupSetting("AppName")} | |
DefaultGroupName=InnoSetupScriptExample | |
OutputDir=. | |
; 以前のインストールがある場合に以前のAppDirを使うか? | |
UsePreviousAppDir=No | |
SetupLogging=yes | |
[Files] | |
[Code] | |
procedure StartInstall(); | |
var | |
FromPath: array of string; | |
ToPath: string; | |
begin | |
FromPath := [ | |
ExpandConstant('{src}\data1.dat'), | |
ExpandConstant('{src}\data2.dat') | |
]; | |
ToPath := ExpandConstant('{app}\data\'); | |
ShellFileOperation(FromPath, ToPath, FILEOPE_COPY); | |
end; | |
{ インストールステップごとに呼び出される } | |
procedure CurStepChanged(CurStep: TSetupStep); | |
begin | |
case CurStep of | |
ssInstall: StartInstall(); | |
end; | |
end; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _INCLUDE_SHFILEOPERAIONMODULE_ | |
#define _INCLUDE_SHFILEOPERAIONMODULE_ | |
[CustomMessages] | |
FailedToShellFileOperation=Failed to %1 folder.%nerr=%2 | |
CancelToShellFileOperation=the %1 operation was cancelled by user. | |
[Code] | |
#IFDEF UNICODE | |
#DEFINE AW "W" | |
#ELSE | |
#DEFINE AW "A" | |
#ENDIF | |
// SHFileOperationを使ったファイルコピーの例 | |
// https://stackoverflow.com/questions/45244210/inno-setup-invoke-or-replicate-native-windows-file-copy-operation | |
type | |
TSHFileOpStruct = record | |
hwnd: HWND; | |
wFunc: UINT; | |
pFrom: string; | |
pTo: string; | |
fFlags: Word; | |
fAnyOperationsAborted: BOOL; | |
hNameMappings: HWND; | |
lpszProgressTitle: string; | |
end; | |
FILEOPE_TYP = (FILEOPE_COPY, FILEOPE_MOVE); | |
const | |
FO_MOVE = $0001; | |
FO_COPY = $0002; | |
FOF_NOCONFIRMATION = $0010; // 確認等不要 | |
FOF_NOCONFIRMMKDIR = $0200; // コピー先フォルダがない場合は暗黙でフォルダを作成する | |
ERR_CANCELED = 1223; // キャンセルした場合 | |
function SHFileOperation(lpFileOp: TSHFileOpStruct): Integer; | |
external 'SHFileOperation{#AW}@shell32.dll stdcall'; | |
function RetryOrRaise(msg: String): Boolean; forward; | |
procedure ShellFileOperation(srcs: array of string; dest: string; mode: FILEOPE_TYP); | |
var | |
FromPath: String; | |
ToPath: String; | |
idx: Integer; | |
FileOp: TSHFileOpStruct; | |
Msg: String; | |
strMode: String; | |
ret: Boolean; | |
retCode: Integer; | |
begin | |
case mode of | |
FILEOPE_COPY: begin | |
strMode := 'Copy'; | |
FileOp.wFunc := FO_COPY; | |
end; | |
FILEOPE_MOVE: begin | |
strMode := 'Move'; | |
FileOp.wFunc := FO_MOVE; | |
end; | |
else RaiseException('Unknown mode: ' + IntToStr(Ord(mode))); | |
end; | |
FileOp.hwnd := WizardForm.Handle; | |
FileOp.fFlags := FOF_NOCONFIRMATION + FOF_NOCONFIRMMKDIR; | |
repeat | |
// コピー元がフォルダまたはファイルとして実在する場合のみ | |
FromPath := ''; | |
for idx := 0 to GetArrayLength(srcs) -1 do begin | |
if DirExists(srcs[idx]) or FileExists(srcs[idx]) then begin | |
FromPath := FromPath + srcs[idx] + #0; // ヌル区切り、ダブルヌル終端 | |
end; | |
end; | |
// FromPathを表示用にセミコロン区切り文字列に変換する | |
Msg := FromPath; | |
StringChangeEx(Msg, #0, ';', True); | |
//MsgBox(Msg, mbInformation, MB_OK); | |
if FromPath = '' then begin | |
exit; // コピー・移動する内容が何もないので常に成功 | |
end; | |
ToPath := dest + #0; // ダブルヌル終端 | |
FileOp.pFrom := FromPath; | |
FileOp.pTo := ToPath; | |
retCode := SHFileOperation(FileOp); | |
ret := (retCode = 0); | |
if not ret then begin | |
if retCode = ERR_CANCELED then begin // キャンセルした場合 | |
ret := RetryOrRaise(ExpandConstant('{cm:CancelToShellFileOperation,' + | |
strMode + '}') +#13 #10 + 'src=' + Msg + #13 #10 + 'dest=' + dest); | |
end else begin // そのほかのエラー | |
ret := RetryOrRaise(ExpandConstant('{cm:FailedToShellFileOperation,' + | |
strMode + ',' + IntToStr(retCode) + '}') +#13 #10 + | |
'src=' + Msg + #13 #10 + 'dest=' + dest); | |
end; | |
end; | |
until ret; | |
end; | |
/////////////////////////////////////////////////// | |
// リトライ・無視・Abortのダイアログを表示し | |
// リトライの場合はFalse、無視の場合はTrueを返す. | |
// Abortの場合は例外をあげる. | |
function RetryOrRaise(msg: String): Boolean; | |
begin | |
Result := False; | |
// リトライ・無視・アボートのいずれかの選択ダイアログ | |
// (無人インストール時はABORT応答扱いとする.) | |
case SuppressibleMsgBox(msg, mbError, MB_ABORTRETRYIGNORE or MB_DEFBUTTON2, IDABORT) of | |
IDIGNORE: begin | |
// 成功してものと見なして次に進む | |
Result := True; | |
exit; | |
end; | |
IDABORT: begin | |
// 例外で終了する | |
RaiseException('Installation abort by user: ' + msg); | |
end; | |
end; | |
end; | |
[/Code] | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment