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
24-06-2014, 15:42
COMPONENTSPAGE и PAGE_DIRECTORY на одной стандартной странице.

Такое сочетание более практично и удобно, чем раздельное листание страниц (хотя лучше это делать с помощью nsDialogs )


!AddPluginDir .
!include "MUI2.nsh"
!define SHACF_FILESYSTEM 0x00000001
!define EN_CHANGE 0x0300

Name "COMPONENTS_PAGE_DIRECTORY"
OutFile "COMPONENTS_PAGE_DIRECTORY.exe"
InstallDir $TEMP
ShowInstDetails show

!define MUI_COMPONENTSPAGE_NODESC
; correct modern_nodesc.exe
!define MUI_UI_COMPONENTSPAGE_NODESC myui.exe

!define MUI_PAGE_CUSTOMFUNCTION_SHOW DirPageShow
!insertmacro MUI_PAGE_DIRECTORY
!define MUI_PAGE_CUSTOMFUNCTION_SHOW HideBack
!insertmacro MUI_PAGE_LICENSE ${__FILE__}
!define MUI_COMPONENTSPAGE_TEXT_INSTTYPE $(^DirBrowseText)
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComPageShow
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"

Function DirPageShow
FindWindow $1 "#32770" "" $HWNDPARENT
System::Call User32::GetWindowLong(ir1,i4)i.R0
SendMessage $HWNDPARENT 0x408 1 0
FunctionEnd

Function HideBack
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 ${SW_HIDE}
FunctionEnd

Function ComPageShow
FindWindow $1 "#32770" "" $HWNDPARENT
GetFunctionAddress $0 onComPageCallback
WndProc::onCallback /r=1 $1 $0
GetDlgItem $0 $1 1001
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^BrowseBtn)"
GetDlgItem $0 $1 1007
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^DirText)"
GetDlgItem $0 $1 1020
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(^DirSubText)"
GetDlgItem $0 $1 1019
SendMessage $0 ${WM_SETTEXT} 0 "STR:$INSTDIR"
System::Call `shlwapi::SHAutoComplete(ir0,i${SHACF_FILESYSTEM})`
FunctionEnd

Function onComPageCallback
${If} $2 = ${WM_COMMAND}
IntOp $5 $3 & 0x0000FFFF
IntOp $6 $3 >> 16
IntOp $6 $6 & 0x0000FFFF
${If} $6 = ${EN_CHANGE}
${AndIf} $5 = 1019
System::Call User32::GetDlgItemText(ir1,i1019,t.d,i${NSIS_MAX_STRLEN})
${EndIf}
System::Call User32::CallWindowProc(iR0,ir1,ir2,ir3,ir4)
${EndIf}
FunctionEnd

Section "Components" Main
SectionIn RO
SectionEnd

Section /o "Component1" Sec01
DetailPrint "Component 1"
SectionEnd

Section "Component 2" Sec02
DetailPrint "Component 2"
SectionEnd


myui.exe - подкорректированный modern_nodesc.exe
WndProc.dll - плагин

комплект во вложении :

MKN
25-06-2014, 13:38
Периодически необходимо перемещать или копировать файлы в папку, в которой уже имеются сотни файлов , в том числе и одноимённых (т.е. таких же, которые я копирую), которые потом нужно или удалить , или сравнить, или ещё чего...
Оказалось, сделать это удобно с помощью функции SHFileOperation, в которой предусмотрено создание копий одноимённых файлов.

Функция SHFileOperation копирует, перемещает, переименовывает или удаляет объект в файловой системе.
Функция имеет единственный аргумент - структуру типа TSHFileOpStruct, в которой и передаются все необходимые данные.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795(v=vs.85).aspx

В зависимости от установленных флагов, производятся нужные операции с файлами. К примеру :

переместить файлы из папки A в папку B и, если в папке B были одноимённые, файлы создать их копии в папке B


System::Call "*(i $HWNDPARENT, i 0x0001, t 'C:\A\*.*',t 'C:\B', i 0x0008|0x0400, i0,i0,i0,&t${NSIS_MAX_STRLEN} r0,&t1 0)i .r0"
System::Call "shell32::SHFileOperation(i r0)i .r1"
System::Free $0

FO_MOVE = 0x0001 Перемеcтить файлы
Для копирования установить флаг FO_COPY = 0x0002 Копировать файлы
FOF_RENAMEONCOLLISION = 0x0008 В случае, если файл с данным именем уже существует, создается файл с именем "Copy #N of..."

Наиболее известно применение этой функции для удаления пустых каталогов. Но бывает полезен и такой момент - удаление файлов в корзину.
Например, при деинсталляции приложения, бывает необходимо сохранить пользовательские данные-файлы (проекты, шаблоны, INI, xml-файлы настроек и т.д.)
И , даже если в Uninstaller_е предусмотрено соответсвующее сообщение, можно случайно пропустить его и удалить нужные файлы.. Тогда беда (для рядового пользователя,точно...)
Поэтому, есть смысл, удалять ответственные файлы в корзину, с помощью SHFileOperation.


System::Call "*(i $HWNDPARENT, i 0x0003, t 'C:\A\*.*',t , i 0x0040|0x0010|0x0400, i0,i0,i0,&t${NSIS_MAX_STRLEN} r0,&t1 0)i .r0"
System::Call "shell32::SHFileOperation(i r0)i .r1"
System::Free $0


Здесь флаги :
FO_DELETE = 0x0003 - Удалить файлы
FOF_ALLOWUNDO = 0x0040 Удалить файлы в корзину.
FOF_NOERRORUI = 0x0400 - Не показывать сообщения об ошибках, которые могут возникнуть в течение процесса.
FOF_NOCONFIRMATION = 0x0010 Отвечает "yes to all" на все запросы в ходе операции, т.е. не спрашивать у пользователя подтверждения удаления.
если сообщение всё же желательно - этот флаг ессно не применяем

( Если надо удалить файлы вместе с папкой - не используем *.* )

MKN
26-06-2014, 13:21
Интересен код использования функции BitBlt. Можно рисовать рядом с окном инсталлятора (или в любом другом месте экрана) изображения, например, для наглядной демонстрации, при выборе компонентов или выборе скинов , тем, шаблонов и т.д.

outfile BitBlt_test.exe

!define LR_LOADFROMFILE 0x0010
!define IMAGE_BITMAP 0
!define LR_CREATEDIBSECTION 0x00002000
Var hBitmap
Var hDC
Var hDCMem
Var oldObject
; Функция BitBlt выполняет передачу битовых блоков данных о цвете, соответствующих прямоугольнику пикселей из заданного исходного контекста устройства
; в целевой контекст устройства.
; Растровая операция SRCCOPY 00CC0020 копирует исходный прямоугольник непосредственно в целевой прямоугольник
Section
StrCpy $0 $EXEDIR\vinni.bmp
System::Call 'user32::LoadImage(i 0, t r0, i ${IMAGE_BITMAP}, i 0, i 0, i ${LR_CREATEDIBSECTION}|${LR_LOADFROMFILE}) i.s'
Pop $hBitmap
System::Call "user32::GetDC(i R1) i.s"
Pop $hDC
System::Call "gdi32::CreateCompatibleDC(i $hDC) i.s"
Pop $hDCMem
System::Call "gdi32::SelectObject(i $hDCMem, i $hBitmap) i.s"
Pop $oldObject
System::Call "gdi32::BitBlt(i $hDC, i 50, i 50, i 185, i 255, i $hDCMem, i 0, i 0, i 0x00CC0020) i.s"

System::Call "gdi32::BitBlt(i $hDC, i 50, i 450, i 185, i 255, i $hDCMem, i 0, i 0, i 0x00CC0020) i.s"
SectionEnd

Function .onGUIEnd
System::Call `gdi32::DeleteObject(i s)` $hBitmap
FunctionEnd

i 50, i 450, i 185, i 255 - координаты и размер BMP рисунка
Есть правда досадный момент - изображение почему то не разрушается при закрытии инсталлятора (хотя DeleteObject предусмотрен в .onGUIEnd )
И изображение можно разрушить любым помещённым на него объектом...
Может кто подскажет, как это устранить ?
Пример во вложении :

K.A.V.
26-06-2014, 13:40
Есть правда досадный момент - изображение почему то не разрушается при закрытии инсталлятора (хотя DeleteObject предусмотрен в .onGUIEnd )
И изображение можно разрушить любым помещённым на него объектом...
Может кто подскажет, как это устранить ? »
У меня как-то странно отрабатывает, даже если сразу запустить инсталлер и навести мышку на изображение - оно исчезает кусками, т.е. именно те куски, где находится курсор, а так через ~3 секунды полностью, так и должно быть?

Насчет разрушения не могу точно сказать, т.к. изображения сами разрушаются, но в описании DeleteObject (http://msdn.microsoft.com/en-us/library/windows/desktop/dd183539(v=vs.85).aspx) сказано, что нужно передавать функции
A handle to a logical pen, brush, font, bitmap, region, or palette.
т.е. хэндл изображения, как я понимаю...
System::Call `gdi32::DeleteObject(i $hBitmap)`

MKN
26-06-2014, 15:15
так и должно быть? »
Вряд ли... Идея интересная, но уж больно тёмная реализация...

MKN
27-06-2014, 11:50
Иногда желательно обратить внимание пользователя на какое-либо сообщение программы. Сделать это можно сопроводив сообщение звуковым сигналом встроенного PC speaker_а (Beeper_a)
и функций winmm или kernel32


OutFile "Beep_test.exe"
Section
System::Call 'winmm::PlaySound(i0x2A53,i,i0x110001)'
Sleep 1000
; В траве сидел кузнечик
System::Call 'kernel32::Beep(i 440,i 300) l'
System::Call 'kernel32::Beep(i 329,i 300) l'
System::Call 'kernel32::Beep(i 440,i 300) l'
System::Call 'kernel32::Beep(i 329,i 300) l'
System::Call 'kernel32::Beep(i 440,i 300) l'
System::Call 'kernel32::Beep(i 415,i 300) l'
System::Call 'kernel32::Beep(i 0,i 100) l'
System::Call 'kernel32::Beep(i 415,i 300) l'
SectionEnd

мелодию можно набрать любую из частот и длительностей нот

ps Ессно бипер должен физически присутствовать в ПК и быть включен в :

[HKEY_CURRENT_USER\Control Panel\Sound]
"Beep"="yes"

и в "Non Plug and Play Drivers"

MKN
01-07-2014, 12:38
Есть полезный код, перечисляющий все дисковые устройства и их тип :


outfile GetLogicalDrives_GetDriveType.exe
!include LogicLib.nsh
ShowInstDetails show

Section
System::Call 'kernel32::GetLogicalDrives()i.r0'
StrCpy $2 0
StrCpy $4 65 ; 'A'
loop:
IntOp $3 $0 & 1
${If} $3 <> 0
IntFmt $3 "%c:\" $4
System::Call 'kernel32::GetDriveType(tr3)i.r5'
DetailPrint "$3=$5"
${EndIf}
IntOp $4 $4 + 1
IntOp $0 $0 >> 1
StrCmp $0 0 "" loop
SectionEnd


Вопрос : каким образом занести в одну (или несколько) переменную - ВСЕ полученные в цикле, данные ? Ведь количество дисков не предсказуемо...

K.A.V.
01-07-2014, 13:03
Вопрос : каким образом занести в одну (или несколько) переменную - ВСЕ полученные в цикле, данные ? »
Ты снова меня удивляешь простыми вопросами :)


Function .onInit

call test
MessageBox MB_OK|MB_ICONINFORMATION "$R0"

quit
FunctionEnd




Function test
StrCpy $R0 ""
System::Call 'kernel32::GetLogicalDrives()i.r0'
StrCpy $2 0
StrCpy $4 65 ; 'A'
loop:
IntOp $3 $0 & 1
${If} $3 <> 0
IntFmt $3 "%c:\" $4
System::Call 'kernel32::GetDriveType(tr3)i.r5'
DetailPrint "$3=$5"
StrCpy $R0 "$R0 $3"
${EndIf}
IntOp $4 $4 + 1
IntOp $0 $0 >> 1
StrCmp $0 0 "" loop
FunctionEnd

MKN
01-07-2014, 15:15
удивляешь простыми вопросами »
Сам удивился... :) Делал почти то же самое, но досадно ошибся... Благодарствую.

Otlanta
11-07-2014, 15:23
Всем привет, как определить дату модификации файла с помощью NSIS?

MKN
11-07-2014, 15:44
как определить дату модификации файла с помощью NSIS? »
Можно с помощью http://nsis.sourceforge.net/Time_plug-in
или с помощью GetTime :
http://nsis.sourceforge.net/Docs/AppendixE.html#E.1.6

natasha_82
14-07-2014, 20:48
Доброго времени суток
Прошу не судить строго, NSIS занимаюсь не очень давно.
Не могу найти ответ (хотя перечитала многое), на такой вопрос:
Можно ли на NSIS сделать инсталляцию (тихую), которая во время установки будет считывать данные с другого файла (т.е. exe одна, а в файле можно, например, изменить путь (или/и другие параметры) и при тихой инсталляции новый путь (параметры) будет учитываться (без пересборки exe))?
Нашла варианты считывания с .ini - но не подходит, т.к. считывает в момент сборки, и нет реакции если внести изменения((

profcom
14-07-2014, 20:59
natasha_82, конечно можно и кстати с ini файлами как раз будет работать, просто не надо этот ini файл подключать в инсталятор, а считывать например из рядом лежащего файла:
ReadINIStr $0 "$EXEDIR\file.ini" "Section" "Param"
StrCpy $INSTDIR "$0"

K.A.V.
14-07-2014, 21:05
natasha_82, больше конкретики, что имеем, какой формат файла, что нужно сделать (читать значение определённой строки в файле или читать значение параметра в INI файле), либо читать из ключа в реестре? Пишите конкретней, чтобы мы не давали вам размытые ответы, вроде вот этого :)

Справочник по NSIS (http://forum.oszone.net/thread-168287.html) читали, надеюсь?

Изменить путь установки можно в любом месте кода, достаточно присвоить перменной $INSTDIR нужный путь
Если меняете путь установки в silent архиве (тихая установка), то лучше всего менять путь установки в .onInit функции, например чтением из файла формата INI

Пример установки нового путя чтением из INI файла в момент запуска вашего установщика:

ReadINIStr $INSTDIR "$EXEDIR\settings.ini" "TEST" "InstDir"
MessageBox MB_OK "Новая директория установки: $INSTDIR"


Также могу сказать про то, что можно изменить путь установки, выполнив запуск вашего инсталлятора с ключем /D
installer.exe /D=C:\Program Files\Моя папка

Otlanta
15-07-2014, 20:38
Всем привет, как перевести HeX значение в string?

K.A.V.
15-07-2014, 21:14
Otlanta, с помощью плагина Registry (http://nsis.sourceforge.net/Registry_plug-in#StrToHex_.28converts_string_to_hex_values.29)?

Otlanta
15-07-2014, 23:45
K.A.V., неа, почему то отображает не весь текст а лишь первое слово, значение хекс достаточно длинное, есть ли альтернатива?

K.A.V.
16-07-2014, 00:05
K.A.V., неа, почему то отображает не весь текст а лишь первое слово »
Я не знаю, что там у вас обрезается, в моём примере всё корректно отрабатывает

Попробуйте у себя проверить вот этот код:

${registry::HexToStr} "c5f1ebe820e2fb20f7e8f2e0e5f2e520fdf2eef220f2e5eaf1f22c20e7ede0f7e8f220e2fb20ebe3f3ed20e820e220e2e0f8 e5ec20eaeee4e520e4eeeff3f9e5ede020eef8e8e1eae02120cff0e8e2e5f220eef2204b2e412e562e2c20f320eaeef2eef0 eee3ee20e2f1b820f0e0e1eef2e0e5f220eff0e5eaf0e0f1edee203b29" $1
MessageBox MB_OK|MB_ICONINFORMATION "$1"

MKN
16-07-2014, 10:14
значение хекс достаточно длинное, есть ли альтернатива? »
http://nsis.sourceforge.net/Special_Builds
( nsis-2.46-strlen_8192 или nsis-3.0b0-strlen_8192 )

diakov
16-07-2014, 17:09
Уважаемые, возможно ли сделать так что бы установщик переименовал сам себя? Например был файл скомпилированный в nsis file.exe после запуска он в той же директории переименовал себя в file1.exe и продолжал выполнять постановленные задачи?
Ну или как реализовать альтернативный вариант (более закрученый): установщик запущенный из одной директории, путь его расположения помещается в переменную, установщик копирует себя в папку скажем темп, по старому пути удаляется и продолжает выполнять задания по пути из переменной.
С первым пунктом можно сделать установщик в установщике, но хотелось бы проще.




© OSzone.net 2001-2012