Информация Удаление файлов по логу установки. (Решено)

Andreo Fadio

Старожил
@Xenium, чтобы работало надо задавать:

Exec(ExpandConstant('{cmd}'), ExpandConstant('/C attrib -R -H "appdir\*.*" /s /d'), '', SW_SHOW, ewWaitUntilTerminated, ResultCode);

Или задать значение appdir уже сразу:

appdir := ExpandConstant('{app}');
 

Xenium

Новичок
@Andreo Fadio,
@Xenium, чтобы работало надо задавать:

Exec(ExpandConstant('{cmd}'), ExpandConstant('/C attrib -R -H "appdir\*.*" /s /d'), '', SW_SHOW, ewWaitUntilTerminated, ResultCode);

Или задать значение appdir уже сразу:

appdir := ExpandConstant('{app}');
К сожалению тоже ничего не меняет. Как были файлы readonly так и остались, пока полный путь вручную не прописать.
 
Последнее редактирование:

Xenium

Новичок
@sergey3695, @Andreo Fadio, Думаю попробовать с этим делом что-то....


Код:
function GetFileAttributes(lpFileName: PAnsiChar): DWORD;
external 'GetFileAttributesA@kernel32.dll stdcall';

function SetFileAttributes(lpFileName: PAnsiChar;
   dwFileAttributes: DWORD): BOOL;
external 'SetFileAttributesA@kernel32.dll stdcall';

procedure RemoveReadOnly(FileName : String);
var
Attr : DWord;
begin
  Attr := GetFileAttributes(FileName);
  if (Attr and 1) = 1  then        
  begin
    Attr := Attr -1;
    SetFileAttributes(FileName,Attr);
  end;
end;

/UPD.
Теперь работает, но по отдельности)
Вместе выдает ошибку "list index out of bounds 1"


Код:
SvfList := TStringList.Create;
SvfList.LoadFromFile(ExpandConstant('{app}\INSTALL.LOG'));
  for i := 0 to SvfList.Count-1 do
RemoveReadOnly(ExpandConstant('{app}\'+SvfList[i]));
DeleteFile(ExpandConstant('{app}\'+SvfList[i]));
 
Последнее редактирование:

Xenium

Новичок
@Andreo Fadio,
Код:
    Exec('attrib', ExpandConstant(' -h -s -r /D "{app}\*.*"'),'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
    Exec('attrib', ExpandConstant(' -h -s -r "{app}\*.*"'),'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
потом выполняете приведенный пример очистки.
Так сработало, спасибо)
А что на счет использования procedure RemoveReadOnly ? Ее не лучше использовать вместо обращения к cmd?

Я думаю, что нужно что-то изменить в этом месте
for i := 0 to SvfList.Count-1 do
, но не могу понять что и как.

UPD/ Все оказалось еще проще...))) Проблема решена.
 
Последнее редактирование:

Xenium

Новичок
@Formular и для всех интересующихся данной проблемой)

1- Необходимо создать .bat файл со следующим содержимым:

Код:
@Echo Off
SetLocal EnableDelayedExpansion
Set DataRoot=%~dp0
Set OutFile=filelist.list
For /F "delims=" %%A In ('Dir "%DataRoot%\*.*" /B /S /A-D 2^>nul') Do (
  Set str=%%A
  Set stra=!str:%~dp0=!
  Echo !stra!>>"%OutFile%")
Pause
- Кидаем батник в папку с нашими файлами(которые потом будут устанавливаться на ПК юзеру)
- Запускаем батник, после чего он создаст файл filelist.list
- filelist.list - пакуем в наши архивы

Далее код, который использую я (спасибо всем, кто откликнулся ранее)
Код:
//Удаление файлов по списку - start
procedure ScanDir(SearchPath: String);
var
  FindRec: TFindRec;
begin
  if FindFirst(ExpandConstant(AddBackslash(SearchPath)+'*.*'), FindRec) then
  begin
    try
      repeat
        if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
        begin
          if (FindRec.Name<>'.') and (FindRec.Name<>'..') then
          begin
            List.Add(AddBackslash(SearchPath) + FindRec.Name + '\');
            ScanDir(AddBackslash(SearchPath) + FindRec.Name + '\');
          end;
        end;
      until not FindNext(FindRec);
      finally
      FindClose(FindRec);
    end;
  end;
end;


function GetFileAttributes(lpFileName: PAnsiChar): DWORD;
external 'GetFileAttributesA@kernel32.dll stdcall';

function SetFileAttributes(lpFileName: PAnsiChar; dwFileAttributes: DWORD): BOOL;
external 'SetFileAttributesA@kernel32.dll stdcall';

procedure RemoveReadOnly(FileName : String);
var
  Attr : DWord;
begin
  Attr := GetFileAttributes(FileName);
  if (Attr and 1) = 1  then
    begin
      Attr := Attr -1;
      SetFileAttributes(FileName,Attr);
  end;
end;


procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
  i: integer;
  z: integer;
  n: integer;
  SvfList: TStringlist;
  Checked: TStringlist;
  ResultCode: Integer;
begin
  if (CurUninstallStep = usUninstall) then
      begin
      // fix "read-only" status of only files for
        SvfList := TStringList.Create;
        SvfList.LoadFromFile(ExpandConstant('{app}\Uninstall\filelist.list'))
        for i := 0 to SvfList.Count-1 do
        RemoveReadOnly(ExpandConstant('{app}\'+SvfList[i]));
      begin
        for z := 0 to SvfList.Count-1 do
        DeleteFile(ExpandConstant('{app}\'+SvfList[z]));
      // delete empty folders
      begin
        List := TStringList.Create;
        ScanDir(ExpandConstant('{app}\'));
        if (List.Count<>0) then
      begin
        for n:= List.Count-1 downto 0 do
        RemoveDir(List[n]);
      end;
      List.Free;
      DeleteFile(ExpandConstant('{app}\Uninstall\filelist.list'))
      end;
      end;
      end
end;
//Удаление файлов по списку - end
Обращаю внимание, что ЛОГ создаем батником, а не средствами Inno Setup (т.к инно пропускает некоторые файлы, что в итоге выливается в проблему при удалении - не все файлы будут удалены)
 
Последнее редактирование:

ilyaign86

Новичок
@Formular и для всех интересующихся данной проблемой)

1- Необходимо создать .bat файл со следующим содержимым:

Код:
@Echo Off
SetLocal EnableDelayedExpansion
Set DataRoot=%~dp0
Set OutFile=filelist.list
For /F "delims=" %%A In ('Dir "%DataRoot%\*.*" /B /S /A-D 2^>nul') Do (
  Set str=%%A
  Set stra=!str:%~dp0=!
  Echo !stra!>>"%OutFile%")
Pause
- Кидаем батник в папку с нашими файлами(которые потом будут устанавливаться на ПК юзеру)
- Запускаем батник, после чего он создаст файл filelist.list
- filelist.list - пакуем в наши архивы

Далее код, который использую я (спасибо всем, кто откликнулся ранее)
Код:
//Удаление файлов по списку - start
procedure ScanDir(SearchPath: String);
var
  FindRec: TFindRec;
begin
  if FindFirst(ExpandConstant(AddBackslash(SearchPath)+'*.*'), FindRec) then
  begin
    try
      repeat
        if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
        begin
          if (FindRec.Name<>'.') and (FindRec.Name<>'..') then
          begin
            List.Add(AddBackslash(SearchPath) + FindRec.Name + '\');
            ScanDir(AddBackslash(SearchPath) + FindRec.Name + '\');
          end;
        end;
      until not FindNext(FindRec);
      finally
      FindClose(FindRec);
    end;
  end;
end;


function GetFileAttributes(lpFileName: PAnsiChar): DWORD;
external 'GetFileAttributesA@kernel32.dll stdcall';

function SetFileAttributes(lpFileName: PAnsiChar; dwFileAttributes: DWORD): BOOL;
external 'SetFileAttributesA@kernel32.dll stdcall';

procedure RemoveReadOnly(FileName : String);
var
  Attr : DWord;
begin
  Attr := GetFileAttributes(FileName);
  if (Attr and 1) = 1  then
    begin
      Attr := Attr -1;
      SetFileAttributes(FileName,Attr);
  end;
end;


procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
  i: integer;
  z: integer;
  n: integer;
  SvfList: TStringlist;
  Checked: TStringlist;
  ResultCode: Integer;
begin
  if (CurUninstallStep = usUninstall) then
      begin
      // fix "read-only" status of only files for
        SvfList := TStringList.Create;
        SvfList.LoadFromFile(ExpandConstant('{app}\Uninstall\filelist.list'))
        for i := 0 to SvfList.Count-1 do
        RemoveReadOnly(ExpandConstant('{app}\'+SvfList[i]));
      begin
        for z := 0 to SvfList.Count-1 do
        DeleteFile(ExpandConstant('{app}\'+SvfList[z]));
      // delete empty folders
      begin
        List := TStringList.Create;
        ScanDir(ExpandConstant('{app}\'));
        if (List.Count<>0) then
      begin
        for n:= List.Count-1 downto 0 do
        RemoveDir(List[n]);
      end;
      List.Free;
      DeleteFile(ExpandConstant('{app}\Uninstall\filelist.list'))
      end;
      end;
      end
end;
//Удаление файлов по списку - end
Обращаю внимание, что ЛОГ создаем батником, а не средствами Inno Setup (т.к инно пропускает некоторые файлы, что в итоге выливается в проблему при удалении - не все файлы будут удалены)
есть косяк с BAT, в одной игре, файлы которой сканировал, был в папке файл COW!.wav. Так вот этот BAT восклицательный знак, возможно и какие-то другие подобные, не видит и записывает просто как COW.wav
 

Andreo Fadio

Старожил
есть косяк с BAT, в одной игре, файлы которой сканировал, был в папке файл COW!.wav. Так вот этот BAT восклицательный знак, возможно и какие-то другие подобные, не видит и записывает просто как COW.wav
Сделай создание лога на самом IS

Код:
[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Code]
var
WayScan: String;

procedure MaskScanFilesInListStr(ADirName,AFileName,AFileName2,Mask:String);
var
FindRec: TFindRec;
SD: String;
begin
  if FindFirst(AddBackslash(ADirName)+'*.*', FindRec) then begin
   try
    repeat
     if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then begin
      if (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin
       MaskScanFilesInListStr(AddBackslash(ADirName)+FindRec.Name,AFileName,AFileName2,Mask);
      end;
     end else begin
      SD:= AddBackslash(ADirName)+FindRec.Name;
      if (Pos(AnsiLowerCase(AFileName), AnsiLowerCase(SD)) = 0) and
         (Pos(AnsiLowerCase(AFileName2), AnsiLowerCase(SD)) = 0) then
      begin
       StringChangeEx(SD, WayScan, Mask, true);  
       SaveStringToFile(AFileName2, SD+#13#10, True);
      end;
     end;
    until not FindNext(FindRec);
   finally
    FindClose(FindRec);
   end;
  end;
end;

function InitializeSetup: Boolean;
var
strFileName: String;
strTextfile: TArrayOfString;
begin
  WayScan:= ExpandConstant('{src}');
  strFileName:= ExpandConstant('{src}\Install.log');
  if FileExists(strFileName) then DeleteFile(strFileName);
  MaskScanFilesInListStr(WayScan,ExtractFileName(ExpandConstant('{srcexe}')),ExtractFileName(strFileName),'ForChange');
  if MsgBox('Хотите сконвертировать файл из ANSI в UTF8?', mbInformation, MB_YESNO) = IDYES then begin
   LoadStringsFromFile(strFileName, strTextfile);
   SaveStringsToUTF8File(strFileName, strTextfile,False);
  end;
  Result:= False;
end;
 
Последнее редактирование:

Xenium

Новичок
Сделай создание лога на самом IS

Код:
[Setup]
AppName = MyApp
AppVerName = MyApp
DefaultDirname = {pf}\MyApp
OutputDir=.

[Code]
procedure MaskScanFilesInListStr(ADirName,AFileName,AFileName2:String);
var
FindRec: TFindRec;
SD: String;
begin
  if FindFirst(AddBackslash(ADirName)+'*.*', FindRec) then begin
   try
    repeat
     if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then begin
      if (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin
       MaskScanFilesInListStr(AddBackslash(ADirName)+FindRec.Name,AFileName,AFileName2);
      end;
     end else begin
      SD:= AddBackslash(ADirName)+FindRec.Name;
      if (Pos(AnsiLowerCase(AFileName), AnsiLowerCase(SD)) = 0) and
         (Pos(AnsiLowerCase(AFileName2), AnsiLowerCase(SD)) = 0) then
      begin
       StringChangeEx(SD, ExpandConstant('{src}\'), '', true);   
       SaveStringToFile(ExpandConstant('{src}')+'\'+AFileName2, SD+#13#10, True);
      end;
     end;
    until not FindNext(FindRec);
   finally
    FindClose(FindRec);
   end;
  end;
end;

function InitializeSetup: Boolean;
begin
if FileExists(ExpandConstant('{src}\Install.log')) then
  DeleteFile(ExpandConstant('{src}\Install.log'));
MaskScanFilesInListStr(ExpandConstant('{src}'),ExtractFileName(ExpandConstant('{srcexe}')),'Install.log');
Result:= False; 
end;
Он так не все файлы пишет в лог, если Вы тему читали внимательно)
 

Xenium

Новичок
есть косяк с BAT, в одной игре, файлы которой сканировал, был в папке файл COW!.wav. Так вот этот BAT восклицательный знак, возможно и какие-то другие подобные, не видит и записывает просто как COW.wav
Вы можете сделать решение на PowerShell и поделиться с коллегами)
 

Andreo Fadio

Старожил
Он так не все файлы пишет в лог, если Вы тему читали внимательно)
а тут не при установке делается чтением распаковываемого файла, а запуском сканирования после конкретной папки или за ранее до сжатия. Пишет все, покрайней мере у меня :D
 

ilyaign86

Новичок
Вот остановился на решении ниже. Помогли на другом форуме с написанием БАТ-ника, подредактировали мне его спецы более правильно, за что благодарен. Отказался от всяких логов как от лишнего элемента: устанавливаете игру > запускаете файл в папке > получаете готовый результат, который потом чуть подчистив лишнее, копируете в раздел [UninstallDelete]. Получится, что деинсталлятор удалит только распакованные файлы. Даже запись кода распакованной Half-Life с ~90 тыс. файлов занимает несколько секунда.

Код:
@Echo off
    Set "DataRoot=%~dp0"
    Set "OutFile=FILELIST.TXT"
 
    >"%OutFile%" (For /F "delims=" %%A in ('2^>nul Dir "%DataRoot%\*.*" /B /S /A-D') Do (
        Set "Str=%%A"
        Call Echo Type: files; Name: "{app}\%%str:%~dp0=%%"
    ))
 
    >>"%OutFile%" (For /F "delims=" %%A in ('2^>nul Dir "%DataRoot%\*.*" /B /S /A:D ^|Sort/R') Do (
        Set "Str=%%A"
        Call Echo Type: dirifempty; Name: "{app}\%%str:%~dp0=%%"
    ))
Exit /B
 
Сверху