Вопрос по – Inno Setup: чтение измененного времени из одного файла и использование его для установки времени для файлов во всем каталоге

2

В моем установщике я извлекаю файлы из архивов, в которых не хранятся атрибуты времени и даты, поэтому при их извлечении дата последнего изменения устанавливается на текущую дату. Я хотел бы установить дату последнего изменения файла архива, но не могу понять, как это сделать. Я пытался использовать кусочки кода изВот а такжеВот но, хотя он не давал никаких ошибок, он не работал для изменения времени. Дата последнего изменения должна быть изменена на *. * В папке.

Also, where do I need to hook into to delete these files if the user cancels setup and it starts rolling back changes? I've got it taken care of in UninstallDelete but not if the user cancels setup.

РЕДАКТИРОВАТЬ: не обращая внимания на вторую часть, я на самом деле понял это вскоре после того, как я разместил здесь. Добавлен мой собственный CleanUp () в DeinitializeSetup () с проверкой ключа реестра деинсталлятора.

Вот фрагмент кода, к которому я пытаюсь добавить его:

procedure VolExtract(VWorld: String);
var
  ResultCode: Integer;
  VPath: String;
begin
  // Files are extracted to {app}\VWorld\One, {app}\VWorld\Two, etc.
  VPath := ExpandConstant('{app}\' + VWorld);
  WizardForm.FilenameLabel.Caption := DriveLetter + VWorld + '\one.vol';
  if Exec(ExpandConstant('{tmp}\volextract.exe'), '"' + DriveLetter + VWorld + '\one.vol" "' + VPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then
  begin
    // Yep, it executed successfully
    WizardForm.FilenameLabel.Caption := DriveLetter + VWorld + '\two.vol';
    if Exec(ExpandConstant('{tmp}\volextract.exe'), '"' + DriveLetter + VWorld + '\two.vol" "' + VPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then
    begin
      // Next
      WizardForm.FilenameLabel.Caption := DriveLetter + VWorld + '\three.vol';
      if Exec(ExpandConstant('{tmp}\volextract.exe'), '"' + DriveLetter + VWorld + '\three.vol" "' + VPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0) then
      begin
        // Next
        WizardForm.FilenameLabel.Caption := DriveLetter + VWorld + '\four.vol';
        Exec(ExpandConstant('{tmp}\volextract.exe'), '"' + DriveLetter + VWorld + '\four.vol" "' + VPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
      end;
    end;
  end;
  if ResultCode <> 0 then
  begin
    // Handle Fail
    CDFound := False;
    MsgBox(CustomMessage('FileErr'), mbInformation, MB_OK);
    WizardForm.Close;
  end;
end;

Ваш Ответ

2   ответа
2

о LastWriteTime) для всех файлов из указанного каталога с помощью LastWriteTime определенного файла, используйте следующий код после извлечения файлов. Вы можете следоватьcommented version предыдущей версии этого поста, но обратите внимание, что у меня там были ошибки (смешанные временные параметры и параметр неиспользуемого флажка файла), но точка остается.

Также обратите внимание, что этот код предназначен для ANSI-версии InnoSetup. Если вам нужно использовать это для версии Unicode, вы должны определитьCreateFile импорт функции какCreateFileW вместоCreateFileA или используйте трюк, предложенныйkobik в этомpost.

[code]
const
  OPEN_EXISTING = 3;  
  FILE_SHARE_WRITE = 2;
  GENERIC_WRITE = $40000000;
  INVALID_HANDLE_VALUE = 4294967295;

function CreateFile(lpFileName: string; dwDesiredAccess, dwShareMode,
  lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes: DWORD;
  hTemplateFile: THandle): THandle; 
  external '[email protected] stdcall';
function CloseHandle(hObject: THandle): BOOL; 
  external '[email protected] stdcall';
function SetFileTime(hFile: THandle; const lpCreationTime, lpLastAccessTime, 
  lpLastWriteTime: TFileTime): BOOL; 
  external '[email protected] stdcall';

function FileSetTime(const AFileName: string; const ACreationTime, 
  ALastAccessTime, ALastWriteTime: TFileTime): Boolean;
var
  FileHandle: THandle;
begin
  Result := False;
  FileHandle := CreateFile(AFileName, GENERIC_WRITE, FILE_SHARE_WRITE, 0,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if FileHandle <> INVALID_HANDLE_VALUE then
  try
    Result := SetFileTime(FileHandle, ACreationTime, ALastAccessTime, 
      ALastWriteTime);
  finally
    CloseHandle(FileHandle);
  end;
end; 

procedure ModifyLastWriteTime(const ASourceFile, ATargetFolder: string);
var
  FindRec: TFindRec;
  LastWriteTime: TFileTime;
begin
  if FindFirst(ASourceFile, FindRec) then
  begin
    LastWriteTime := FindRec.LastWriteTime;
    if FindFirst(ATargetFolder + '*.*', FindRec) then
    try
      repeat
        if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
          FileSetTime(ATargetFolder + FindRec.Name, FindRec.CreationTime, 
            FindRec.LastAccessTime, LastWriteTime);
      until
        not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end;
end;

И использование. Первый параметрModifyLastWriteTime процедура - это имя исходного файла, из которого берется LastWriteTime. Второй параметр - это каталог, в котором файлы будут изменять свои значения LastWriteTime исходным файлом (не забудьте добавить обратную косую черту в параметре целевой папки):

ModifyLastWriteTime('c:\SourceFile.xxx', 'c:\TargetFolder\')
Отлично! Я попробую это прямо сейчас, если это сработает, я пойду дальше и отмечу это как ответ. Большое спасибо :) user477276
0

вы можете удалить файлы, которые были извлечены в процедуре под названием

Procedure CancelButtonClick(CurPageID: Integer; Var Cancel, Confirm: Boolean);
Begin
End;

Как объяснено в разделе chm,Pascal Scripting: Event Functions

Что касается первого вопроса, я бы предложил вам использовать раздел inno setup [files] вместо извлечения из архива. Возможно, вы могли бы распаковать этот архив в локальную папку (то есть со своей стороны, перед компиляцией, и добавить эту локальную папку в [файлы]. Но я могу неправильно понять ваш императив относительно даты изменения файла.

Да, это было мое понимание CancelButtonClick уже. Мне действительно удалось выяснить эту часть вскоре после того, как я первоначально разместил этот вопрос, и у меня еще не было возможности обновить его. Я добавил процедуру CleanUp () в DeinitializeSetup () с проверкой ключа деинсталлятора в реестре. user477276
вCancelButtonClick Вы можете установитьConfirm а такжеCancel Параметры в True, и вы получите подтверждениеExit setup ? диалоговое окно после кода в этом событии сделано. Так что это не то место, потому что вы можете отклонить это диалоговое окно подтверждения.

Похожие вопросы