echo "First line" >newfile.txt
cat oldfile.txt >>newfile.txt
mv newfile.txt oldfile.txt
sed -i -e '1 s/^/First line\n/' file.txt
echo "First line" >newfile.txt
cat oldfile.txt >>newfile.txt
mv newfile.txt oldfile.txt
sed -i -e '1 s/^/First line\n/' file.txt
Проще всего сделать sed’ом.
В том же самом файле (добавляем параметр командной строки -i
):
sed -i 's/\r$//' file.txt
В другой файл:
cat winfile.txt | sed -i 's/\r$//' >linuxfile.txt
Например, у нас есть софтина, которая в процессе своей установки требует перезагрузку, после чего доустанавливается. Например, софт устанавливает свой драйвер, обновление, или же регистрирует системный сервис. Как реализовать инсталлятор для такой программы?
Изначально я хотел обойтись параметрами командной строки, добавляемыми при запуске установщика, но с ними произошла жопа, поэтому будем действовать более надежными методами.
0. Проверяем наличие уникального ключа Реестра, сигнализирующего о том, что надо выполнить вторую часть установки (после перезагрузки):
DetailPrint "Read After Reboot flag..."
ReadRegStr $R0 HKCU "Software\Microsoft\Windows\CurrentVersion\"
"${APPNAME}_afterreboot"
StrCmp "$R0" "1" AfterReboot
1. Производим все действия, которые необходимо произвести до перезагрузки (устанавливаем драйвера, регистрируем DLL и т.д.)
2. Записываем в однократную автозагрузку (ключ Реестра RunOnce
) наш инсталлятор, путь к exe файлу инсталлятора, который можно взять из переменной $EXEPATH
.
Автозагрузку прописываем для текущего пользователя (пользователя, запустившего установщик), т.е. в ключ HKEY_CURRENT_USER
.
WriteRegStr HKCU
"Software\Microsoft\Windows\CurrentVersion\RunOnce"
"${APPNAME}" "$EXEPATH"
Примечание: В RunOnce
могут записаться программы, которые требуется выполнить однократно при загрузке системы. После выполнения программ, ключ RunOnce
очищается автоматически, что отличает его от ключа Run
, где данные не очищаются, и его можно использовать, как постоянную автозагрузку.
3. Устанавливаем уникальный флаг, по которому будем определять, что инсталлятор был запущен после перезагрузки, например, таким образом:
DetailPrint "Write After Reboot flag..."
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\"
"${APPNAME}_afterreboot" "1"
4. Выдаем запрос на немедленную перезагрузку:
DetailPrint "Reboot request."
MessageBox MB_YESNO|MB_ICONINFORMATION
"Installation will be cobntinue after reboot. Press OK to reboot now." IDYES RebootID
Если пользователь ответил «Yes
«, сразу перезагружаемся:
RebootID: DetailPrint "Rebooting..." Reboot
Если нет, ждем перезагрузки вручную:
DetailPrint "Installation continue if user restart system."
Goto SecEnd
5. После перезагрузки удаляем флаг (проверив его наличие, см выше):
DetailPrint "Delete After Reboot flag..."
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\"
"${APPNAME}_afterreboot"
6. И продолжаем установку…
DetailPrint "Continue install after reboot..."
Вот серьезно, бьюсь (головой об стену) уже третий день, ну не работает функция GetOptions
, так, как заявлено в NSIS Wiki, уже и по колесам стучал, и фары протирал, в смысле просто тупо копировал код из примера в тестовый инсталлятор, и еще десяток написал, перепробовав все что можно и нельзя, ну не выходит каменный цветок, хоть тресни. Функция в любом случае выдает, либо что никаких ошибок не случилось, для следующего кода, соответственно, всегда получается found:
Section ${GetOptions} "/S /T" "/T" $R0 IfErrors 0 +2 MessageBox MB_OK "Not found" IDOK +2 MessageBox MB_OK "Found" SectionEnd
Либо, для следующего кода всегда остается значение по умолчанию, даже если в командной строке явно задано иное:
Section ${GetOptions} "/AR=N" "/AR=" $R0 DetailPrint "R0: $R0" SectionEnd
Например, выполняешь TestInstaller.exe /AR=Y
, все равно в переменной $R0
оказывается N
Такие дела.
Пришли сегодня ко мне с одной задачкой, мол есть у нас программка, которая висит в фоне и периодически выводит данные в консоль. Неудобно оператору работать, либо что-то другое делать, либо ничего не делать, лишь в консоль смотреть. Даже отдельный комп думаем программке выделить, чтоб она на нем крутилась-вертелась. И нельзя ли так сделать, чтоб программку на другом терминале запустить, чтоб можно было по Ctrl+Alt+F[номер] переключаться, и за состоянием программки смотреть?
Вот запустить нельзя, без особого бубна, а вывод переопределить, всегда пожалуйста.
Можно пользуясь стандартным перенаправлением ввода-вывода в Linux, заставить программу или скрипт отправлять сообщения на другой терминал. Пусть программка будет называться tscript
. За терминалы в Linux отвечают устройства /dev/tty*
, например, /dev/tty2
отвечает за терминал, вызываемый по Ctrl+Alt+F2.
Например, чтобы программа переопределяла вывод на /dev/tty2
, запускаем ее таким образом:
tscript >/dev/tty2
Можно отправить на другой терминал только вывод сообщений об ошибках:
tscript 2>/dev/tty2
Чтобы программа работала в фоне, а на том терминале, с которого мы ее запустили, можно было продолжить работу, добавляем после команды знак &
:
./tscript >/dev/tty2 &
Пишем тестовый скрипт, который, скажем, будет бесконечно выводить на консоль случайное шестнадцатиричное число раз в секунду:
#!/bin/bash SEC=1 echo "Test script, write to STDOUT random number after $SEC sec." while [ 1 -eq 1 ];do sleep $SEC printf 'Number: %x\n' $RANDOM done
Пишем скрипт, который будет убивать тестовый:
#!/bin/bash
echo "Kill test script..."
pkill tscript
Пишем запускающий скрипт, в котором вывод тестового скрипта переопределяется на терминал tty2
:
#!/bin/bash
TERMNO=2
echo "Send tscript output to terminal #$TERMNO"
./tscript >/dev/tty$TERMNO &
Запускаем тестовый скрипт на текущем терминале:
Выполняем запускающий скрипт:
Вывод на tty2
Исходники примера
Секции — это удобный механизм, позволяющий обеспечить пользователю выбор компонентов программы, если такие присутствуют. В каждой секции можно создавать свои ярлыки, распаковывать файлы, и производить любые другие действия, практически независимо от других секций. Естественно, значения переменных, измененные в одной секции, в других тоже будут изменены, потому что в NSIS все переменные глобальные.
Для самого простого выбора компонентов в NSIS, необходимо вставить в скрипт, перед, собственно, описанием секции, следующий код:
ComponentText "Какой-то текст"
, например:
ComponentText "Choose which features of ${APPNAMEANDVERSION} you want to install."
Естественно, ${APPNAMEANDVERSION}
должна быть заранее определена:
!define APPNAME "SectionsExample"
!define APPNAMEANDVERSION " SectionsExample 0.1"
В любом NSIS-скрипте должна быть создана хотя бы одна секция, иначе компилятор будет ругаться, и файл установщика не создаст. В самом простом случае, когда не требуется выбор компонентов, создается единственная секция без названия:
Section DetailPrint "Hello, world!" SectionEnd
Примечание: После конструкции Section
идет имя секции, заключенное в кавычки. Если кавычки пропустить, то имя секции будет некорректным, и неверно отобразится в окне выбора компонентов. Попробуйте вставить следующий код в пример, и посмотрите, как он будет работать. Ссылка на пример в конце заметки.
Section Component 4 ; Wrong section description SetOverwrite on DetailPrint "Component #4 installing..." SectionEnd
Для чего? Например, у нас есть программа, у которой, в свою очередь есть основные компоненты, например экзешник и DLL, а также дополнительные, которые можно устанавливать, а можно и не устанавливать. И если уж пользователь хочет поставить наше приложение, то он должен установить хотя бы основные компоненты.
Для того, чтобы заблокировать чекбокс, прописываем в начале секции конструкцию:
SectionIn RO
Section "Main Program and components" ; Checkbox select and disable user changes SectionIn RO SetOverwrite on DetailPrint "Main program installing..." SectionEnd
Для этого ничего делать не надо, только определить секцию с именем в кавычках и дефольными настройками. Пользователь может деактивировать checkbox (снять галочку) в окне выбора компонентов.
Section "Component #2" ; Checkbox enabled by default & user will change it state SetOverwrite on DetailPrint "Component #2 installing..." SectionEnd
Наверное, самый частый вопрос, задаваемый, что в рунете, что в Интернете вообще, по поводу NSIS. Так вот, ларчик открывается просто. Достаточно после Section
поставить специальный флаг /o
.
Пользователь также сможет активировать checkbox (галочку), если ему нужно будет установить данный компонент.
Section /o "Component #3" ; Checkbox disabled by default & user will change it state SetOverwrite on DetailPrint "Component #3 installing..." SectionEnd
Такие секции не будут отображены в окне выбора компонентов. Их названия пишутся без кавычек и без пробела, а перед названием ставится знак «-
«. Код в таких секциях будет выполнен в любом случае, независимо от желания пользователя:
Section -HiddenSection DetailPrint "This is a hidden section" DetailPrint "This code running anyway." SectionEnd
К ним, наверное, относится одна — Uninstall
, ну и еще не совсем секция, а встроенная функция, которую можно переопределить, дописав свой код, т.е. что-то типа обработчика событий в «больших» языках, например в C#
О секции Uninstall
и рассказывать особо не надо, кроме ремарки, что в секции Uninstall
«забываются» все значения глобальных переменных и значение переменной $INSTDIR
Наконец-то руки дошли прикрутить инсталлер и выложить 🙂
Программа предназначена для отображения внешнего IP-адреса компьютера, определения географической принадлежности IP-адреса, а также того, не попадает ли IP-адрес в список «запрещенных» стран.
Программа получает IP-адрес, из поставляемого с ней PHP-скрипта, размещенного на Web-сервере в Интернете, и/или (в текущей версии) с сайтов, которые информируют пользователя о его внешнем IP. В текущей версии не все такие сайты подходят (сайт не должен быть заскриптован, не требовать обязательного использования cookie и не выдавать капчу), а оригинальный скрипт PHP предоставляет некоторые дополнительные возможности.
Далее, программа получает из базы данных SxGeo сведения о геопозиции, и, если настроено и IP-адрес попал в стоп-лист стран, выводит предупреждение о попадании в данный список.
Свежую версию БД SxGeo можно бесплатно скачать с сайта разработчиков базы данных: https://sypexgeo.net/ru/download/
Программа при запуске находится в системном трее, управление производится через контекстное меню.
Изначально писалась по заказу одного активиста, у которого была проблема с периодическим отключением от VPN, в связи с чем, случайно мог «засветиться» его IP, или VPN мог переключить его на нежелательную страну.
По умолчанию программа запускается в «портативном» режиме (все данные хранятся в подкаталоге data
каталога с исполняемым файлом)
Microsoft Windows XP и выше (Vista/7/8/8.1/10), .NET Framework 2.0 и выше, 512 Мб оперативной памяти, 15 Мб на жестком диске.
В качестве контрола для ввода IP-адреса мы использовали C# IP Address Control вот этого автора:
https://www.codeproject.com/Articles/9352/A-C-IP-Address-Control
База данных SypexGeo (SxGeo):
© 2006-2018 zapimir
© 2006-2018 BINOVATOR
0.0.1 b, 19/01/2010 — Первая версия, написанная для товарища OPPosition
0.1.2 08/08/2018 — Исправлен код запросов и конфигов, многое переделано
0.2.0 01/07/2019 — Программа «отвязана» от скрипта с SxGeo на сервере, интерфейс к БД SxGeo перенесен внутрь программы, запросы к БД обрабатываются локально, добавлена поддержка других источников IP-адресов. Первая публичная версия.
Портабельная версия
Инсталлятор
С подрочества собирал фразочки, опечатки, оговорки и приколы, а так же надписи в лифтах и туалетных кабинках. Вот он вам тот самый сборник (часть I)
Программа выполнила некорректную операцию и будет закрыта
Любимая ось
Девушки! Не бойтесь секса, он во рту вкуснее кекса!
Подсмотренно в туалете
Я сегодня милку съел, только клитор захрустел.
Постапокалиптическое
Не верь хую, встающему по утру,
Ведь он не любви просящий,
А ПОПИСАТЬ вопиющий.
Подсмотренно в туалете лицея
Кафедра физики мертвого тела.
Кафедра физики голого тела.
Кафедра МАТанализа. Лицам младше 18 лет вход строго запрещен.
Надпись на туалете: «Мы ждем Вас».
Студенты
У какого же растения все-таки квадратный корень???
Карл Линней
Изготовление оградок, стальных дверей, арматуры, оконных решеток по
чертежам заказчика и других металлических изделий.
Отдам запорожец в добрые руки
Объявление
Наша деревня называется Трах
«Поход изгоев»
А я деятель физиологии, анатомии и знатный фекаловед!
Подвал имел отношение к заведению жрального типа, которое умерло грязной
смертью из-за запрета СЭС.
«В мире животного»
Принять меры по эксплуатации людей…
Правила ПБ ЦГБ
Надпись на могиле: «Эй вы, жлобы из профсоюза, а теперь верите, что я был
БОЛЕН!?»
Рабинович.
Постоянно следуй влечению
Не высказывай всё напрямую, но лучись добротой
Конкурентов нет, но будь ангелом
Набаловав, не упорядочивай связи
Уважай седины, а не прикидывайся незнайкой
В долгах перехватывай инициативу
По-женски гаси возмущение
Мой генератор фразочек
Покупайте лотерейные авиобилеты.
«Красная шапочка, я тебя съем!» , — сказал пионер и сожрал свою пилотку.
Как говорят в мужской балетной школе — одно другому не мешает.
Если вы постоянно ставите точки над i, значит вы пишите по-украински
Русское радио
Сел гвоздем на задницу.
Дебицилл.
Губернал-генератор.
Быстро надежно и без хлопот Вас похоронит Аэрофлот.
Без подписи.
У Армянского Радио спрашивают: «Многие города переименовали, а как можно
переименовать Москву?»
«На прошлой неделе — в Ереван, а теперь после активизации скинхедов —
в Жидгород»
Почему албанцы дают жару сербам? Так ведь у них столица в стране — Тирана!
Наши бы переименовали Москву в Наподдаванск, тоже что-нибудь бы устроили!
Все гордимся мы сполна,
Что российский хакер
Сеть любую без труда
Взламывает на фиг.
«Тушите свет»
Это программное обеспечение было установлено под счетом с правами
администратора. Вы должны бревно на счет с правами администратора
неустановить это программное обеспечение.
Переводчик
Вчера прохожий Н. гуляя по лесу наткнулся на пожарную часть.
Это была часть пожарного, которого накануне задрал медведь
Наши глупости
Лопаты по технике безопасности.
Электрический торк.
Числотное кисло.
Иногда настает момент, когда больше уже нельзя оттягивать свой конец.
Надпись в зеленом блокнотике: гр 17 — ЖОПА!
Про мою работу: Че тут написано?! Тыр-пыр. Тру-щу-щу???
Препод по электротехнике
Перелом тазов.
Пердохранители
Класрификация помещений по степени электрической. опасности
Помазать ожог сырыми яйцами.
Затянуть жгут повыше руки.
Затянуть жгут повыше локтя, пониже запястья.
Хабзайцы
Контакторы пенного тока
Магнитные пукатели
Марки кобелей
Замеситель директора
Неисправность барана принтера
Налоговая баба
1 МОм = 1024 кОм
Сие печатал и говорил я.
Или как поместить uninstaller не в директории программы.
Конечно, возникает вопрос «зачем?». Ну, например, мы устанавливаем некое системное приложение, драйвер, или хотим что-то пропатчить. В качестве каталога по умолчанию для такого приложения может служить, например, директория $WINDIR
(обычно C:\Windows
). Если мы хотим безболезненно удалить такое приложение, то нам нужно создать анинсталлер, но, совсем не обязательно чтоб он хранился в том же каталоге, что и установленное приложение. Зачем, например, загаживать каталог C:\Windows
файлами uninstall.exe
. Да в том то все и дело, что незачем, и вот тут мы сталкиваемся с глюками анинсталлера.
В анинстайлере и инсталляторе переменная $INSTDIR
определяется по-разному. В секции установки $INSTDIR
можно задать, в т.ч. и автоматически, а в uninstaller’е она определяется, как директория, из которой запустился анинсталлер. Это довольно легко проиллюстрировать простым кодом, который на самом деле ничего не устанавливает, а просто предлагает пользователю выбрать каталог для установки, а сам выводит пути к каталогам и создает тестовый анинсталлер во временном каталоге. Анинсталлер тоже ничего не удаляет, просто выводит значения переменных, заданных в основном скрипте.
Любые пользовательские переменные при работе uninstall так же «забываются», вне зависимости от того, были ли они определены в секции, или в скрипте вообще.
Фрагмент кода из установщика:
; явно задаем директорию для установки InstallDir "$PROGRAMFILES\TestUninst" ;создаем тестовую переменную Var TESTVAR ;[..] ;выводим окно для выбора директории для установки DirText "Choose the folder in which to install ${APPNAME}." Section "Inst" ; Set Section properties SetOverwrite on StrCpy $TESTVAR "Test variable value" DetailPrint "INSTDIR (install): $INSTDIR" DetailPrint "TESTVAR (install): $TESTVAR" WriteUninstaller "$TEMP\TestUninst.exe" SectionEnd
Секция установки:
1. Заполняем $TESTVAR
2. Выходим значение $TESTVAR
3. Выводим значение $INSTDIR
4. Создаем Uninstall’ер, причем не в $INSTDIR
В секции удаления выводим значения $INSTDIR
и $TESTVAR
, анинсталлер запускаем из временного каталога.
Section Uninstall SetDetailsView show DetailPrint "INSTDIR (uninstall): $INSTDIR" DetailPrint "TESTVAR (uninstall): $TESTVAR" SectionEnd
Значение $INSTDIR
изменилось на временный каталог, а значение $TESTVAR
было потеряно. Если переместить анинсталлер в другой каталог, значение $INSTDIR
опять поменяется.
Из вышеизложенного напрашивается вывод, что значения $INSTDIR
и нужных переменных надо сохранять на этапе установки, например в Реестр или INI-файл, а на этапе удаления восстанавливать.
В следующем примере я буду сохранять нужные значения в INI-файл, который будет располагаться в директории с uninstall.exe
, а сама программа будет устанавливаться в другой каталог. Сгенерирую простой скрипт мастером скриптов и немного подправлю.
1. Меняем InstallDir
на "$TEMP\TestApp"
InstallDir "$TEMP\TestApp"
2. Заводим переменную $UNINSTDIR
Var UNINSTDIR
3. В секции установки задаем ее значение, скажем "$PROGRAMFILES\TestApp"
StrCpy $UNINSTDIR "$PROGRAMFILES\TestApp"
4. Создаем каталог $UNINSTDIR
CreateDirectory "$UNINSTDIR"
5. Меняем где надо пути в создаваемых ярлыках
CreateShortCut "$SMPROGRAMS\TestApp\Uninstall.lnk" "$UNINSTDIR\uninstall.exe"
6. …путь для записи uninstall.exe
WriteUninstaller "$UNINSTDIR\uninstall.exe"
7. …и запись в Реестре для «Программ и компонентов»
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$UNINSTDIR\uninstall.exe"
8. После создания uninstall.exe
в каталоге $UNINSTDIR
необходимо создать INI-файл, в который сохранить пути к каталогам $UNINSTDIR
и $INSTDIR
WriteINIStr "$UNINSTDIR\dirs.ini" "dirs" "I" "$INSTDIR"
WriteINIStr "$UNINSTDIR\dirs.ini" "dirs" "U" "$UNINSTDIR"
На этом с секцией установки закончили.
В секции удаления:
1. Читаем значения из INI-файла (который для uninstall.exe
будет располагаться в каталоге из переменной $INSTDIR
) в перезаписываемые переменные $0
и $1
. Если чтение не удалось, необходимо будет обработать ошибку (см. описания функций ReadINIStr
и конструкции IfErrors
в справочнике копия).
ReadINIStr $0 "$INSTDIR\dirs.ini" "dirs" "I"
IfErrors Dupa 0
ReadINIStr $1 "$INSTDIR\dirs.ini" "dirs" "U"
IfErrors Dupa 0
2. Восстанавливаем значения $INSTDIR
и $UNINSTDIR
:
StrCpy $INSTDIR $0
StrCpy $UNINSTDIR $1
3. Удаляем uninstall.exe
, INI-файл и каталог анинсталлера:
Delete "$UNINSTDIR\uninstall.exe"
Delete "$UNINSTDIR\dirs.ini"
RMDir "$UNINSTDIR\"
4. Удаляем компоненты программы и ярлыки.
5. В конце секции заводим метку OK:
6. После удаления программы переходим в конец секции
Goto OK
7. Перед меткой OK:
заводим метку Dupa:
, куда попадем если произошла ошибка чтения INI-файла. После метки Dupa:
будет обработчик ошибки. В данном случае выводим пользователю сообщение о том, что INI-файл некорректный, и произвести автоматическое удаление программы нельзя.
Dupa: MessageBox MB_ICONSTOP|MB_OK "Error reading $INSTDIR\dirs.ini! Uninstall aborted!"
1. Исходник, иллюстрирующий баг uninstaller’а
2. Исходник примера
Не сильно хороший, но пусть будет.
Примечание: Если открываешь CHM-файл а страницы пустые, нажимаем на файле правой кнопкой мыши, заходим в свойства и разблокируем его (там кнопка будет)
Одна из частых задач при создании инсталлятора — определить версию и архитектуру ОС, например, чтобы в зависимости от этого подкладывать нужную версию экзешника, или устанавливать нужный драйвер.
Для отображения версии Windows можно воспользоваться готовым кодом из NSIS wiki. На выбор предоставлены два скрипта: только для клиентских ОС и для клиентских и серверных. Для своих целей я пользовался вторым, правда в нем есть небольшой баг — клиентская Windows XP x64 определяется как Windows Server 2003:
Создаем отдельный пустой NSIS-скрипт, копируем туда код из wiki, и сохраняем в тот же каталог, где находится основной скрипт инсталлятора под любым удобным названием, например gvv.nsi
.
В основном скрипте подключаем этот файл:
!include gvv.nsi
Далее вызываем GetWindowsVersion
, записываем результат в переменную (например, в предопределенную $R0
) и выводим результат:
${GetWindowsVersion} $R0
DetailPrint "Windows Version: $R0"
Так сказать, «точное» определение версии. Применяется, когда надо выполнить определенные действия, например, в XP и только в XP, или в семерке и только в семерке.
Для этого в комплекте есть модуль WinVer.nsh
, сначала подключим его:
!include WinVer.nsh
Далее используем if
и один из макросов IsWin?
, например IsWinXP
, IsWin7
, IsWin10
:
${If} ${IsWinXP} DetailPrint "Is Windows XP" ${EndIf}
Применяется, когда нужно выполнять код, если версия ОС выше нужной или нужная.
В WinVer.nsh
есть другой комплект макросов — AtLeastWin?
(AtLeastWin7
, AtLeastWin8
, AtLeastWin10
) которые также нужно использовать вместе с if
. Например, следующий код сработает на «семерке» и всех последующих версиях Windows. В деталях установки отобразится соответствующее сообщение:
${If} ${AtLeastWin7} DetailPrint "Is Windows 7 or higher" ${EndIf}
Для определения архитектуры ОС необходимо подключить модуль x64.nsh
(также поставляется вместе с компилятором NSIS):
!include x64.nsh
Поддерживается определение архитектуры x86 (IsNativeIA32
), PC (AMD) x64 (IsNativeAMD64
) и ARM64 (IsNativeARM64
) пример кода есть в самом файле x64.nsh
🙂 Мне ARM была не нужна, поэтому пример кода на три строки короче:
${If} ${IsNativeAMD64} DetailPrint "System Architecture: x64" ${ElseIf} ${IsNativeIA32} DetailPrint "System Architecture: x86" ${Else} DetailPrint "Unsupported CPU architecture!" ${EndIf}
1. Get Windows version
2. Stackoverflow
Может поможет и для других ноутов Acer.
Иногда надо отключить в BIOS/UEFI опцию Secure Boot, например, чтобы переустановить Windows с флешки, иначе при загрузке получим сообщение Secure Boot Fail.
Не знаю, что скурили инженеры Acer, но пункт Secure Boot в разделе Boot неактивен, и по умолчанию его значение никак не изменить. Итак, отключаем Secure Boot:
1. Заходим в BIOS/UEFI (клавиша F2 при загрузке)
2. Переходим в раздел Security
3. Задаем Supervisor Password (пароль администратора BIOS). Без разницы какой, но главное его не забыть — забудете, будете долго трахаться с перепрошивкой BIOS. Просто так сбросить его не получится! Так что задайте что-нибудь типа 111
4. На этом этапе нужные пункты уже будут открыты, но лучше зайти на последнюю вкладку, выбрать Exit & Save Changes, перезагрузиться и вновь войти в BIOS по F2
5. Потом надо будет ввести установленный пароль.
6. Пункт Secure Boot в разделе Boot стал активен, теперь можно изменить его значение на Disabled
Изучение любого языка начинается с Hello, world, вот и я не буду отступать от этой традиции. Напишем простой инсталлятор, который даже не инсталлятор, потому что ничего не устанавливает, а просто пишет сообщение пользователю.
Name "HelloWorld" OutFile "helloworld.exe" ShowInstDetails show RequestExecutionLevel User Section DetailPrint "Hello, world!" SectionEnd
Сначала пишем обязательную конструкцию Name
и придумываем имя установщика, тут, естественно, "HelloWorld"
. Имя может содержать пробелы, оно будет отображаться в заголовках окон и окнах инсталлятора, а также попадет в список программ в «Программы и компоненты», в случае реального установщика.
Далее идет обязательная конструкция OutFile
— файл установщика. Если его не прописать, то компилятор не будет знать под каким именем собрать программу установки и пошлет нас.
Следующим шагом (ShowInstDetails show
) развернем окно с логом установки, как это было описано в предыдущей копия заметке.
Теперь запрашиваем запуск из под пользователя с ограниченными правами (RequestExecutionLevel User
). Инсталляторы обычно запускаются с правами администратора, но в данном случае мы ничего не устанавливаем, и нажимать лишний раз кнопку в окошке UAC не нужно.
Далее необходимо завести хотя бы одну секцию. Если в скрипте не будет хотя бы одной секции — компилятор прервет работу. Организуем единственную секцию без названия.
Section [ТУТ БУДЕТ КОД] SectionEnd
На самом деле секции нужны для того, чтобы сделать возможным выбор компонентов устанавливаемой программы, полную или выборочную установку. Но об этом как-нибудь в другой раз.
Внутри секции пишем сообщение, выводящее заданный текст в окошко с логом (деталями установки):
DetailPrint "Hello, world!"
На самом деле выбора не так, чтобы много, но какой-никакой есть. На официальном сайте предлагают пользоваться Eclipse и плагином к нему, но у меня на Клипсу, wim и TeX стойкая аллергия еще со студенческих времен.
Есть плагин для Visual Studio, но написан он китайцами для китайцев, так что нафиг. Впрочем, может есть и нормальные плагины, но я не нашел. Сам пользуюсь пожилой средой Venis IX, там есть мастер для генерации простых установщиков, которого вполне хватает, чтоб постоянно не писать одно и то же, создавая новый инсталлятор.
Если ничего не делать, детали установки по умолчанию скрыты:
Чтобы лог установки сразу был виден пользователю, необходимо применить один из следующих методов:
1. В коде скрипта, до секций прописываем команду:
ShowInstDetails show
Окошко с логом (деталями установки) будет открыто
2. Прописать внутри секции команду:
SetDetailsView show
Это может быть полезно, например, если вы хотите, чтобы детали показывались и при удалении. В таком случае, вышеуказанная команда добавляется в начало секции, описывающей анинсталлер:
Section Uninstall SetDetailsView show [..] [..] SectionEnd
Крипяток
«Я от вашей истории крипятком писал!»
Делал, чтоб клиенту меньше ручками работать. Теперь не надо самому определять версию винды, и вытаскивать нужный devcon из архива соответственно.
Предыдущий я сделал на Inno Setup, но Inno Setup оказался той еще заразой, нихрена он версию Винды толком определить не мог, и тихой сапой подкладывал во все винды один и тот же devcon, который подходит для Windows 7 и выше. От чего у клиента с виндой XP x64 произошел адский баттхерт, так, что забрызгало пол-Петербурга, аж до моей деревни брызги долетели. Видимо, клиент меня проклял, потому что мне на ногу упал топор (слава Ктулху обухом), у меня упали форточки, точнее форточка, но стеклянная и на пол, ко мне какого-то черта приперлась лесная охрана и стала [РОСКОМНАДЗОР], и я после этого [РОСКОМНАДЗОР] в результате, теперь страдаю [МИНЗДРАВ].
Новый сделал на NSIS, но как оказалось — NSIS тоже [РОСКОМНАДЗОР], точнее, не сам NSIS, он мне как раз понравился, за исключением одного странного недокументированного глюка, о котором как-нибудь расскажу, и скрипт-язык, вполне себе такая помесь Бейсика с Башем. А вот документация, это, товарищи, лютый [РОСКОМНАДЗОР] в последней стадии.
Русский мануал к популярному инсталл-мэйкеру писали сто лет назад какие-то [ДАННЫЕ УДАЛЕНЫ] с OSZone.net, еще и назвали свое творение «справочником», хотя что-что а справочники так не делают. Просто плохо структурированные статьи, которые на [РОСКОМНАДЗОР] запихнули в chm-файл. [РОСКОМНАДЗОРКА], поучитесь у того же Исзелиона с wasm.ru, как нужно делать справочники и мануалы. На туториале Исзелиона сотня-другая студентов если не аспирантами стали, так свой зачет по ассемблеру точно получили. Аффтар еще и жалуется на форуме, типа, «ну на[РОСКОМНАДЗОР] обновлять мануал, если его никто не читает, и очевидные вопросы задает». Так [РОСКОМНАДЗОРКА], [РОСКОМНАДЗОРКА], ты так написал этот мануал, что кошка [РОСКОМНАДЗОРОМ] по клавиатуре лучше напишет. Но ладно, я много захотел, русского мануала. Да, согласен. Но теперь «поговорим о влажности в номере», точнее об оригинальной вики от разработчиков.
Оригинальная вики тоже [РОСКОМНАДЗОРНЫЙ], [РОСКОМНАДЗОР] твою мать, [РОСКОМНАДЗОР]. Причем, я вполне себе уверен, что там есть все описания функций языка NSIS, вот только отдельной категории для списка функций нет. Функции потом ищутся гуглем, который выводит на страницу-сироту с вполне нормальным описанием, но [РОСКОМНАДЗОР] знает, почему на эту страницу нельзя попасть из самой вики. В навигации [РОСКОМНАДЗОР] не валялся, в общем без стакана не разобраться. А еще пишут, что «хорошо документированный продукт». Документирован он может и хорошо, но найти в документации что-то конкретное, это как в ГОРФ пойти к чиновнику: «вы мне справку ЕПРСТ-1488 принесли, а надо было ЖПЧШЦ-666», и [РОСКОМНАДЗОР] знает где это написано.
Даже есть мысль как-нибудь выкачать эту вики себе на комп, сделать нормально, попытаться перевести и выпустить в виде справочника.
Впрочем, инсталлер сделал:
Скачать с Mega.nz
С GitHub
Исходник (файлы devcon_all.nsi и gvv.nsi)
И никакой конспирологии…
Тут некоторые задаются вопросом, что семь капитанов первого ранга искали на секретной подлодке в глубине северных морей. Есть совсем уж русофобские и конспирологические версии, что они хотели устроить всем суверенный Рунет, обрубив трансатлантический кабель.
Да конспирология это все, причем, довольно низкого пошиба. Чем у нас могут заниматься военные, да еще и в первых чинах, на дне, причем, проводя батиометрические исследования, т.е. исследования того самого дна.
Да рубль они на дне искали.
А почему у них бомбануло, ну, знаете ли, океанская кора тонкая, и куда там рубль провалится…
При установке Windows 7 на компьютер с USB 3.0 можно столкнуться с ошибкой «Не найден необходимый драйвер для дисковода оптических дисков.«, на самом деле, дисковод оптических дисков тут не при чем, особенно, если установка производится с загрузочной флэшки с дистрибутивом «семерки». В Windows 7 и его установочном окружении просто нет драйверов для контроллеров USB 3.0.
Самый простой вариант, когда в BIOS/UEFI удается переключить USB-контроллер в legacy-режим. Но на многих системах это самое legacy реализовано весьма коряво. Например, live-дистрибутивы Linux могут в таком режиме видеть и контроллер, и подключенные накопители, а вот установщик Windows 7 (и сама винда) нет.
На днях попался такой ноутбук, в котором примерно так и получалось, и вот, хочу рассказать об интересном способе это побороть.
Конечно, можно поступить стандартно — создать отдельный дистрибутив для такого компьютера, внедрив нужные драйвера, или же скачать какую-нибудь «колхозную» сборку. Но есть и другой способ — воспользоваться установочным окружением от Windows 8/8.1 в котором драйвера для USB 3.0 есть.
Минус способа — в установленной Windows 7 драйвера для USB 3.0 будут отсутствовать, как, наверняка, и драйвера от сетевой карты, и возникнет проблема, как их туда затолкать.
В источнике есть способ сделать это с помощью консоли восстановления с получившейся флэшки, у меня же получилось еще проще. Кривое ноутбучное legacy поддерживалось Linux’ом с System Rescue CD, так что на этом моменте я останавливаться не буду.
1. Образ установщика Windows 7
2. Образ установщика Windows 8/8.1
3. Флэшка 🙂
1. Закатываем на флэшку дистрибутив Windows 8/8.1, например, с помощью программы Rufus, особых подробностей я рассказывать не буду, но я сначала переключил UEFI ноута в режим Legacy BIOS (хоть он работал нормально и, главное, был), снес б-гмерзкое GPT, а потом установил в Rufus «Схема раздела и тип системного интерфейса» в значение «MBR для компьютеров с BIOS или UEFI«.
2. Итак, у нас получилась флэшка с Windows 8/8.1, переходим на нее, заходим в каталог sources
и удаляем оттуда файлы install.wim
и/или install.esd
.
3. Теперь из образа Windows 7 вытаскиваем файл install.wim
(он тоже лежит в подкаталоге sources
образа). Если у вас образ AIO, т.е. «все в одном», образ, из которого можно установить сразу несколько версий Windows, например, Starter, Home и Professional, то необходимо из образа Windows 7 вытащить файлы sources/*.clg
, например, install_Windows 7 Home Basic x64.clg
, install_Windows 7 Home Premium x64.clg
и т.д. Также можно попробовать скопировать папку $OEM$
, но не везде срабатывает, т.е. иногда конкретный дистрибутив может ее проигнорировать.
4. Теперь копируем все, что вытащили из дистрибутива Windows 7 в каталог sources на флэшке.
5. ФАНФАРЫ!
Загрузчик установщика Windows современных версий сначала загружает файл boot.wim
, который представляет из себя хитрый архив (виртуальный диск, наподобие initrd
в Linux), содержащий необходимые для процесса установки драйвера, основные файлы и саму программу-установщик. Далее окружение предустановки ищет дополнительные компоненты на диске с boot.wim
, в частности install.wim
, виртуальный диск с файлами операционной системы, которая должна быть установлена. Тут мы просто оставили предустановочное окружение, подсунув ему ОС другой версии.