Inno setup Inno设置之间通过管道的进程间通信无法创建管道

Inno setup Inno设置之间通过管道的进程间通信无法创建管道,inno-setup,communication,named-pipes,interprocess,Inno Setup,Communication,Named Pipes,Interprocess,我想将一个巨大的Inno设置分离成更小的包,将它们的进度和状态提供给“主”设置。子设置应称为静默/隐藏,以便只有一个窗口位于前面,并将所有其他窗口的进度集成到一个(总)进度条中。 我曾尝试通过Windows管道系统进行内部通信,但即使创建命名管道也失败了。我使用了“\\.\pipe\SetupMsPipe123”,在调试时,它在给定变量中正确显示。甚至像“\\.\\pipe\\SetupMsPipe123”这样的附加转义也失败了。 函数的返回值似乎是无效的句柄值,但Inno变量似乎只包含8字节句

我想将一个巨大的Inno设置分离成更小的包,将它们的进度和状态提供给“主”设置。子设置应称为静默/隐藏,以便只有一个窗口位于前面,并将所有其他窗口的进度集成到一个(总)进度条中。 我曾尝试通过Windows管道系统进行内部通信,但即使创建命名管道也失败了。我使用了“\\.\pipe\SetupMsPipe123”,在调试时,它在给定变量中正确显示。甚至像“\\.\\pipe\\SetupMsPipe123”这样的附加转义也失败了。 函数的返回值似乎是无效的句柄值,但Inno变量似乎只包含8字节句柄值中的4个字节。 变量之间的类型转换可能有问题

(根据TLama的建议更新)

[code]{BOTH}
类型
#ifdef UNICODE
#定义AW“W”
#否则
#定义“A”
#恩迪夫
#定义DefPipeName“\\。\pipe\SetupMsPipe123”
变量
MH管柄:THandle;
msPipeName:string;
键入LPSECURITY_ATTRIBUTES=Cardinal;函数CreateNamedPipe(lpName:string;dwOpenMode,dwPipeMode,NmaxinStations,nOutBufferSize,nInBufferSize,nDefaultTimeOut:DWORD;lpSecurityAttributes:LPSECURITY_属性):THandle;
外部“CreateNamedPipe{#AW}@kernel32.dll stdcall”;
函数WaitNamedPipe(lpNamedPipeName:string;nTimeOut:DWORD):布尔;
外部“WaitNamedPipe{#AW}@kernel32 stdcall”;
函数ConnectNamedPipe(hNamedPipe:THandle;lpOverlapped:LongWord):布尔值;
外部的ConnectNamedPipe@kernel32stdcall';
函数DisconnectNamedPipe(hNamedPipe:THandle):布尔值;
外部的DisconnectNamedPipe@kernel32stdcall';
函数CreateFile(lpFileName:string;dwDesiredAccess,dwShareMode:DWORD;lpSecurityAttributes:LPSECURITY_属性;dwCreationDisposition,dwFlagsAndAttributes:DWORD;hTemplateFile:THandle):LongWord;
外部“CreateFile{#AW}@kernel32 stdcall”;
函数读取文件(hFile:THandle;lpBuffer:string;nNumberOfBytesToRead:DWORD;var lpNumberOfBytesRead:LongWord;var lpOverlapped:LongWord):布尔值;
外部的ReadFile@kernel32stdcall';
函数WriteFile(hFile:THandle;lpBuffer:string;nNumberOfBytesWrite:DWORD;var lpNumberOfBytesWrite:LongWord;var lpOverlapped:LongWord):布尔;
外部的WriteFile@kernel32stdcall';
函数CloseHandle(hObject:THandle):布尔;
外部的CloseHandle@kernel32stdcall';
函数GetLastError():DWORD;
外部的GetLastError@kernel32stdcall';
[代码]{MASTER}
过程初始化Wizard();
变量
立法会二题:长字词;
LCB文件名:长单词;
bStat:布尔型;
lpPipename:字符串;
开始
msPipeName:=ExpandConstant('{#DefPipeName}');
mhPipeHandle:=dllCreateNamedPipe(msPipeName、管道访问权、管道类型字节或管道NOWAIT、2、1024、1024、60000、0);
如果mhpipehold的值无效,则开始
bStat:=dllConnectNamedPipe(mhPipeHandle,0);
结束;
结束;
过程CurStepChanged(CurStep:TSetupStep);
变量
iProgressInner:整数;
bStat:布尔型;
acReadBuffer:字符串;
德布弗伦:德沃德;
德比特斯拉德:德沃德;
德沃德:德沃德;
开始
设置长度(acReadBuffer,1024);
如果CurStep=ssInstall,则开始
Exec('setupInner.exe'、''、'SW_SHOW、ewNoWait、ResultCode);

while(iProgressInnerHandle是32位,而不是64位(有可用的
THandle
类型)。Inno安装程序不使用反斜杠转义。代码中可疑的是
AnsiString
类型用于
lpName
参数。如果使用Unicode Inno安装程序,这将失败(因为您将调用需要Unicode输入的函数的变体
CreateNamedPipeW
)。尝试运行此操作。是的,成功了。管道似乎按预期创建,但现在我无法写入。它抛出“访问冲突…在模块KERNELBASE.dll中。写入地址00000000”因此,主节点执行以下步骤:
code
CreateNamedPipe-ConnectNamedPipe-ReadFile-DisconnectNamedPipe-CloseHandle和从节点:
code
WaitNamedPipe-CreateFile-WriteFile-CloseHandle我使用了一个字符串作为writebuffer,其中包含“001”它应该以百分比表示进度。我看不到您的代码,因此我无法提供帮助。但是为这些内容创建一个小型库(如果只是更新进度,则使用Windows消息)不是更好的选择.Code已更新。从长远来看,不仅进度,而且当前处理的文件名、错误状态或其他可行信息都必须传递给主机。这就是使用管道或共享内存原则的原因。
[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;