Inno setup Inno Setup在CD上搜索特定文件,检索确切的文件路径并将值返回到[Files]-部分

Inno setup Inno Setup在CD上搜索特定文件,检索确切的文件路径并将值返回到[Files]-部分,inno-setup,Inno Setup,我想为2张CD上的旧程序制作一个安装程序,我想直接从光盘上安装文件 启动时,安装程序应检查某个文件是否存在,这意味着第一张CD已插入CD rom驱动器。 这是该任务的代码: [Files] Source: {code: ??? }; Destination: {app}; flags:external; [Code] procedure InitializeWizard(); begin if not FileExists('A:\Resource\CD1.GOB') xor

我想为2张CD上的旧程序制作一个安装程序,我想直接从光盘上安装文件

启动时,安装程序应检查某个文件是否存在,这意味着第一张CD已插入CD rom驱动器。 这是该任务的代码:

[Files]
Source: {code: ??? }; Destination: {app}; flags:external;

[Code]
procedure InitializeWizard();
begin
  if not FileExists('A:\Resource\CD1.GOB') xor
         FileExists('B:\Resource\CD1.GOB') xor
         // and so on, for every drive letter...
         FileExists('Z:\Resource\CD1.GOB') then
         Repeat
           if MsgBox('Insert the first CD!', mbInformation, MB_OKCANCEL) = IDCANCEL then
           ExitProcess(0);
         Until  FileExists('A:\Resource\CD1.GOB') or
                FileExists('B:\Resource\CD1.GOB') or
                // going through all letters again...
                FileExists('Z:\Resource\CD1.GOB') = true;
因此,这是预期的效果。如果未插入CD,因此无法找到文件,将显示一条消息,要求用户插入CD

但是我想知道是否有更好的方法来增加驱动器号,因为这太乱了

第二,如何保存完整的文件路径并将其传递到[Files]部分

我希望你能帮我做这件事

更新:

我又试了一次,得出了以下结论:

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageId = wpWelcome then
  begin
    WizardForm.NextButton.Enabled := False; 
    repeat
      for i:=0 to 31 do
        dstr := (Chr(Ord('A') + i) + ':\Resource\CD1.gob');
    until FileExists(dstr);
    WizardForm.NextButton.Enabled := True; 
  end;
end;

但使用此代码时,安装程序在开始时会冻结,即使CD已插入,也不会响应。

类似的操作应该可以满足您的需要:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Files]
Source: {code:GetFileSource}; DestDir: {app}; flags:external;

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  TDriveType = (
    dtUnknown,
    dtNoRootDir,
    dtRemovable,
    dtFixed,
    dtRemote,
    dtCDROM,
    dtRAMDisk
  );
  TDriveTypes = set of TDriveType;
function GetDriveType(lpRootPathName: string): UINT;
  external 'GetDriveType{#AW}@kernel32.dll stdcall';
function GetLogicalDriveStrings(nBufferLength: DWORD; lpBuffer: string): DWORD;
  external 'GetLogicalDriveStrings{#AW}@kernel32.dll stdcall';

var
  FileSource: string;

#ifndef UNICODE
function IntToDriveType(Value: UINT): TDriveType;
begin
  Result := dtUnknown;
  case Value of
    1: Result := dtNoRootDir;
    2: Result := dtRemovable;
    3: Result := dtFixed;
    4: Result := dtRemote;
    5: Result := dtCDROM;
    6: Result := dtRAMDisk;
  end;
end;
#endif

function GetLogicalDrives(var ADrives: array of string; 
  AFilter: TDriveTypes): Integer;
var
  S: string;
  I: Integer;
  DriveRoot: string;
begin
  Result := 0;
  SetArrayLength(ADrives, 0);

  I := GetLogicalDriveStrings(0, #0);
  if I > 0 then
  begin
    SetLength(S, I);
    if GetLogicalDriveStrings(Length(S), S) > 0 then
    begin
      S := TrimRight(S);
      I := Pos(#0, S);
      while I > 0 do
      begin
        DriveRoot := Copy(S, 1, I - 1);
        #ifdef UNICODE
        if (AFilter = []) or
          (TDriveType(GetDriveType(DriveRoot)) in AFilter) then
        #else
        if (AFilter = []) or
          (IntToDriveType(GetDriveType(DriveRoot)) in AFilter) then
        #endif
        begin
          SetArrayLength(ADrives, GetArrayLength(ADrives) + 1);
          #ifdef UNICODE
          ADrives[High(ADrives)] := DriveRoot;
          #else
          ADrives[GetArrayLength(ADrives) - 1] := DriveRoot;
          #endif
        end;
        Delete(S, 1, I);
        I := Pos(#0, S);
      end;
      Result := GetArrayLength(ADrives);
    end;
  end;
end;

function GetFileSource(Value: string): string;
begin
  // file source path passed to the [Files] section
  Result := FileSource;
end;

procedure InitializeWizard;
var
  I: Integer;
  DriveCount: Integer;
  DriveArray: array of string;
begin
  // the function will fill the DriveArray only with CDROM
  // drives and returns the count of found drives
  DriveCount := GetLogicalDrives(DriveArray, [dtCDROM]);
  // here you have an array of CD-ROM drives so iterate it
  // search for a file you need and when you find it, pass
  // the path to the FileSource variable, which will later
  // be queried to get the source to the file in [Files]
  for I := 0 to DriveCount - 1 do
  begin
    if FileExists(DriveArray[I] + 'Resource\CD1.GOB') then
    begin
      FileSource := DriveArray[I] + 'Resource\CD1.GOB';
      Break;
    end;
  end;
  MsgBox('File was found on path: ' + FileSource, mbInformation, MB_OK);
end;

我现在想换一种方式。使用“我的方法”时,如果插入CD并在消息框中单击“确定”,向导将等待,直到选中CD为止。这是因为安装程序检查了两次。所以我想去掉这个消息框,在欢迎页面上实现这个检查(可能是你的)。在CD-ROM驱动器上找到特定文件之前,将显示一条消息,提示“插入CD”。在找到文件之前,“下一步”按钮应该是灰色的。好吧,看来我的帖子不适合你,所以发布你自己的答案并接受它。。。现在我很后悔我一直在浪费时间准备答案。对不起,但我仍然可以用不同的方式。也许你的答案可以帮助其他人,所以去发布吧!我不确定我是否能像我想象的那样去做。嗯,也许我们彼此不了解。您一直在问如何优化您的脚本,以避免写入每个驱动器号来查找CD上的特定文件。好的,您可以使用一些循环,在其中您可以将字母从
A
递增到
Z
,并从中构建路径,但是谁能保证您的用户不会在驱动器
d
上拥有该文件,例如,该驱动器可以是硬盘驱动器?我在这方面使用了不同的方法。我得到了所有CD/DVD驱动器的列表,并只检查它们上是否存在该文件(是什么使该检查更安全了)。我再次查看了它。文件是否在CD或硬盘上并不重要。我想在欢迎页面上执行检查,以便在找到文件之前禁用“下一步”按钮。但是我错误地实现了它,因此向导不再响应。