Показать полную графическую версию : .: NSIS - все вопросы :. часть 2.
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 - плагин
комплект во вложении :
Периодически необходимо перемещать или копировать файлы в папку, в которой уже имеются сотни файлов , в том числе и одноимённых (т.е. таких же, которые я копирую), которые потом нужно или удалить , или сравнить, или ещё чего...
Оказалось, сделать это удобно с помощью функции 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" на все запросы в ходе операции, т.е. не спрашивать у пользователя подтверждения удаления.
если сообщение всё же желательно - этот флаг ессно не применяем
( Если надо удалить файлы вместе с папкой - не используем *.* )
Интересен код использования функции 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 )
И изображение можно разрушить любым помещённым на него объектом...
Может кто подскажет, как это устранить ?
Пример во вложении :
Есть правда досадный момент - изображение почему то не разрушается при закрытии инсталлятора (хотя 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)`
так и должно быть? »
Вряд ли... Идея интересная, но уж больно тёмная реализация...
Иногда желательно обратить внимание пользователя на какое-либо сообщение программы. Сделать это можно сопроводив сообщение звуковым сигналом встроенного 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"
Есть полезный код, перечисляющий все дисковые устройства и их тип :
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
Вопрос : каким образом занести в одну (или несколько) переменную - ВСЕ полученные в цикле, данные ? Ведь количество дисков не предсказуемо...
Вопрос : каким образом занести в одну (или несколько) переменную - ВСЕ полученные в цикле, данные ? »
Ты снова меня удивляешь простыми вопросами :)
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
удивляешь простыми вопросами »
Сам удивился... :) Делал почти то же самое, но досадно ошибся... Благодарствую.
Всем привет, как определить дату модификации файла с помощью NSIS?
как определить дату модификации файла с помощью 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 - но не подходит, т.к. считывает в момент сборки, и нет реакции если внести изменения((
natasha_82, конечно можно и кстати с ini файлами как раз будет работать, просто не надо этот ini файл подключать в инсталятор, а считывать например из рядом лежащего файла:
ReadINIStr $0 "$EXEDIR\file.ini" "Section" "Param"
StrCpy $INSTDIR "$0"
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\Моя папка
Всем привет, как перевести HeX значение в string?
Otlanta, с помощью плагина Registry (http://nsis.sourceforge.net/Registry_plug-in#StrToHex_.28converts_string_to_hex_values.29)?
K.A.V., неа, почему то отображает не весь текст а лишь первое слово, значение хекс достаточно длинное, есть ли альтернатива?
K.A.V., неа, почему то отображает не весь текст а лишь первое слово »
Я не знаю, что там у вас обрезается, в моём примере всё корректно отрабатывает
Попробуйте у себя проверить вот этот код:
${registry::HexToStr} "c5f1ebe820e2fb20f7e8f2e0e5f2e520fdf2eef220f2e5eaf1f22c20e7ede0f7e8f220e2fb20ebe3f3ed20e820e220e2e0f8 e5ec20eaeee4e520e4eeeff3f9e5ede020eef8e8e1eae02120cff0e8e2e5f220eef2204b2e412e562e2c20f320eaeef2eef0 eee3ee20e2f1b820f0e0e1eef2e0e5f220eff0e5eaf0e0f1edee203b29" $1
MessageBox MB_OK|MB_ICONINFORMATION "$1"
значение хекс достаточно длинное, есть ли альтернатива? »
http://nsis.sourceforge.net/Special_Builds
( nsis-2.46-strlen_8192 или nsis-3.0b0-strlen_8192 )
Уважаемые, возможно ли сделать так что бы установщик переименовал сам себя? Например был файл скомпилированный в nsis file.exe после запуска он в той же директории переименовал себя в file1.exe и продолжал выполнять постановленные задачи?
Ну или как реализовать альтернативный вариант (более закрученый): установщик запущенный из одной директории, путь его расположения помещается в переменную, установщик копирует себя в папку скажем темп, по старому пути удаляется и продолжает выполнять задания по пути из переменной.
С первым пунктом можно сделать установщик в установщике, но хотелось бы проще.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC