PDA

Показать полную графическую версию : .: NSIS - все вопросы :. часть 2.


Страниц : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 [142] 143 144 145 146

MKN
31-10-2023, 11:47
Задача: "просмотреть" в папке все файлы и записать из них только нужное в другой файл. (соответственно с каждой строкой необходимо произвести манипуляции по нахождению-извлечению нужного)


Var FileCat
Var Name
Var Content
!macro FRead Name Content
ClearErrors
FileOpen $R5 "$EXEDIR\data.txt" w
FileOpen $R4 "$Name" r
${Do}
FileRead $R4 $Content
${IfThen} ${Errors} ${|} ${ExitDo} ${|}
MessageBox MB_OK "$Content"
FileWrite $R5 "$Name - $Content$\r$\n"
${Loop}
FileClose $R4
FileClose $R5
!macroend

Section
ClearErrors
FindFirst $0 $FileCat "$EXEDIR\TEST\*.*"
loop:
StrCmp $FileCat "" done
StrCmp $FileCat "." next
StrCmp $FileCat ".." next
StrCpy $Name "$EXEDIR\TEST\$FileCat"
!insertmacro FRead "$Name" "$Content"
next:
FindNext $0 $FileCat
Goto loop
done:
FindClose $0
SectionEnd
Для чтения-записи использую макрос с циклом FileRead. "Проверочный" MessageBox "фиксирует" данные в переменной из каждой строки каждого файла, но записываются данные только из одного файла, либо после обработки строк, вообще нечто рэндомное... В чём здесь ошибка ?

iglezz
31-10-2023, 17:03
MKN,
FileOpen $R5 "$EXEDIR\data.txt" w
Файл открывается на запись с уничтожением содержимого.

AlekseyPopovv
01-11-2023, 10:13
Как "пропустить" ошибку:
"Невозможно открыть файл для записи:"
Т.е. если файл занят, просто пропустить его копирование без MessageBox.

inco1
01-11-2023, 12:02
Всем хорошего дня.
Помогите, пожалуйста с удалением папок.
Нигде не нашел, как удалить папки с расширением, например папки с расширением .tmp

Этот вариант не работает:

SetOutPath "$TEMP\*.tmp"
SetOutPath "$TEMP"
RMDir /r "$TEMP\*.tmp"

AlekseyPopovv
01-11-2023, 12:11
inco1, Стандартная команда RMDir /r не удалит папки по расширению. Надо знать как папки называются.

inco1
01-11-2023, 12:25
AlekseyPopovv, Я правильно понял, что в NSIS есть только команда удаления по маске файлов, а удаление по маске папок даже не предусмотрено?

AlekseyPopovv
01-11-2023, 12:29
inco1, Да.

inco1
01-11-2023, 14:47
AlekseyPopovv, Странно как то всё это, если для этой цели даже батник есть в одну крохотную строчку:

for /d %%d in (*.tmp) do rd /s /q %%d

Не совать же батник в инсталятор для таких случаев. :o

iglezz
01-11-2023, 16:52
Как "пропустить" ошибку:
"Невозможно открыть файл для записи:"
Т.е. если файл занят, просто пропустить его копирование без MessageBox. »
SetOverwrite try

inco1, Странно как то всё это, если для этой цели даже батник есть в одну крохотную строчку
...»
Внезапно, команда rd тоже не умеет работать с масками.
Разница лишь в том, что в у интерпретатора командной строки есть готовые команды для циклов, а в nsis - нет.

MKN
03-11-2023, 18:32
Задача : необходимо в txt файле заменить конкретную строку на другую. Т.е. ,например, строку №5 удалить и заменить на содержимое из переменной и т.д.
Пробовал функцию - https://nsis.sourceforge.io/Replace_line_that_starts_with_specified_string
Не работает... (там правда не конкретная строка заменяется, а вроде как строка имеющая определённое вхождение, что тоже интересно, но тоже не заработало...)
Как решить такую задачу ?

iglezz
04-11-2023, 03:17
MKN, Та функция вполне рабочая, хотя и перемудрена немного. Но применяемый там метод записи ломает хард/софт-линки

Вот так можно построить обработку конструкциями в стиле LogicLib:
ShowInstDetails show
RequestExecutionLevel user
InstallColors /windows

!include FileFunc.nsh
!include LogicLib.nsh
!include Util.nsh

; String begins with
!macro _[== _a _b _t _f
!insertmacro _LOGICLIB_TEMP
StrLen $_LOGICLIB_TEMP `${_b}`
StrCpy $_LOGICLIB_TEMP `${_a}` $_LOGICLIB_TEMP
StrCmp `$_LOGICLIB_TEMP` `${_b}` `${_t}` `${_f}`
!macroend

; String ends with
!macro _]== _a _b _t _f
!insertmacro _LOGICLIB_TEMP
StrLen $_LOGICLIB_TEMP `${_b}`
StrCpy $_LOGICLIB_TEMP `${_a}` '' -$_LOGICLIB_TEMP
StrCmp `$_LOGICLIB_TEMP` `${_b}` `${_t}` `${_f}`
!macroend

; String includes
!macro _*== _a _b _t _f
!insertmacro _LOGICLIB_TEMP
System::Call 'shlwapi.dll::StrStrI(ts, ts)p.s' `${_a}` `${_b}`
Pop $_LOGICLIB_TEMP
StrCmp $_LOGICLIB_TEMP 0 `${_f}` `${_t}`
!macroend

!define PathSplitPN `!insertmacro PathSplitPN `
!macro PathSplitPN outParent outName Path
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Push `${Path}`
${CallArtificialFunction} PathSplitPN_
Pop ${outName}
Pop ${outParent}
!verbose pop
!macroend
!macro PathSplitPN_
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Exch $0
Push $1
Push $2

StrCpy $1 $0 1 -1
StrCmp $1 '\' 0 +3
StrCpy $0 $0 -1
Goto -3

StrLen $2 $0
IntOp $2 $2 - 1
StrCpy $1 $0 1 $2
StrCmp $1 '\' +2
StrCmp $1 '' 0 -3

StrCpy $1 $0 $2 ; path
IntOp $2 $2 + 1
StrCpy $0 $0 '' $2 ; name

Pop $2
Exch $1
Exch
Exch $0
!verbose pop
!macroend

!define FileGetTempCopy `!insertmacro FileGetTempCopy `
!macro FileGetTempCopy outDuplicateName FullFileName
!verbose push
!verbose ${_FILEFUNC_VERBOSE}
Push `${FullFileName}`
Exch $0 ; [in] FullFileName / [out] outDuplicateName
Push $1 ; file path
Push $2 ; name / handle
Push $3 ; outDuplicateName

${PathSplitPN} $1 $2 $0
System::Call 'kernel32::GetTempFileName(tr1, tr2, i0, t.r3)i.r2'
${If} $2 != 0
FileClose $2
SetDetailsPrint none
CopyFiles /silent $0 $3
SetDetailsPrint lastused
${IfNot} ${Errors}
StrCpy $0 $3
${Else}
StrCpy $0 ''
SetDetailsPrint none
Delete $3
SetDetailsPrint lastused
${EndIf}
${Else}
StrCpy $0 ''
${EndIf}

Pop $3
Pop $2
Pop $1
Exch $0
Pop ${outDuplicateName}
!verbose pop
!macroend

!define FileReadByLine `!insertmacro _FileReadByLine '' `
!define FileReadByLineUTF16LE `!insertmacro _FileReadByLine UTF16LE `
!macro _FileReadByLine ENCODING LineNumberVar LineVar ReadFile WriteFile
!verbose push
!verbose ${LOGICLIB_VERBOSITY}
!insertmacro _PushScope FileProcessByLine _FileProcessByLine.${__COUNTER__}
!insertmacro _PushScope FileProcessByLineLineVar ${LineVar}
!insertmacro _PushScope FileProcessByLineENCODING '${ENCODING}'
!insertmacro _PushScope FileProcessByLineReadFile '${ReadFile}'
!insertmacro _PushScope FileProcessByLineWriteFile '${WriteFile}'
!ifndef _FileProcessByLine_Initialize_Variables
!define _FileProcessByLine_Initialize_Variables
Var /GLOBAL _FileProcessByLine_Var_RD
Var /GLOBAL _FileProcessByLine_Var_RDHANDLE
Var /GLOBAL _FileProcessByLine_Var_WR
Var /GLOBAL _FileProcessByLine_Var_LINE
Var /GLOBAL _FileProcessByLine_Var_LINENUMBER
!else
!define ${_FileProcessByLine}__Save_Vars
Push $_FileProcessByLine_Var_RD
Push $_FileProcessByLine_Var_RDHANDLE
Push $_FileProcessByLine_Var_WR
Push $_FileProcessByLine_Var_LINE
Push $_FileProcessByLine_Var_LINENUMBER
!endif

GetFullPathName $_FileProcessByLine_Var_RD `${ReadFile}`
${IfNotThen} ${FileExists} $_FileProcessByLine_Var_RD ${|} Goto ${_FileProcessByLine}__errors ${|}
${If} `${_FileProcessByLineWriteFile}` == ``
${OrIf} `${_FileProcessByLineWriteFile}` == `${_FileProcessByLineReadFile}`
StrCpy $_FileProcessByLine_Var_WR $_FileProcessByLine_Var_RD
${FileGetTempCopy} $_FileProcessByLine_Var_RD $_FileProcessByLine_Var_WR
${IfThen} $_FileProcessByLine_Var_RD == '' ${|} Goto ${_FileProcessByLine}__errors ${|}
${Else}
StrCpy $_FileProcessByLine_Var_RD `${ReadFile}`
StrCpy $_FileProcessByLine_Var_WR `${WriteFile}`
${EndIf}

ClearErrors
FileOpen $_FileProcessByLine_Var_RDHANDLE $_FileProcessByLine_Var_RD r
${If} ${Errors}
Goto ${_FileProcessByLine}__errors
${EndIf}

FileOpen $_FileProcessByLine_Var_WR $_FileProcessByLine_Var_WR w
${If} ${Errors}
FileClose $_FileProcessByLine_Var_RDHANDLE
Goto ${_FileProcessByLine}__errors
${EndIf}
StrCpy $_FileProcessByLine_Var_LINENUMBER 0

${Do}
FileRead${ENCODING} $_FileProcessByLine_Var_RDHANDLE $_FileProcessByLine_Var_LINE
${IfThen} ${Errors} ${|} ${ExitDo} ${|}
!define ${_FileProcessByLine}__LineNumberVar=${LineNumberVar}
!ifdef ${_FileProcessByLine}__LineNumberVar= | ${_FileProcessByLine}__LineNumberVar=-
!else
IntOp $_FileProcessByLine_Var_LINENUMBER $_FileProcessByLine_Var_LINENUMBER + 1
StrCpy ${LineNumberVar} $_FileProcessByLine_Var_LINENUMBER
!endif
!undef ${_FileProcessByLine}__LineNumberVar=${LineNumberVar}
StrCpy ${LineVar} $_FileProcessByLine_Var_LINE

; ...............

!verbose pop
!macroend

!define FileWriteByLine `!insertmacro _FileWriteByLine "" `
!define FileWriteByLineUTF16LE `!insertmacro _FileWriteByLine UTF16LE `
!macro _FileWriteByLine ENCODING
!verbose push
!verbose ${LOGICLIB_VERBOSITY}
!ifndef _FileProcessByLine
!error "Cannot use FileProcessByLineEnd${ENCODING} without a preceding FileProcessByLine${ENCODING}"
!endif

; ...............

FileWrite${ENCODING} $_FileProcessByLine_Var_WR ${_FileProcessByLineLineVar}
${Loop}

FileClose $_FileProcessByLine_Var_RDHANDLE
FileClose $_FileProcessByLine_Var_WR

${_FileProcessByLine}__errors:
SetErrors

${If} `${_FileProcessByLineWriteFile}` == ``
${OrIf} `${_FileProcessByLineWriteFile}` == `${_FileProcessByLineReadFile}`
SetDetailsPrint none
Delete $_FileProcessByLine_Var_RD
SetDetailsPrint lastused
${EndIf}

!ifdef ${_FileProcessByLine}__Save_Vars
!undef ${_FileProcessByLine}__Save_Vars
Pop $_FileProcessByLine_Var_LINENUMBER
Pop $_FileProcessByLine_Var_LINE
Pop $_FileProcessByLine_Var_WR
Pop $_FileProcessByLine_Var_RDHANDLE
Pop $_FileProcessByLine_Var_RD
!endif
!insertmacro _PopScope FileProcessByLine
!insertmacro _PopScope FileProcessByLineLineVar
!insertmacro _PopScope FileProcessByLineENCODING
!insertmacro _PopScope FileProcessByLineReadFile
!insertmacro _PopScope FileProcessByLineWriteFile
!macroend


Section TEST
SetDetailsPrint none
CopyFiles /silent '${__FILE__}' '${__FILE__}-1.txt'
CopyFiles /silent '${__FILE__}' '${__FILE__}-2INPLACE.txt'
CopyFiles /silent '${__FILE__}' '${__FILE__}-3.txt'
SetDetailsPrint lastused

/* вместо иснструкции:

${FileReadByLine} LineNumber Line FileToRead FileToWrite
LineNumber - переменная с номером строки или '' или '-' (не использовать)
Line - переменная со строкой (включает символы конца строки)
FileToRead - файл для чтения
FileToWrite - файл для записи
Если FileToWrite=='' или FileToWrite==FileToRead, будет изменён фходной файл

Внутри цикла
${FileReadByLine}
....
${Continue} завершит работу с текущей строкой, пропустит запись и перейдёт к чтению следующей строки
${Break} прекратит обработку
....
${FileWriteByLine}

${FileReadByLine} / ${FileReadByLineUTF16LE} - читать как ANSI / UTF16-LE
${FileWriteByLine} / ${FileWriteByLineUTF16LE} - писать как ANSI / UTF16-LE

*/

; пронумерует строки:
${FileReadByLine} $0 $1 '${__FILE__}-1.txt' '${__FILE__}-1NUMBERS.txt'
IntFmt $0 '%4d' $0
StrCpy $1 '[$0] $1'
${FileWriteByLineUTF16LE} ; сохранить в кодировке UTF16LE

; оставит и пронумерует только нечётные строки:
${FileReadByLine} $0 $1 '${__FILE__}-1.txt' '${__FILE__}-1ODDS.txt'
IntOp $2 $0 % 2
${IfThen} $2 == 0 ${|} ${Continue} ${|}
IntFmt $0 '%4d' $0
StrCpy $1 '[$0] $1'
${FileWriteByLine}

; удалит пустые строки, измениы ыходной файл:
${FileReadByLine} - $1 '${__FILE__}-2INPLACE.txt' ''
${IfThen} $1 == '$\r$\n' ${|} ${Continue} ${|}
; обработка прекратится на следующей строке:
${IfThen} $1 *== '; break on this line' ${|} ${Break} ${|}
${FileWriteByLine}

; вложенный цикл
${FileReadByLine} - $1 '${__FILE__}-1.txt' ''
${If} $1 [== 'Section '
${FileReadByLine} $0 $1 '${__FILE__}-3.txt' '${__FILE__}-3BLOCKS.txt'
${If} $1 [== '!macro '
${OrIf} $1 [== 'Function '
${OrIf} $1 [== 'Section '
IntFmt $0 '%4d' $0
StrCpy $1 '[$0] $1'
${Else}
${Continue}
${EndIf}
${FileWriteByLine}
${Break} ; завершить обработку
${EndIf}
${FileWriteByLine}
SectionEnd

MKN
04-11-2023, 09:31
iglezz, спасибо !, но очень мудрёно... Наивный практический вопрос - как выглядит то запрос на замену ? Скажем, входной файл In.txt , строка для замены №7, заменить на содержимое из $data.
ps Можно ли оформить функцию как .nsh ? (чтобы не очень пугала... :) )

iglezz
04-11-2023, 10:54
Скажем, входной файл In.txt , строка для замены №7, заменить на содержимое из $data. »
Просто заменить седьмую строку на $data:
${FileReadByLine} $0 $1 'In.txt' ''
${IfThen} $0 == 7 ${|} StrCpy $1 $data ${|}
${FileWriteByLine}

Можно ли оформить функцию как .nsh ? »
Не можно, а нужно.
В примере оно из разных nsh подёргано.

MKN
04-11-2023, 12:07
iglezz,
Почему то после замены строки, следующая строка, имеющаяся в файле "прилепляется" к концу заменённой, т.е. после строки замены отсутствует перенос строки... Можно конечно после Line добавить $\r$\n, а может лучше в код функции добавить перенос, куда следует добавить ?
И можно ли в ${FileReadByLine} $0 $1 использовать свои переменные(вместо $0 $1) ?

iglezz
04-11-2023, 14:42
Почему то после замены строки, следующая строка, имеющаяся в файле "прилепляется" к концу заменённой, т.е. после строки замены отсутствует перенос строки... Можно конечно после Line добавить $\r$\n, а может лучше в код функции добавить перенос, куда следует добавить ? »
Как и в инструкциях NSIS FileRead/FileReadUTF16LE строка (в пределах NSIS_MAX_STRLEN) считывается с символами завершения строки. Добавлять их обработку в макрос большого смысла нет, т.к. это замедлит и без того небыстрый код, а нужно не всегда.
Можно просто добавлять $\r$\n к переменной Line, если нет желания использовать EOL-символы для конкретной обрабатываемой строки.
И можно ли в ${FileReadByLine} $0 $1 использовать свои переменные(вместо $0 $1) ? »
Можно любые.

Тут, кстати, надо учитывать, что на строках длиннее NSIS_MAX_STRLEN работа может быть некоректной.
Для таких случаев нужна отдельная версия этой конструкции, в которой побочно и EOL-символы получатся в отдельной переменной.

AlekseyPopovv
01-12-2023, 07:51
В файле длинная строка, в ней нужно найти такие данные:
"download":{"default_directory":"C:\Пользователи\Downloads"}
Путь разный у всех.
Надо заменить на:
"download":{"default_directory":"$EXEDIR\${DEFDIR}\Downloads"}
Как это сделать по проще, если можно?

MKN
17-12-2023, 16:25
Подскажите пожалуйста - как приспособить RegistryFunc.nsh (из Справочника) для работы с UNICODE версиями NSIS ?
К сожалению сказано, что "библиотека полностью совместима только ANSI версией компилятора NSIS"...

iglezz
17-12-2023, 17:16
MKN,
Посмотрев код по диагонали, могу сказать, что потребуется вдумчиво прогнать всё через дебаггер в голове на предмет выявления мест, где идёт работа на уровне байт, а не символов.
Параллельно можно и оптимизировать немного на производительность.

MKN
17-12-2023, 18:41
потребуется вдумчиво прогнать всё через дебаггер в голове на предмет выявления мест, где идёт работа на уровне байт, а не символов. Параллельно можно и оптимизировать немного на производительность. »
Вся надежда на тебя... :)

iglezz
18-12-2023, 01:44
MKN, Большого смысла адаптировать RegistryFunc.nsh не вижу, проще новый написать с нуля.




© OSzone.net 2001-2012