Цитата Dodakaedr:
наверное из-за переменной $R0, она берется уже с call DeleteLineFunc? Применил свою переменную, все заработало. »
|
Ну вот видите, достаточно всего-лишь внимательно смотреть на код и на используемые переменные. Значение переменной может быть изменено в любой части кода, что может повлиять на функционал других функций, использующих одну переменную.
Ещё советую при использовании команд внимательно читать описание к команде, некоторые команды в NSIS переназначают значения переменных своими данными, из-за чего ваш код так же может оказаться некорректным, если вы используете те же переменные, что и команда NSIS, простой пример - команда
Locate для поиска файлов, её callback функция использует переменные для хранения своих данных во время процесса поиска:
Код:
Function "Function"
; $R9 "путь\имя"
; $R8 "путь"
; $R7 "имя"
; $R6 "размер" ($R6="" если директория, $R6="0" если поиск с ключем /S=)
; $R0-$R5 не используется функцией.
; ...
Push $var ; Если $var="StopLocate" Завершение функции
FunctionEnd
Цитата Dodakaedr:
у меня опыта с nsis ноль целых х*р десятых. Да и в программировании где-то также. »
|
Скрытый текст
Для изучения конкретно NSIS вам нужно только одно - желание. Я тут уже 100 раз рассказывал, как лично я познакомился с NSIS будучи ещё совсем "зелёным" (во всех смыслах), я не то чтобы даже английский язык не знал, я в то время даже не знал, что такое интернет и редактор реестра. У меня кроме дистрибутива с непонятной программой (NSIS), которая просто была на CD в куче софта, больше ничего не было, ни знаний компьютерных, ни интернета, ни уж тем более справочника на русском
Я даже сейчас не знаю ни одного языка программирования и английского языка тоже не знаю, но просто есть желание и упорство - всё получается, это я к тому, что всё зависит только от вас, к тому же, у вас есть то, чего не было лично у меня - помощь со стороны более опытных кодеров и русская справка, пусть и не с огромным количеством всяких примеров и переведённых команд - но всё же для получения базовых знаний о NSIS справочник вполне сойдёт.
Цитата Dodakaedr:
читаю я ваш справочник, если бы все понимал то и не спрашивал помощи, а так команды строковые для меня вообще темный лес »
|
Если после прочтения описания команды в справочнике и проведения тестов вы всё-равно не понимаете, как пользоваться командой - приходите и спрашивайте, что конкретно не понятно, в чем проблема то.
-------
Цитата Dodakaedr:
Не могу понять принцип работы строковых команд а именно как и что сравнивать надо »
|
Так вы логику действий у себя в голове выстроите и продумывайте команды, разберём простой пример:
вам нужно удалить пустую строку
Вот дальше вам необходимо понять всю силу фразы "Читайте справочник", если вы будете знать о всех командах, которые вам доступны в NSIS - вы будете писать код в несколько раз быстрее, зная команды - у вас в голове сразу будет строится код.
Что для этого нужно? Так, ну, раз у меня простой текстовый файл, значит для начала мне нужно прочитать строку, а как я могу прочитать строку? Точно, есть же команда
LineRead!
Код:
${LineRead} "[Файл]" "[Номер строки]" $var
Так, ну, допустим, я прочитаю первую строку, а если моя строка записана второй, как мне сделать универсальный код, не дублируя строки? Точно, есть же математическая команда
IntOp, я сделаю счетчик и он будет плюсоваться после чтения строки, если это не моя строка - будем увеличивать счетчик и идти дальше по файлу!
В голове строится код
Код:
StrCpy $1 0 ; нам сначала нужно обнулить счетчик, т.к. переменная возможно уже ранее использовалась
IntOp $1 $1 + 1 ; в переменную будет помещено текущее значение переменной $1 с прибавлением на 1
${LineRead} "[Файл]" "$1" $0
Так, круто, что дальше то, я прочитал первую строку, а как понять, что она пустая то? Точно, есть же команда
StrCmp!
Т.к. содержимое прочитанной строки помещается в переменную
$0 (смотри описание команды LineRead), то, соответственно, нам нужно сделать условие сравнения этой переменной с пустым значением в команде
StrCmp, с пустым потому, что нам нужно определить, что прочитанная строка действительно пустая, а не с данными
Код:
StrCpy $1 0 ; нам сначала нужно обнулить счетчик, т.к. переменная возможно уже ранее использовалась
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 ЕСЛИ_НЕТ ; метка 0 означает, что если условие истина, т.е. значение переменной $0 - пусто, то опускаемся дальше по коду
так, а что мне делать дальше то? Если строка пустая, то...она мне не нужна, значит прописываю команду удаления ниже по коду, а как? Точно, мне же K.A.V. пример кидал с комментарием на каждой строке!
Код:
${LineFind} "$DESKTOP\hosts" "" "$R1" "DeleteLineCallback" ; удалем строку, в которой найдена фраза, передавая номер удаляемой строки
так, в комменте сказано, что в команду нужно передавать номер строки, а у меня он где?! Точняк, это же счетчик в переменной
$1, значит меняю переменную из примера на свою
Код:
StrCpy $1 0
IntOp $1 $1 + 1
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 ЕСЛИ_НЕТ
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
так, что дальше то делать после удаления строки? а, ну, нам нужно прочитать следующую строку, т.е. нам нужно как-то вернуться на начало код...хм, о, есть же команда
goto, её нужно поместить так, чтобы после удаления строки наш счетчик увеличился
Код:
StrCpy $1 0
NextLineRead:
IntOp $1 $1 + 1
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 ЕСЛИ_НЕТ
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
goto NextLineRead
Вроде что-то получается, так, K.A.V. же вроде говорил, что при удалении строки - другие строки смещаются, значит если у меня будет 2 пустые строки подряд, то я сначала удалю первую, у меня увеличится счетчик и я пропущу вторую строку, которая сместилась выше относительно других строк...как же быть, о, значит после удаления строки нам нужно прочитать эту строку ещё раз! Давай добавим меточку и изменим условие после удаления строки
Так, стоп, а как же условие того, что наша строка не пустая, что делать то...а, ну всё правильно, нам нужно перейти к следующей строке, значит в условие
StrCmp делаем ссылку на метку
NextLineRead
Код:
StrCpy $1 0
NextLineRead:
IntOp $1 $1 + 1
NowRead:
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 NextLineRead
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
goto NowRead
Во, вроде всё правильно! хотя...блин, а как я пойму, что строки в файле то закончились? У меня же получился бесконечный цикл чтения файла
Точно, есть же команда
LineSum, которая подсчитывает общее количество строк в файле! Давай-ка её в начало пропишем и назначим переменную для хранения
$R0.
Код:
${LineSum} "[Файл]" $R0
StrCpy $1 0
NextLineRead:
IntOp $1 $1 + 1
NowRead:
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 NextLineRead
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
goto NowRead
Тааак, теперь я знаю количество строк в файле! Теперь нужно вставить условие после счетчика и сравнивать, достигнута ли последняя строка, но подожди, комадна
StrCmp же не подойдёт, потому что если я увеличу счетчик и сразу же сравню это значение с общим количеством строк - я могу не прочитать последнюю строку, значит нужна другая команда...точно,
IntCmp!
Я укажу так, что если текущий счетчик строки больше общего количества строк, то закончим обработку, а если меньше либо равно - то продолжу чтение
Код:
${LineSum} "[Файл]" $R0
StrCpy $1 0
NextLineRead:
IntOp $1 $1 + 1
IntCmp $1 $R0 0 0 end
NowRead:
${LineRead} "[Файл]" "$1" $0
StrCmp $0 "" 0 NextLineRead
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
goto NowRead
end:
Так, ну, вроде бы всё...а нет, K.A.V. же ещё делал замечание по поводу того, что если мы удаляем строку - то общее количество строк становится меньше, и чтобы не делать лишних попыток чтения после удаления нескольких строк, нам нужно после каждой команды удаления строки заново получать общее количество строк в файле, продублирую команду
Код:
${LineSum} "[Файл]" $R0
StrCpy $1 0
NextLineRead:
IntOp $1 $1 + 1
IntCmp $1 $R0 0 0 end
NowRead:
${LineRead} "[Файл]" "$1" $0
${TrimNewLines} '$0' $0
StrCmp $0 "" 0 NextLineRead
${LineFind} "$DESKTOP\hosts" "" "$1" "DeleteLineCallback"
${LineSum} "[Файл]" $R0
goto NowRead
end:
Кстати, при использовании LineRead в переменной будет значение с символом перехода на новую строку, поэтому команда сравнения может не сработать, для удаления символа перехода на новую строку мы используем команду ${TrimNewLines} после чтения строки
Вроде бы всё, осталось добавить callback функцию DeleteLineCallback для удаления строки
Код:
Function DeleteLineCallback
StrCpy $0 SkipWrite
Push $0
FunctionEnd
Круто, работает! Вроде и ничего сложного, если знаешь, какие команды есть в NSIS...
На самом деле, если посмотреть на этот код - здесь реально ничего мегакрутого нет - обычный код с использованием стандартных команд, вся фишка в том, что я знаю много команд в NSIS и знаю, что конкретно могу получить от той или иной команды. На основе этих знаний у меня код в голове строится автоматически, остаётся только его напечатать и проверить работоспособность
В примере этого сообщения я вам продемонстрировал, как на самом деле всё просто, достаточно всего-лишь знания команд NSIS и немного времени, чтобы продумать логику действий в коде.
Цитата Dodakaedr:
главное чтобы у вас терпения хватило »
|
Главное, чтобы вы реально прочитали справочник перед написанием постов в этой теме, в этой теме было пару человек, сообщения которых я просто игнорировал, зная ответы, по причине того, что им лень было открыть справочник и прочитать инфу, когда их об этом просили неоднократно, им нужны были только готовые примеры.