我想将一个巨大的Inno设置分成更小的包,这些包将他们的进度和状态分配给" master"建立。子设置应称为静默/隐藏,以便只有一个窗口在前面,并将所有其他窗口的进度集成到一个(总)进度条中。 我试图通过Windows管道系统进行相互通信,但即使创建命名管道也会失败。我已经使用了" \\。\ pipe \ SetupMsPipe123"并且在调试时它在给定变量中正确显示。甚至可以像" \\\\。\\ pipe \\ SetupMsPipe123"失败。 函数的返回值似乎是INVALID_HANDLE_VALUE,但Inno变量似乎只保存8字节句柄值的4个字节。 可能是变量之间的类型转换有问题。
(更新了TLama的建议)
[Code] {BOTH}
type
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
#define DefPipeName "\\.\pipe\SetupMsPipe123"
var
mhPipeHandle: THandle;
msPipeName : string;
type LPSECURITY_ATTRIBUTES = Cardinal; function CreateNamedPipe(lpName: string; dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut: DWORD; lpSecurityAttributes: LPSECURITY_ATTRIBUTES): THandle;
external 'CreateNamedPipe{#AW}@kernel32.dll stdcall';
function WaitNamedPipe(lpNamedPipeName: string; nTimeOut: DWORD): Boolean;
external 'WaitNamedPipe{#AW}@kernel32 stdcall';
function ConnectNamedPipe(hNamedPipe: THandle; lpOverlapped: LongWord): Boolean;
external 'ConnectNamedPipe@kernel32 stdcall';
function DisconnectNamedPipe(hNamedPipe: THandle): Boolean;
external 'DisconnectNamedPipe@kernel32 stdcall';
function CreateFile(lpFileName: string; dwDesiredAccess,dwShareMode: DWORD; lpSecurityAttributes: LPSECURITY_ATTRIBUTES; dwCreationDisposition,dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): LongWord;
external 'CreateFile{#AW}@kernel32 stdcall';
function ReadFile(hFile: THandle; lpBuffer: string; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: LongWord; var lpOverlapped: LongWord): Boolean;
external 'ReadFile@kernel32 stdcall';
function WriteFile(hFile: THandle; lpBuffer: string; nNumberOfBytesToWrite: DWORD; var lpNumberOfBytesWritten: LongWord; var lpOverlapped: LongWord): Boolean;
external 'WriteFile@kernel32 stdcall';
function CloseHandle(hObject: THandle): Boolean;
external 'CloseHandle@kernel32 stdcall';
function GetLastError(): DWORD;
external 'GetLastError@kernel32 stdcall';
[Code] {MASTER}
procedure InitializeWizard();
var
lcbProgress: longword;
lcbFilename: longword;
bStat: Boolean;
lpPipename: string;
begin
msPipeName := ExpandConstant('{#DefPipeName}');
mhPipeHandle := dllCreateNamedPipe(msPipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE or PIPE_NOWAIT, 2, 1024, 1024, 60000, 0);
if mhPipeHandle <> INVALID_HANDLE_VALUE then begin
bStat := dllConnectNamedPipe(mhPipeHandle, 0);
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
iProgressInner: integer;
bStat: Boolean;
acReadBuffer: string;
dwBufLen: DWORD;
dwBytesRead: DWORD;
dwOverlapped: DWORD;
begin
SetLength(acReadBuffer, 1024);
if CurStep = ssInstall then begin
Exec('setupInner.exe', '', '', SW_SHOW, ewNoWait, ResultCode);
while (iProgressInner<100) do begin
bStat := ReadFile(mhPipeHandle, acReadBuffer, Length(acReadBuffer), dwBytesRead, dwOverlapped);
iProgressInner := StrToInt(acReadBuffer);
WizardForm.Caption:='Progress: ' + IntToStr(iProgressInner);
WizardForm.Refresh();
Sleep (1000)
end;
end;
end;
procedure DeinitializeSetup();
begin
DisconnectNamedPipe(mhPipeHandle);
CloseHandle(mhPipeHandle);
end;
[code] {Slave}
function InitializeSetup(): Boolean;
var
bStat: Boolean;
lpOutBuffer: LongWord;
nOutBufferSize: DWORD;
lpBytesRead: LongWord;
begin
msPipeName := ExpandConstant('{#DefPipeName}');
bStat := WaitNamedPipe(msPipeName, 60000);
mhPipeHandle := CreateFile(msPipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Result := true;
end;
procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);
var
iProgress: integer;
bStat: Boolean;
acWriteBuffer: String;
dwBufLen: DWORD;
dwWritten: DWORD;
dwOverlapped: DWORD;
sTemp: String;
begin
sTemp := IntToStr(CurProgress);
while Length(sTemp) < 3 do begin
sTemp := '0' + sTemp;
end;
acWriteBuffer := sTemp;
// Here the exception occurs !!!
bStat := WriteFile(mhPipeHandle, acWriteBuffer, Length(acWriteBuffer), dwWritten, dwOverlapped);
end;