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
22-10-2015, 15:30
Как лучше определить, что юзаем десятку? »
WinVer2.nsh от kotkovets правильно определяет ОС - Win10 + прочие параметры десятки, но... в пределах запуска скомпилированного скрипта с HDD...
Запускаю тот же скомпилированный скрипт с флешки - ОС Win10, почему то определяется как Win8 + прочие параметры восьмёрки...
И как это понимать ? :) Сначала было даже смешно..., но как работать с флешки ? :)

wolkow70
22-10-2015, 15:45
MKN,
Windows 8.1 - 6.3
Windows 8 - 6.2
Windows 10 - 10.0
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
У меня в реестре почему-то
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
"ProductName"="Windows 10 Home"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
"CurrentVersion"="6.3"

WinVer2.nsh от kotkovets »
Этот хедер не совместим одновременно со стандартным WinVer.nsh, который мне нужен в скрипте. Вот если бы отдельно функцию выдрать...

MKN
22-10-2015, 15:56
Т.е. - при запуске exe-скрипта с флешки из под Win10 и с помощью чисто GetVersionEx, и с помощью WinVer2.nsh - ошибочная версия ОС. (при запуске с флешки из под W7 и W8 - всё ОК)
При запуске с флешки из под Win10 с помощью WMI.nsh ( т.е. с использованием WMIC) - всё определяется правильно :


;http://nsis.sourceforge.net/WMI_header
OutFile "OperatingSystemInfo.exe"
!include MUI2.nsh
!include WMI.nsh
!include LogicLib.nsh
!insertmacro MUI_LANGUAGE "English"

Var WMI_Caption
Var WMI_Version
Var WMI_CSDVersion
Var WMI_ServicePackMajorVersion
Var WMI_ServicePackMinorVersion
Var WMI_PushVar

Section
; короткое описание версии операционной системы
${WMIGetInfo} root\CIMV2 Win32_OperatingSystem Caption callback_Function
StrCpy $WMI_Caption $WMI_PushVar

; версия ОС
${WMIGetInfo} root\CIMV2 Win32_OperatingSystem Version callback_Function
StrCpy $WMI_Version $WMI_PushVar

; последний установленный сервис-пак (строка); если никакой сервис-пак не установлен, пустая строка.
${WMIGetInfo} root\CIMV2 Win32_OperatingSystem CSDVersion callback_Function
StrCpy $WMI_CSDVersion $WMI_PushVar

; версия сервис-пака
${WMIGetInfo} root\CIMV2 Win32_OperatingSystem ServicePackMajorVersion callback_Function
StrCpy $WMI_ServicePackMajorVersion $WMI_PushVar

; подверсия сервис-пака
${WMIGetInfo} root\CIMV2 Win32_OperatingSystem ServicePackMinorVersion callback_Function
StrCpy $WMI_ServicePackMinorVersion $WMI_PushVar
SectionEnd

Function callback_Function
System::Call "user32::OemToChar(t R2, t. r2)"
detailprint "$2"
StrCpy $WMI_PushVar $2
FunctionEnd


А такой код (ранее предложенный kotkovets), в Win10 - c HDD работате нормально, с флешки в Win10 - вообще не работает

OutFile "WMI_OperatingSystem.exe"
!include "LogicLib.nsh"

!macro IWbemClassObject->Get NameObject OUT
System::Call "*(i,i,i)i.R4"
System::Call "$R3->4(w'${NameObject}',i0,iR4,i0,i0)"
System::Call "*$R4(i.R6,i,i.R5)"
StrCmp $R6 3 0 +2
IntFmt $R5 %u $R5
StrCmp $R6 8 0 +2
!ifdef NSIS_UNICODE
IntFmt $R5 %s $R5
!else
IntFmt $R5 %S $R5
!endif
System::Call "ole32::VariantClear(iR4)"
System::Free $R4
StrCpy ${OUT} $R5
!macroend

Section
System::Call "ole32::CoInitializeEx(i0,i2)"
System::Call "ole32::CoCreateInstance(g'{4590f811-1d3a-11d0-891f-00aa004b2e24}',i0,i1,g'{dc12a687-737f-11cf-884d-00aa004b2e24}',*i.R0)i.R7"
${If} $R7 == 0
System::Call "ole32::CoInitializeSecurity(i0,i-1,i0,i0,i2,i3,i0,i0,i0)"
System::Call "$R0->3(w'root\CIMV2',i0,i0,i0,i0,i0,i0,*i.R1)i.R7"
${If} $R7 == 0
System::Call "$R1->20(w'WQL', w'SELECT * FROM Win32_OperatingSystem',i48,i0,*i.R2)i.R7"
System::Call "$R2->4(i0xffffffff,i1,*i.R3,*i)i.R7"
${If} $R7 == 0

!insertmacro IWbemClassObject->Get "Caption" $7
MessageBox MB_OK "Caption=$7"
!insertmacro IWbemClassObject->Get "Version" $7
MessageBox MB_OK "Version=$7"

System::Call "$R0->2()"
System::Call "$R1->2()"
System::Call "$R2->2()"
System::Call "$R3->2()"
${Else}
System::Call "$R0->2()"
System::Call "$R1->2()"
System::Call "$R2->2()"
${EndIf}
${Else}
System::Call "$R0->2()"
System::Call "$R1->2()"
${EndIf}
${EndIf}
SectionEnd


Может Вячеслав скажет в чём тут дело ? (и подправит код...)

PS StdUtils плаг - также правильно определяет параметры Win10, и с флешки и с HDD. (кстати, он обновился Version 1.08, released 2015-10-10 )

wolkow70
22-10-2015, 17:39
MKN,
Коды WMI работают, но нужно в какой-то переменной просто получить значение 10, а не полную версию Оси.
Можно конечно отрезать, но это уже гемор дополнительный.

kotkovets
22-10-2015, 20:15
с флешки в Win10 - вообще не работает »
спотыкается здесь именно выделенным, возвращается не ноль в $R7, загадка, причины непонятна......
System::Call "$R1->20(w'WQL', w'SELECT * FROM Win32_OperatingSystem',i48,i0,*i.R2)i.R7"
System::Call "$R2->4(i0xffffffff,i1,*i.R3,*i)i.R7"
${If} $R7 == 0

MKN
24-10-2015, 12:27
Пример "географического" кода для определения параметров локализации
(используются функции GetUserDefaultLangID GetLocaleInfo GetUserGeoID GetGeoInfo ) :


OutFile "GetGeoInfo_test.exe"

!include LogicLib.nsh
; LCTYPE Constants - https://msdn.microsoft.com/en-us/library/ms906223.aspx
!define LOCALE_SCOUNTRY 6
!define LOCALE_SENGCOUNTRY 4098
!define LOCALE_SENGLANGUAGE 0x00001001
; SYSGEOTYPE enumeration - https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd374071(v=vs.85).aspx
!define GEOCLASS_NATION 16
!define GEOID_NOT_AVAILABLE -1
!define GEO_ISO2 4
!define GEO_ISO3 5
!define GEO_OFFICIALNAME 9
!define GEO_LATITUDE 2
!define GEO_LONGITUDE 3

Section
System::Call 'KERNEL32::GetUserDefaultLangID()i.r0'
DetailPrint LANGID=$0 ; ID языка, по умолчанию используемого в локали текущего пользователя
System::Call 'KERNEL32::GetLocaleInfo(i$0,i${LOCALE_SENGCOUNTRY},t.r1,i1000)'
DetailPrint LOCALE_SENGCOUNTRY=$1 ; Полное английское название страны / региона.
System::Call 'KERNEL32::GetLocaleInfo(i$0,i${LOCALE_SCOUNTRY},t.r1,i1000)'
DetailPrint LOCALE_SCOUNTRY=$1 ; Полное локализованное название страны / региона.
System::Call 'KERNEL32::GetLocaleInfo(i$0,i${LOCALE_SENGLANGUAGE},t.r1,i1000)'
DetailPrint LOCALE_SENGLANGUAGE=$1 ; Полное английское название языка по международному стандарту кода языков ( ISO 639 )

; текущий регион (местоположение)
; Table of Geographical Locations - https://msdn.microsoft.com/en-us/library/dd374073.aspx
System::Call 'KERNEL32::GetUserGeoID(i${GEOCLASS_NATION})i.r0'
DetailPrint GEOID=$0 ; Geographical location identifier (Decimal). 203 - Russia
${If} $0 <> ${GEOID_NOT_AVAILABLE} ; Only available if the user has set a country/location
${AndIf} $0 != "error" ; GetUserGeoID is WinXP+

; Извлекаем информацию о заданном географическом местоположении на основании GeoID
System::Call 'KERNEL32::GetGeoInfo(i$0,i${GEO_ISO2},t.r1,i1000,i0)'
DetailPrint GEO_ISO2=$1 ; 2-буквенный код страны / региона
System::Call 'KERNEL32::GetGeoInfo(i$0,i${GEO_ISO3},t.r1,i1000,i0)'
DetailPrint GEO_ISO3=$1 ; 3-буквенный код страны / региона
System::Call 'KERNEL32::GetGeoInfo(i$0,i${GEO_OFFICIALNAME},t.r1,i1000,i0)'
DetailPrint GEO_OFFICIALNAME=$1 ; Официальное название страны
System::Call 'KERNEL32::GetGeoInfo(i$0,i${GEO_LATITUDE},t.r1,i1000,i0)'
; координаты расположения страны (точка на карте ~ в центре страны)
DetailPrint GEO_LATITUDE=$1 ; Широта места. Это значение - число с плавающей точкой.
System::Call 'KERNEL32::GetGeoInfo(i$0,i${GEO_LONGITUDE},t.r1,i1000,i0)'
DetailPrint GEO_LONGITUDE=$1 ; Долгота места. Это значение - числo с плавающей точкой.
${EndIf}
SectionEnd


В частности, практический интерес представляет функция GetUserGeoID. Можно автоматом (не выбирая язык из списка) устанавливать, к примеру, язык интерфейса установки и т.д., соответствующий локали пользователя, запустившего инсталлятор.

MKN
25-10-2015, 11:12
Да... Похоже для определения Windows 10 надо использовать новую функцию - IsWindowsVersionOrGreater
http://stackoverflow.com/questions/32115255/c-how-to-detect-windows-10
http://www.tek-tips.com/faqs.cfm?fid=7848

Осталось адаптировать эту функцию под NSIS...

MKN
27-10-2015, 13:01
Вариант определения major и minor версий ОС с помощью функции NetWkstaGetInfo.
В Win 10 работатет (и с флешки тоже)


OutFile WinVer-NetWkstaGetInfo.exe
InstallDir $TEMP
ShowInstDetails show
RequestExecutionLevel admin
Page instfiles
# Примечание: В старых версиях NSIS (в том числе 2,46) System plug-in не поддерживае тип р, нужный для правильной работы кода

; используется структура WKSTA_INFO_100 https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa371402(v=vs.85).aspx
; а именно : DWORD wki100_ver_major и DWORD wki100_ver_minor;

Section
System::Call "netapi32::NetWkstaGetInfo(pn,i100,*p.R1)i.R2"
System::Call "*$R1(i,p,p,i.R3,i.R4)"
# в $R3 - основной номер версии ОС ver_major, в $R4 - доп. номер версии**ver_minor
IntOp $R0 $R3 << 16
IntOp $R0 $R0 | $R4
System::Call "netapi32::NetApiBufferFree(pR1)"
;Результат в шестнадцатеричной системе счисления
# 0x00050000 5.0 Windows 2000
# 0x00050001 5.1 Windows XP
# 0x00050002 5.2 Windows XP (x64), Windows Server 2003, Windows Server 2003 R2
# 0x00060000 6.0 Windows Vista, Windows Server 2008
# 0x00060001 6.1 Windows 7, Windows Server 2008 R2
# 0x00060002 6.2 Windows 8, Windows Server 2012
# 0x00060003 6.3 Windows 8.1, Windows Server 2012 R2
# 0x000A0000 10.0 Windows 10, Windows Server Technical Preview
IntFmt $R0 "0x%08X" $R0
DetailPrint "$R0"
; получаем ver_major и ver_minor "в десятичном виде"
IntOp $0 $R0 >> 16
IntOp $1 $R0 & 0xFFFF
DetailPrint "$0.$1"
SectionEnd

wolkow70
27-10-2015, 14:57
MKN,
Я для своих нужд так сделал:

Var IsOSWin10
StrCpy $IsOSWin10 "0"

Push $R0
Push $R1
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ProductName"
StrCpy $R1 $R0 10
${If} $R1 == "Windows 10"
StrCpy $IsOSWin10 "1"
${EndIf}
Pop $R1
Pop $R0

${If} $IsOSWin10 == "1"
Выполняем комманды для Windows 10
${EndIf}

kotkovets
27-10-2015, 21:40
Вариант определения major и minor версий ОС с помощью функции NetWkstaGetInfo »
будет время попытаюсь, вшить эти директивчики десяточные в winver2
# Примечание: В старых версиях NSIS (в том числе 2,46) System plug-in не поддерживае тип р, нужный для правильной работы кода »
нормально всё работает на 2,46, вместо p - i (integer)

wolkow70
29-10-2015, 07:37
MKN,
Подкорректируйте пожалуйста код NetWkstaGetInfo для 2,46, с учетом замечания
kotkovets, нормально всё работает на 2,46, вместо p - n (integer) »

MKN
29-10-2015, 10:34
wolkow70,
Можно ещё проще, без канители с конвертированием. ( Я ведь такой код уже выкладывал в прошлом году... )

System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i r0 r0) i.r6"
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
MessageBox MB_OK "$2 $3 domain (platform_id $1 - ver OS $4.$5) "
System::Call "netapi32::NetApiBufferFree(*i r0) i.r6"


но, как рекомендуют, если вдруг функция выполнится с ошибкой , так :

!include LogicLib.nsh
System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i 0 r0) i.r1"
${If} 0 = $1
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
MessageBox MB_OK "$2 $3 domain (platform_id $1 - ver OS $4.$5) "
${EndIf}
${IfThen} $0 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir0)" ${|}


Есть ещё такой занятный код - версия ОС берётся из ресурсов какой-либо системной DLL, например из kernel32.dll.
Работает в Win10


Outfile "OS-Info_test.exe"

!ifndef RT_VERSION
!define RT_VERSION 16
!endif
!ifndef VS_FILE_INFO
!define VS_FILE_INFO ${RT_VERSION}
!endif
!ifndef VS_VERSION_INFO
!define VS_VERSION_INFO 1
!endif

Section
StrCpy $R0 0
System::Call 'kernel32::LoadLibrary(t"kernel32.dll")p.R1' ; System::Call "kernel32::LoadLibrary(t '\path\your.dll(exe)') i .r0"
IntCmp $R1 0 error
System::Call 'kernel32::FindResource(pR1,p${VS_VERSION_INFO},p${VS_FILE_INFO})p.R2'
IntCmp $R2 0 ok
System::Call 'kernel32::LoadResource(pR1,pR2)p.R3'
IntCmp $R3 0 ok
System::Call 'kernel32::LockResource(pR3)p.R4'
IntCmp $R4 0 ok
System::Call "*$R4(&i2,&i2.R5,&i2,&w16,&i2,i,i,i.R6)"
IntCmp $R5 0 ok
IntFmt $R0 "0x%08X" $R6
ok:
System::Call "kernel32::FreeLibrary(pR1)"
error:
IntOp $0 $R0 >> 16
IntOp $1 $R0 & 0xFFFF
DetailPrint "$0.$1"
MessageBox MB_OK "ver $0.$1"
SectionEnd


Этот код можно использовать для определения версий не только DLL, но и EXE.
Жаль, что только до одного знака подверсии... Возможно можно как то подкорректировтаь...

Также интересна функция System::Call 'ntdll::RtlGetVersion , работающая в Win10
Но с её синтаксисом я не разобрался...

wolkow70
29-10-2015, 13:28
MKN,

Можно ещё проще, без канители с конвертированием. ( Я ведь такой код уже выкладывал в прошлом году... ) »
Похоже, что-то не то в конце получается:

DetailPrint
0x00000000
0.0
Completed

MKN
29-10-2015, 13:40
Похоже, что-то не то в конце получается: »
У меня всё нормально работает и после компиляции NSIS 3 и после NSIS 2.46 и на всех ОС.

wolkow70
29-10-2015, 13:48
У меня всё нормально работает и после компиляции NSIS 3 и после NSIS 2.46 и на всех ОС. »
Можно более полный блок кода?

MKN
29-10-2015, 15:05
Можно более полный блок кода? »
:) Куда уж полнее, чем уже дан... Выложи ка свой, не работающий код.

wolkow70
29-10-2015, 17:29
MKN,

Собственно с вашего копировал...

OutFile WinVer-NetWkstaGetInfo.exe
InstallDir $TEMP
ShowInstDetails show
RequestExecutionLevel admin
Page instfiles
!include LogicLib.nsh
# Примечание: В старых версиях NSIS (в том числе 2,46) System plug-in не поддерживае тип р, нужный для правильной работы кода

; используется структура WKSTA_INFO_100 https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa371402(v=vs.85).aspx
; а именно : DWORD wki100_ver_major и DWORD wki100_ver_minor;

Section

System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i 0 r0) i.r1"
${If} 0 = $1
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
MessageBox MB_OK "$2 $3 domain (platform_id $1 - ver OS $4.$5) "
${EndIf}
${IfThen} $0 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir0)" ${|}

;Результат в шестнадцатеричной системе счисления
# 0x00050000 5.0 Windows 2000
# 0x00050001 5.1 Windows XP
# 0x00050002 5.2 Windows XP (x64), Windows Server 2003, Windows Server 2003 R2
# 0x00060000 6.0 Windows Vista, Windows Server 2008
# 0x00060001 6.1 Windows 7, Windows Server 2008 R2
# 0x00060002 6.2 Windows 8, Windows Server 2012
# 0x00060003 6.3 Windows 8.1, Windows Server 2012 R2
# 0x000A0000 10.0 Windows 10, Windows Server Technical Preview
IntFmt $R0 "0x%08X" $R0
DetailPrint "$R0"
; получаем ver_major и ver_minor "в десятичном виде"
IntOp $0 $R0 >> 16
IntOp $1 $R0 & 0xFFFF
DetailPrint "$0.$1"
SectionEnd

MKN
29-10-2015, 17:49
wolkow70,
В примерах были разные переменные для версий. И во втором варианте НЕ нужно кода конвертации.
Т.е. в итоге :

OutFile WinVer-NetWkstaGetInfo.exe
InstallDir $TEMP
ShowInstDetails show
RequestExecutionLevel admin
Page instfiles
!include LogicLib.nsh

Section
System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i 0 r0) i.r1"
${If} 0 = $1
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
;MessageBox MB_OK "ver OS $4.$5) "
DetailPrint "$4.$5"
${EndIf}
${IfThen} $0 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir0)" ${|}
SectionEnd

Dodakaedr
03-11-2015, 08:35
Объясните, пожалуйста, почему если указать в строке 'StrCmp $R0 "0"' 0 +5 сообщение показываеться, а если +4 то нет.
outfile "test.exe"
!include "Registry.nsh"
Autoclosewindow true
Silentinstall silent
section "Main"
${registry::KeyExists} "HKCU\Software\11" $R0
StrCmp $R0 "0" 0 +4
${registry::MoveKey} "HKCU\SOFTWARE\11" "HKCU\SOFTWARE\11_backup" $R4
${registry::Unload}
goto +2
MessageBox mb_ok|mb_iconinformation "Ключа нет"
quit
sectionend

K.A.V.
03-11-2015, 10:00
Объясните, пожалуйста, почему если указать в строке 'StrCmp $R0 "0"' 0 +5 сообщение показываеться, а если +4 то нет. »
Потому что строки:
${registry::MoveKey} "HKCU\SOFTWARE\11" "HKCU\SOFTWARE\11_backup" $R4
${registry::Unload}
это не команды, а макросы, а в макросах может содержаться несколько команд
Макрос в NSIS своеобразная "оболочка" для команд, в макросы можно заключить несколько часто используемых команд+удобно потом ориентироваться в коде
Т.е. прописывая сроку с макросом, при компиляции эта самая строка может развернуться в несколько десятков строк (в зависимости от команд, которые прописаны в теле макроса) и, соответственно, при использовании всяких +2 +3 +5 прыжков на строку, которая прописана за макросом, может оказаться проблемой и вы получите нерабочий/не правильно работающий код

Конкретно в вашем коде - макрос ${registry::MoveKey} содержит в себе 2 строки команд:
!macro registry::MoveKey _PATH_SOURCE _PATH_TARGET _ERR
registry::_MoveKey /NOUNLOAD `${_PATH_SOURCE}` `${_PATH_TARGET}`
Pop ${_ERR}
!macroend
Из-за чего ваш код стал не рабочим
Для решения этой проблемы либо создавайте метку и указывайте её в качестве цели "прыжка" (за место +4), либо еще лучше, пользуйтесь конструкциями с ${If}
outfile "test.exe"
!include "Registry.nsh"
Autoclosewindow true
Silentinstall silent
section "Main"
${registry::KeyExists} "HKCU\Software\11" $R0
${If} $R0 == "0"
${registry::MoveKey} "HKCU\SOFTWARE\11" "HKCU\SOFTWARE\11_backup" $R4
${registry::Unload}
${Else}
MessageBox mb_ok|mb_iconinformation "Ключа нет"
${EndIf}
quit
sectionend




© OSzone.net 2001-2012