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

iglezz
26-04-2023, 03:13
Для поиска файлов можно применить Locate (https://nsis.sourceforge.io/Docs/AppendixE.html#locate) из FileFunc.nsh
Для сопоставления имён файлов - WinAPI-функции PathMatchSpec (https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathmatchspecw)/PathMatchSpecEx (https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathmatchspecexw)
PathMatchSpecEx может сопоставлять строку с множеством шаблонов, разделяемых точкой с запятой (из-за чего ";" в шаблонах использовать нельзя).

!appendfile 'test ccc' ''
!appendfile 'test1234' ''
!system 'md "test"'
!system 'md " test2"'
!system 'md "test aaa"'
!system 'md "test bbb"'
!system 'md "test xxx"'
!system 'md "test yyy"'
!system 'md "test_xyz"'

ShowInstDetails show
RequestExecutionLevel user
SetFont 'Fira Code Retina' 9
InstallColors /windows

!include LogicLib.nsh
!include FileFunc.nsh

Section UseLocate
${Locate} $EXEDIR '/M=test *' DeleteFilesByMask
SectionEnd

Function DeleteFilesByMask
SetDetailsPrint both

System::Call 'shlwapi.dll::PathMatchSpecEx(tR7, ts, i1)p.R0' 'test xxx;test yyy'
${If} $R0 == 1
${If} $R6 == ''
DetailPrint 'RMDir $R7'
; RMDir /r '$R9'
${Else}
DetailPrint 'Delete $R7'
; Delete '$R9'
${EndIf}
${Else}
DetailPrint 'Skip $R7'
${EndIf}

Push ''

SetDetailsPrint textonly
FunctionEnd

AlekseyPopovv
26-04-2023, 05:20
Всем привет. Столкнулся недавно с файлами *.json.
Нашёл плагин NsJSON.
Как создать файл с данными я понял:

nsJSON::Set /file "$APPDATA\Prog\config.json"
nsJSON::Set /Value `{}`
nsJSON::Set `license_file` /value `"$APPDATA\\Prog\\license.lic",`
nsJSON::Serialize /format /file "$APPDATA\Prog\config.json"

а как потом из этого файла удалить строки не понял. Может кто знает?

iglezz
26-04-2023, 13:34
а как потом из этого файла удалить строки не понял. »
nsJSON::Delete [NodePath] /end
У меня этот плагин работает некорректно на удаление и имеет проблемы с чтением некоторых файлов (например, при наличи пустого массива с них).
Автор плагина давно пропал, так что надеятся на исправление ошибок особо не стоит.

Лучше использовать более проверенный временем инструмент вроде jq (https://stedolan.github.io/jq/)

inco1
06-05-2023, 07:40
Всем хорошего дня и здоровья.
Помогите разобраться. Не могу разобраться с условиями, когда все последующие условия привязаны к первому условию, а в этих последующих условиях есть свои условия.... Правильно ли расставил ${EndIf} с такими условиями. По предварительным тестам работает, но не уверен в правильности кода. Последовательность действий изменять нельзя:

Section Run64
; если запущено на х64

${If} ${RunningX64}
; (здесь некое действие) ;; == произойдет некое действие

${If} ${FileExists} "$R1\A.exe"
; (здесь некое действие) ;; == если найден файл A.exe, то произойдет некое действие
${EndIf}

${IfNot} ${FileExists} "$R2\A.txt"
${AndIfNot} ${FileExists} "$R2\B.txt" ;; == если не найден файл A.txt и B.txt , то произойдет некое действие
; (здесь некое действие)
${EndIf}

${IfNot} ${FileExists} "$R3\B.exe" ;; == если не найден файл B.exe, то произойдет некое действие
; (здесь некое действие)
${EndIf}

${If} $R4 != 1234567890 ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
; (здесь некое действие)
${If} ${FileExists} "$R5\C.exe" ;; == если значение переменной $R4 не равно 1234567890, и найдены файлы C.exe и D.exe, то произойдет некое действие
${AndIf} ${FileExists} "$R5\D.exe"
; (здесь некое действие)
${EndIf}
; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf}
; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf}

SectionEnd

iglezz
06-05-2023, 13:25
Правильно ли расставил ${EndIf} с такими условиями. »
Для начала надо отформатировать код так, чтобы отступы отражали степень вложенности фрагментов этого кода.
Так будет легче увидеть логические ошибки, которые не ловятся компилятором.
Section Run64
; если запущено на х64

${If} ${RunningX64}
; (здесь некое действие) ;; == произойдет некое действие

${If} ${FileExists} "$R1\A.exe"
; (здесь некое действие) ;; == если найден файл A.exe, то произойдет некое действие
${EndIf}

${IfNot} ${FileExists} "$R2\A.txt"
${AndIfNot} ${FileExists} "$R2\B.txt" ;; == если не найден файл A.txt и B.txt , то произойдет некое действие
; (здесь некое действие)
${EndIf}

${IfNot} ${FileExists} "$R3\B.exe" ;; == если не найден файл B.exe, то произойдет некое действие
; (здесь некое действие)
${EndIf}

${If} $R4 != 1234567890 ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
; (здесь некое действие)

${If} ${FileExists} "$R5\C.exe" ;; == если значение переменной $R4 не равно 1234567890, и найдены файлы C.exe и D.exe, то произойдет некое действие
${AndIf} ${FileExists} "$R5\D.exe"
; (здесь некое действие)
${EndIf}

; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf}

; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf}

SectionEnd

Далее нужно избавляться от избыточной вложенности и/или сложности, порой с изменением структуры проекта.

inco1
07-05-2023, 07:37
iglezz,
Для начала надо отформатировать код так, чтобы отступы отражали степень вложенности фрагментов этого кода
Да, так виднее. И сразу выплыла ошибка в конце кода:

Section Run64
; если запущено на х64

${If} ${RunningX64}
; (здесь некое действие) ;; == произойдет некое действие

${If} ${FileExists} "$R1\A.exe"
; (здесь некое действие) ;; == если найден файл A.exe, то произойдет некое действие
${EndIf}

${IfNot} ${FileExists} "$R2\A.txt"
${AndIfNot} ${FileExists} "$R2\B.txt" ;; == если не найден файл A.txt и B.txt , то произойдет некое действие
; (здесь некое действие)
${EndIf}

${IfNot} ${FileExists} "$R3\B.exe" ;; == если не найден файл B.exe, то произойдет некое действие
; (здесь некое действие)
${EndIf}

${If} $R4 != 1234567890 ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
; (здесь некое действие)

${If} ${FileExists} "$R5\C.exe" ;; == если значение переменной $R4 не равно 1234567890, и найдены файлы C.exe и D.exe, то произойдет некое действие
${AndIf} ${FileExists} "$R5\D.exe"
; (здесь некое действие)
${EndIf}

; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf}

; (здесь некое действие) ;; == если значение переменной $R4 не равно 1234567890, то произойдет некое действие
${EndIf} ;; == если запущено на х64, то произойдет некое действие

SectionEnd

И еще вопрос, обязательно ли прописывать к примеру условие: "если файл найден" если следует команда на удаление этого самого файла или что то похожее в этом роде? Это будет "легче" для кода или нейтрально?

iglezz
08-05-2023, 00:28
И еще вопрос, обязательно ли прописывать к примеру условие: "если файл найден" если следует команда на удаление этого самого файла или что то похожее в этом роде? Это будет "легче" для кода или нейтрально? »
Проверять наличие файла перед удалением не обязательно, но имеет смысл результат, если файл существует, но не может быть удалёнClearErrors
Delete FILESPEC
${If} ${Errors}
MessageBox MB_OK "Хьюстон, у нас проблема"
Quit
${EndIf}

inco1
08-05-2023, 06:52
И еще вопрос, может кто знает, по каким параметрам некоторые разработчики прописывают проверку, что программа запущена на виртуалке?

iglezz
09-05-2023, 07:22
VM обнаруживается по записям с аппаратной конфигурации/драйверов, специфическим записям в реестре, файлам, процессам, сервисам.
В случае универсального детектора требуется проверить множество позиций как минимум для HyperV, VirtualBox, VMWare.

AlekseyPopovv
01-06-2023, 15:08
Как удалить записи из реестра после работы приложения по путям:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\S-1-5-21-1528902807-2110943787-476340328-1000

iglezz
01-06-2023, 18:41
AlekseyPopovv,
В первом случае сложностей не вижу
Во втором случае вижу пару особенностей в виде необходимости получения SID и преобразования буквы диска в имя устройства

Для получения SID текущено пользователя можно применить макрос GetCurrentUserSID !define GetCurrentUserSID `!insertmacro GetCurrentUserSID `
!macro GetCurrentUserSID out_SID
Push $0 ; fn ret / out_SID
Push $1 ; SID struct
Push $2 ; tmp

System::Call "advapi32::GetUserName(t.s, *i${NSIS_MAX_STRLEN}) i.r0"
StrCmp $0 0 +5
System::Call 'advapi32::LookupAccountName(i0, ts, @r1, *i${NSIS_MAX_STRLEN}, t .r2, *i ${NSIS_MAX_STRLEN}, *i .r2 ) i.r0'
StrCmp $0 0 +3
System::Call 'advapi32::ConvertSidToStringSid(pr1, *t.r0 )'
Goto +2
StrCpy $0 ''

Pop $2
Pop $1
Exch $0

Pop ${out_SID}
!macroend
Пример использования:
${GetCurrentUserSID} $0
DetailPrint 'SID = [$0]'

Если надо пройтись по всем пользователям, то можно использовать макрос EnumUsersReg EnumUsersRegEx (https://github.com/iglezz/NSIS-examples/blob/master/Include/EnumUsersRegEx.nsh) (пример (https://github.com/iglezz/NSIS-examples/blob/master/Examples/EnumUsersRegEx.nsi)).

Для преобразования пути в простейшем случае (c:\path -> \Device\HarddiskVolume3\path) можно использовать такой макрос:!define GetPathWithDeviceName `!insertmacro GetPathWithDeviceName `
!macro GetPathWithDeviceName out_DevPath in_DOSPath
Push '${in_DOSPath}'
Exch $0
Push $1
Push $2

StrLen $1 $0
StrCmp $1 1 0 +3
StrCpy $1 $0:
Goto +2

StrCpy $1 $0 2
System::Call 'kernel32::QueryDosDevice(tr1, t.r2, i${NSIS_MAX_STRLEN} ) i.r3'

StrCmp $3 0 0 +3
StrCpy $0 ''
Goto +3

StrCpy $0 $0 '' 2
StrCpy $0 $2$0

Pop $2
Pop $1
Exch $0

Pop ${out_DevPath}
!macroend
Пример использования:
${GetPathWithDeviceName} $0 "C:\path\to\file"
DetailPrint 'path = [$0]'

AlekseyPopovv
02-06-2023, 18:36
Как покрасить эти места в белый?
Function MyGUIInit
System::Call "user32::GetWindowLong(i$HWNDPARENT,i-20)i.s"
System::Int64Op "0x80000" |
System::Call "user32::SetWindowLong(i$HWNDPARENT,i-20,is)"
System::Call "user32::SetLayeredWindowAttributes(i$HWNDPARENT,i,i243,i0x00000002)"

GetDlgItem $R0 $HWNDPARENT 1034
GetDlgItem $R1 $HWNDPARENT 1037
GetDlgItem $R2 $HWNDPARENT 1038
SetCtlColors $R0 000000 FFFFFF
SetCtlColors $R1 000000 FFFFFF
SetCtlColors $R2 000000 FFFFFF
FunctionEnd

iglezz
02-06-2023, 20:59
Кроме замены цвета фона окна (в .onGUIInit) надо ещё поменять цвет фона каждой страницы и всех элементов в ней (в show-функции для каждой страницы)
!include WinMessages.nsh
RequestExecutionLevel user
InstallDir $TEMP

Page components "" cshow
Page directory "" dshow
Page instfiles "" ishow

; define background color
!define BACKGROUNDCOLOR 0xFFFFFF

Section `Dummy Section`
DetailPrint ...
SectionEnd

Function cshow
; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1017
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1021
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1022
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1023
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1032
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
FunctionEnd

Function dshow
; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1019
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
; ...
FunctionEnd

Function ishow
; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
FunctionEnd

Function .onGUIInit
; repaint window
SetCtlColors $HWNDPARENT '' ${BACKGROUNDCOLOR}

; set BrandingText ${BACKGROUNDCOLOR} background
GetDlgItem $0 $HWNDPARENT 1028
SetCtlColors $0 '' transparent
FunctionEnd

iglezz
02-06-2023, 21:31
Фон также можно задавать для каждой отдельной страницы
!include WinMessages.nsh
RequestExecutionLevel user
InstallDir $TEMP

Page components "" cshow
Page directory "" dshow
Page instfiles "" ishow

!define /ifndef RDW_INVALIDATE 0x0001
!define /ifndef RDW_ERASE 0x0004

; define background color
!define BACKGROUNDCOLOR 0xFFFFFF

Section `Dummy Section`
DetailPrint ...
SectionEnd


Function cshow
; repaint window
SetCtlColors $HWNDPARENT '' ${BACKGROUNDCOLOR}

; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1017
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1021
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1022
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1023
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1032
SetCtlColors $0 '' ${BACKGROUNDCOLOR}

System::Call "user32::RedrawWindow(i,i,i,i)i ($HWNDPARENT, 0, 0,${RDW_INVALIDATE}|${RDW_ERASE})"
FunctionEnd

Function dshow
; redefine page background
!define /redef BACKGROUNDCOLOR 0x88ff88

; repaint window
SetCtlColors $HWNDPARENT '' ${BACKGROUNDCOLOR}

; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1019
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1020
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1023
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1024
SetCtlColors $0 '' ${BACKGROUNDCOLOR}

System::Call "user32::RedrawWindow(i,i,i,i)i ($HWNDPARENT, 0, 0,${RDW_INVALIDATE}|${RDW_ERASE})"
FunctionEnd

Function ishow
; redefine page background
!define /redef BACKGROUNDCOLOR 0xabcdef

; repaint window
SetCtlColors $HWNDPARENT '' ${BACKGROUNDCOLOR}

; repaint page
FindWindow $1 "#32770" "" $HWNDPARENT
SetCtlColors $1 '' ${BACKGROUNDCOLOR}

; repaint page controls
GetDlgItem $0 $1 1031
SetCtlColors $0 '' ${BACKGROUNDCOLOR}
GetDlgItem $0 $1 1006
SetCtlColors $0 '' ${BACKGROUNDCOLOR}

System::Call "user32::RedrawWindow(i,i,i,i)i ($HWNDPARENT, 0, 0,${RDW_INVALIDATE}|${RDW_ERASE})"
FunctionEnd


Function .onGUIInit
; set BrandingText${BACKGROUNDCOLOR} background
GetDlgItem $0 $HWNDPARENT 1028
SetCtlColors $0 '' transparent
FunctionEnd

AlekseyPopovv
03-06-2023, 16:20
Как переименовать кнопку отмена на кастомной странице ReadmePage?

iglezz
03-06-2023, 19:33
Пример прямо в справке есть
GetDlgItem $1 $HWNDPARENT 2
SendMessage $1 ${WM_SETTEXT} 0 "STR:Goodbye"

id кнопок:
1 = next
2 = cancel
3 = back

AlekseyPopovv
04-06-2023, 11:41
Есть у кого ни будь пример кастомной страницы MUI_PAGE_INSTFILES?

AlekseyPopovv
04-06-2023, 16:43
Как убрать кнопку закрыть и сделать кнопку отмена активной?

iglezz
05-06-2023, 00:45
Как убрать кнопку закрыть и сделать кнопку отмена активной? »
Инструкция ShowWindow с примером в справке, аналогично переименовыванию.
Отмену активной сделать мало, там ещё много чего написать надо для обработки этой отмены - InstFiles Cancel - Allowing a user to cancel installation during InstFiles (https://nsis.sourceforge.io/InstFiles_Cancel_-_Allowing_a_user_to_cancel_installation_during_InstFiles)

AlekseyPopovv
06-06-2023, 16:38
iglezz, как поменять шрифт над прогресс баром?




© OSzone.net 2001-2012