PDA

Показать полную графическую версию : SFX Creator 4 Alpha - создаём SFX архивы


Страниц : 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

Iska
25-05-2011, 18:47
для начала, сделать хотя бы только утилитку для извлечения ProductCode из MSI файла »
MKN, попробуйте такое (без обработки ошибок, VBScript):
Option Explicit

Const msiOpenDatabaseModeReadOnly = 0

Dim strPath2MSIFile
Dim strProductCode


strPath2MSIFile = "C:\Program Files\Windows Installer 4.5 SDK\TOOLS\orca.msi"

With WScript.CreateObject("WindowsInstaller.Installer")
With .OpenDatabase(strPath2MSIFile, msiOpenDatabaseModeReadOnly)
With .OpenView("SELECT * FROM Property WHERE Property = 'ProductCode'")
.Execute()

With .Fetch()
strProductCode = .StringData(2)
WScript.Echo strProductCode
End With
End With
End With
End With

WScript.Quit 0

{4F34C602-4D6D-470D-A2A0-59E4F25DDBF2}

kotkovets
26-05-2011, 00:45
громоздко с помощью макроса опубликованного kotkovets и включенного в справочник »
есть пример куда проще определять:
OutFile "GetMSI.exe"

!define GetMSIProduct `!insertmacro _GetMSIProduct`
!macro _GetMSIProduct VAR ProductCode
System::Call 'msi::MsiQueryProductStateA(t "${ProductCode}") i.s'
Pop ${VAR}
!macroend

Section MSIProduct
${GetMSIProduct} $0 "{837b34e3-7c30-493c-8f6a-2b0f04e2912c}" ;на примере VC++ 2005 SP1
StrCmp $0 5 0 +2
MessageBox MB_ICONINFORMATION|MB_OK "$$0 = $0$\nЭтот продукт установлен!" IDOK
StrCmp $0 `-1` 0 +2
MessageBox MB_ICONINFORMATION|MB_OK "$$0 = $0$\nЭтот продукт не установлен!" IDOK
StrCmp $0 `-2` 0 +2
MessageBox MB_ICONINFORMATION|MB_OK "$$0 = $0$\nОшибка в ProductCode!" IDOK
SectionEnd
Это было бы действительно весьма полезно... (для начала, сделать хотя бы только утилитку для извлечения ProductCode из MSI файла) »
C этим соглашусь на 100%, даже лучше свою функцию написать и зашить внутрь SFX или виде библиотеки с базой основных кодов продуктов msi: Microsoft .NET Framework, Microsoft Visual C++, MSXML, Java(TM).

MKN
26-05-2011, 10:05
попробуйте такое (без обработки ошибок, VBScript) »
А нельзя ли организовать скрипт так, чтобы он обрабатывал находящийся рядом с ним .MSI файл ?
Чтобы не прописывать ничего в самом скрипте (иначе какая уж тут автоматизация...)

K.A.V.
26-05-2011, 10:26
WScript.Echo strProductCode »
я так понимаю, что здесь выскакивает MesssageBox? Было бы неплохо скидывать значение в файл в любой форме (либо значение в первой строке текстового файла, либо конструкцией INI файла)

MKN
26-05-2011, 18:16
Вот такой скрипт нашёл (экспортирует всё из Property в xls файл ... Но наверное какую то малость можно подправить для ProductCode :

' Export File Table from a given MSI Database to an Excel Spreadsheet

Option Explicit

Const msiOpenDatabaseModeReadOnly = 0


On Error Resume Next
Dim installer : Set installer = Nothing
Dim szMSI

szMSI = InputBox("Enter MSI File (including full path)", "Select MSI", "")
DIM folder : folder = InputBox("Enter Folder to Write Table to...", "Select Export Folder","")

Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError

Dim database : Set database = installer.OpenDatabase(szMSI, msiOpenDatabaseModeReadOnly) : CheckError

Dim table, view, record

table = "Property"

Set view = database.OpenView("SELECT 'Name' FROM _Tables")
view.Execute : CheckError
Do
Set record = view.Fetch : CheckError
If record Is Nothing Then Exit Do
Export table, folder : CheckError
Loop
Set view = Nothing


Export table, folder : CheckError


Wscript.Quit(0)

Sub Export(table, folder)
Dim file :file = table & ".xls"
database.Export table, folder, file
End Sub


Sub CheckError
Dim message, errRec
If Err = 0 Then Exit Sub
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
If Not installer Is Nothing Then
Set errRec = installer.LastErrorRecord
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
End If
Wscript.Echo message
Wscript.Quit 2
End Sub

Iska
26-05-2011, 19:53
Лирическое отступление.
Я пользую файловый менеджер «Far Manager», посему: я работаю с командной строкой Far Manager'а, у меня стандартным хостом WSH назначен консольный «cscript.exe» (вместо «wscript.exe»), я пользую полные пути к скриптам вместо того, чтобы плодить скрипты по папкам.

Так делаю я. У Вас, MKN, K.A.V., я понимаю, процесс работы организован несколько иначе. Скрипт из #141 (http://forum.oszone.net/post-1682466-141.html) я выложил, чтобы Вы могли оценить, работает ли вообще сие, и гож ли подобный подход для Вас. Стало быть, я попробую написать по Вашим предпочтениям, но Вы должны мне разъяснить, почему нужно именно так, а не иначе. Хорошо?

Насколько я понимаю, Far Manager'ом никто из Вас не пользуется (или он не является основным Вашим файловым менеджером), так?

Почему я сие хочу выяснить: дело в том, что в его командной строке очень легко, быстро и удобно указывать путь к WSH-скрипту, лежащему в папке A, как параметр скрипта — путь к некоему msi-файлу, лежащему в папке B, результат работы скрипта перенаправить в некий файл в папке C. Ну, а находиться (иметь текущим каталогом) при этом можно вообще некую папку D ;). Например:
cscript.exe "C:\Program Files\My Scripts\GetProductCodeFromMSI.vbs" "C:\Program Files\Windows Installer 4.5 SDK\TOOLS\orca.msi" 1>"E:\Песочница\0056\ProductCode.txt"
Или, например, просто получить «ProductCode» в редактор:
edit:< cscript.exe "C:\Program Files\My Scripts\GetProductCodeFromMSI.vbs" "C:\Program Files\Windows Installer 4.5 SDK\TOOLS\orca.msi"

Впрочем, сие есть моё видение, но буду признателен Вам, если Вы опишете, как работаете Вы, как предполагаете (и хотели бы) использовать скрипт в Вашей работе. Может быть, Вам нужно его вызывать из редактора, где Вы пишете скрипты NSIS. А пока…

А нельзя ли организовать скрипт так, чтобы он обрабатывал находящийся рядом с ним .MSI файл ? »
Можно. Например, так будут обрабатываться все MSI-файлы, находящиеся рядом с файлом скрипта:
Option Explicit

Const msiOpenDatabaseModeReadOnly = 0

Dim objFSO
Dim objFile

Dim strProductCode


Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

For Each objFile In objFSO.GetFolder(objFSO.GetParentFolderName(WScript.ScriptFullName)).Files
If UCase(objFSO.GetExtensionName(objFile.Name)) = UCase("msi") Then
With WScript.CreateObject("WindowsInstaller.Installer")
With .OpenDatabase(objFile.Path, msiOpenDatabaseModeReadOnly)
With .OpenView("SELECT * FROM Property WHERE Property = 'ProductCode'")
.Execute()

With .Fetch()
strProductCode = .StringData(2)
WScript.Echo strProductCode
End With
End With
End With
End With
End If
Next

WScript.Quit 0

я так понимаю, что здесь выскакивает MesssageBox? Было бы неплохо скидывать значение в файл в любой форме (либо значение в первой строке текстового файла, »
1. Использовать хост «cscript.exe» и перенаправлять вывод в нужный файл.
2. Прямой вывод в текстовый файл из скрипта. Вопрос — в какой именно: где задать его имя, где он будет находиться.

MKN
27-05-2011, 09:18
Iska,
Задача (в моём понимании) на данном частном отрезке "проекта SFX Creator" такова :

получить (экспортировать) из msi файла его ProductCode (и ещё ProductName), которые будут использоваться (записаны) в коде NSIS скрипта. Экспорт произвести в обыкновенный одноимённый txt файл. Например, в ProductCode.txt и ProductName.txt

О местонахождении : думаю, что лучшее местонахождение в процессе подготовки и работы, и msi файлов и результирующих файлов ProductCode.txt и ProductName.txt - это $TEMP. Но это для проекта.

Для работы же, предложенного тобой vbs скрипта, местонахождение и исходного *.msi и результирующего txt файлов - рядом со скриптом vbs.

PS DrWEB c ума сходит от этого скрипта и не даёт сохранять... Что делать ?

MKN
27-05-2011, 10:47
Если рассматривать эту часть проекта , как отдельную утилиту формирования NSIS кода для MSI установки, то происходить будет следующее :

Но сначала ещё немного лирики. :) На кой нам получать ещё и ProductName ? А на той, чтобы видеть над прогрессом установки не бестолковое мельтешение устанавливаемых файлов (или отсутствие оного), что обычно и наблюдаем по умолчанию, а видеть то, что конретно в данный момент устанавливается. Полученный ProductName и будем использовать в DetailPrint "Installing....

Следующий момент. Если с установкой одного msi пакета всё более-менее ясно, то как быть когда их придётся устанавливать несколько ?
Вот конкретный пример, когда я пересобирал отдельное приложение из гигантского пакета Adobe Creative Suite CS5 , для которого пришлось устанавливать аж 8 разных msi пакетов ! (Хотя по сути это были, расчленённые на отдельные дистрибутивы, составляющие их разных VC++... Но разрабам же виднее...)
Как быть с такими случаями в нашем случае ? Я бы предусмотрел в скрипте выбор для разных вариаций msi пакетов.
Например, для начала пусть присутствуют 9 чекбоксов для выбора. Тут есть нюансы, но про это позже...

Пакеты эти, надо предварительно подготовить, создав (для моего примера) 8 папок с именами 1...8, и в каждую из которых, поместить нужные msi дистпибутивы.

Т.е. , что получается :

Запускаем скомпилированный скрипт.

Отмечаем нужные для установки msi пакеты (msi1...msi8)

Отмеченные папки 1...8 с содержимым копируются в $TEMP. В каждую папку копируется файл vbs скрипта (чтобы не было путаницы).

Vbs скрипт начинает свою работу, создав в каждой папке ProductCode.txt и ProductName.txt.

Данные из ProductCode.txt и ProductName.txt заносятся в соответствующие переменные и записываются в код нового созданного файла msi.nsi. Где он будет создан, не критично. К примеру, в C:/myMSInsi

В этот файл msi.nsi записывается (пример на основе кода из справочника, наверное можно и иначе) :

!define MSIGETPRODUCTINFO '!insertmacro MsiGetProductInfo'
Var MSI_PRODUCT
!macro MsiGetProductInfo PRODUCTCODE PROPERTY
и т.д.

Section 1
SetOverwrite on
${MSIGETPRODUCTINFO} "{переменная для кода продукта 1 msi пакета)}" "ProductName"
и т.д.
SectionEnd


Сколько выбрано MSI пакетов для установки - столько запишется и секций.

Ну и в конце "подчищаем" за собой, удаляя не нужное.

Готовый код из файла msi.nsi используем для дальнейшей работы.

Моё сочинение наверняка спорно, потому прошу принять участие в "доводке" и совершенствовании...

kotkovets
27-05-2011, 13:24
MKN, а почему бы всю работу не поручить "бейсику" скрипту vbs - пущай код возврата (установлен - не установлен по коду продукта и пути) пишет в файлик, далее код возврата анализирует код NSIS. Есть мысль по этому поводу - сделать плагин к NSIS на досуге.
Примерно так:
1. Исполняемый файл *.exe который заводится препроцессором NSIS и этот файл *.exe (vbs скрипт) заинклудит массив номерков в код NSIS на этапе компиляции проекта
2. Далее плагин на этапе инсталяции обрабатывает массив номерков возвращает код возврата NSIS
3. Код NSIS анализирует полученные данные от плагина.

MKN
27-05-2011, 15:35
а почему бы всю работу не поручить "бейсику" скрипту vbs »
К сожалению я не владею волшебством бейсика... И сдаётся мне что от vbs скрипта придётся отказаться из-за реакции на него антивирусов (пусть и не всех...).
Пользователь не должен страдать из-за этого. Если конечно Iska чего нибудь в скрипте не подправит...
И возможно придётся сконвертить vbs в exe.
Скрипт должен без проблем автономно запускаться на машинах пользователей, у которых есть проблемы либо с скриптоассоциациями , либо чего то скриптовое не установлено или повреждено. Сплошь и рядом встречаю машины, где не возможно так просто запустить файлы VBS...

kotkovets
27-05-2011, 16:46
MKN, я имел еще виду исполняемый файл для этапа компиляции на с++ - тут придется попотеть), как дополнение к плагину, плагин определения установки msi сделаю после того, как свой плагин для работы с процессами закончу.
кстати еще один код определяющий, какие продукты msi установленные в системе, рядом файлик в формате ini появится.
Dim installer, productcode, text, fso

Set fso = CreateObject("Scripting.FileSystemObject")
Set text = fso.CreateTextFile("msi.ini", True)
Set installer = CreateObject("WindowsInstaller.Installer")

text.writeline ("[Products]")
For Each productcode In installer.products
text.writeline (installer.productinfo (productcode, "InstalledProductName") & " = " & productcode)
'text.writeline (installer.productinfo (productcode, "InstalledProductName") & " v(" & installer.productinfo (productcode,"VersionString") & ") = " & productcode)
Next

Iska
05-06-2011, 09:51
Экспорт произвести в обыкновенный одноимённый txt файл. Например, в ProductCode.txt и ProductName.txt »
Ясно.
Для работы же, предложенного тобой vbs скрипта, местонахождение и исходного *.msi и результирующего txt файлов - рядом со скриптом vbs. »
Результирующие файлы ложатся рядом с «*.msi» — хорошо. Рядом со скриптом — это мне не нравится. Не есть правильно иметь кучу дубликатов скрипта по разным папкам.

На кой нам получать ещё и ProductName ? »
Я хотел сразу и «ProductName» добавить в скрипт, но изначально такой вопрос не стоял — я и не стал делать сие.

Данные из ProductCode.txt и ProductName.txt заносятся в соответствующие переменные и записываются в код нового созданного файла msi.nsi. Где он будет создан, не критично. К примеру, в C:/myMSInsi
В этот файл msi.nsi записывается »
Можно сделать, но мне нужно чёткое пояснение куда писать полученные значения «ProductName» и «ProductCode». По приведённому примеру мне не ясно.

Можно и просто поместить полученные значения в буфер обмена в нужном формате.

Подход:
1. Исполняемый файл *.exe который заводится препроцессором NSIS и этот файл *.exe (vbs скрипт) заинклудит массив номерков в код NSIS на этапе компиляции проекта »
мне кажется более правильным. Кстати, а почему не просто *.vbs, безо всяких компиляций?

А в чём пишете NSIS-проекты? Скажем, редактор SciTE (http://ru.wikipedia.org/wiki/SciTE) умеет передавать выделенный текст запускаемой внешней программе, равно скрипту, как аргумент командной строки, и получать результат работы из её stdout, который затем может быть сразу вставлен в редактируемый текст.

PS DrWEB c ума сходит от этого скрипта и не даёт сохранять... Что делать ? »
Мне сложно что-либо сказать вразумительное по поводу столь неподобающего поведения DrWEB.

И сдаётся мне что от vbs скрипта придётся отказаться из-за реакции на него антивирусов (пусть и не всех...).
Пользователь не должен страдать из-за этого. Если конечно Iska чего нибудь в скрипте не подправит...
И возможно придётся сконвертить vbs в exe. »
Конвертация скрипта в исполняемый файл только усилит подозрительность антивирусов.

Скрипт должен без проблем автономно запускаться на машинах пользователей, у которых есть проблемы либо с скриптоассоциациями , либо чего то скриптовое не установлено или повреждено. Сплошь и рядом встречаю машины, где не возможно так просто запустить файлы VBS... »
«Сплошь и рядом» — не встречал такого.

В принципе, сбитые ассоциации легко обходятся прямым указанием исполняемого файла и пути к скрипту:
C:\WINDOWS\system32\wscript.exe "E:\Песочница\0057\GetProductCodeFromMSI.vbs"
или
C:\WINDOWS\system32\cscript.exe "E:\Песочница\0057\GetProductCodeFromMSI.vbs"
Не установлено — как такое может быть? Это ведь один из основных компонентов системы. Библиотеки, кроме того, входят в состав всех IE. Если повреждено — надо восстанавливать.

Очередное приближение:
Option Explicit

Const msiOpenDatabaseModeReadOnly = 0


Dim strArg
Dim strProperties
Dim strAllValues

Dim objDatabase


If WScript.Arguments.Count <> 0 Then
strAllValues = ""

For Each strArg In WScript.Arguments
With WScript.CreateObject("Scripting.FileSystemObject")
If .FileExists(strArg) Then
If UCase(.GetExtensionName(strArg)) = UCase("msi") Then
Set objDatabase = WScript.CreateObject("WindowsInstaller.Installer").OpenDatabase(strArg, msiOpenDatabaseModeReadOnly)

strProperties = GetMSIProperty(objDatabase, "ProductName") & vbCrLf
strProperties = strProperties & GetMSIProperty(objDatabase, "ProductVersion") & vbCrLf
strProperties = strProperties & GetMSIProperty(objDatabase, "ProductCode") & vbCrLf

With .CreateTextFile(.BuildPath(.GetParentFolderName(strArg), .GetBaseName(strArg) & ".MSIProperties.txt"), True, True)
.Write strProperties
.Close
End With

strAllValues = strAllValues & strProperties & vbCrLf

Set objDatabase = Nothing
Else
WScript.Echo "File [" & strArg & "] in not a MSI file."
End If
Else
WScript.Echo "File [" & strArg & "] not found."
End If
End With
Next

Copy2Clipboard strAllValues
Else
WScript.Echo "Usage: " & WScript.ScriptName & " <msi file 1> <msi file2> … <msi file N>"
End If

WScript.Quit 0
'=============================================================================

'=============================================================================
Function GetMSIProperty(objDatabase, strProperty)
With objDatabase.OpenView("SELECT * FROM Property WHERE Property = '" & strProperty & "'")
.Execute()

With .Fetch()
GetMSIProperty = .StringData(1) & ":" & .StringData(2)
End With

.Close
End With
End Function
'=============================================================================

'=============================================================================
Sub Copy2Clipboard(strValue)
With WScript.CreateObject("InternetExplorer.Application")
.Navigate("about:blank")

.document.parentWindow.clipboardData.setData "text", strValue
.Quit
End With
End Sub
'=============================================================================

Скрипт принимает msi-файлы аргументами командной строки. Можно, например, создать ярлык к скрипту и бросать на него msi-файлы. В папке рядом с каждым msi-файлом будут созданы одноимённые им текстовые файлы по принципу «<Имя msi-файла>.MSIProperties.txt». В число извлекаемых свойств я включил имя пакета — «ProductName», версию — «ProductVersion» и «ProductCode». Помимо того данная информация будет помещена в буфер обмена (будет ли последнее работать с версиями IE > 6 — не знаю) в виде, наподобие:
ProductName:MsiVal2
ProductVersion:4.0.6001.000
ProductCode:{CC14CF6A-7D60-413A-934C-3150D422DA6D}

ProductName:Orca
ProductVersion:4.0.6001.0000
ProductCode:{4F34C602-4D6D-470D-A2A0-59E4F25DDBF2}

ProductName:Norton AntiVirus Help
ProductVersion:15.0
ProductCode:{E3EFA461-EB83-4C3B-9C47-2C1D58A01555}

kotkovets
12-06-2011, 11:21
А в чём пишете NSIS-проекты? »
не поверите, часто всего приходится (в силу разных причин) обычным блокнотом или Notepad ++
попробывал SciTE - понравилось...
и плагин для msi уже написал для NSIS относительно недавно:
http://forum.oszone.net/showpost.php?p=1684697

Iska
18-06-2011, 05:36
Спасибо, ясно.

и плагин для msi уже написал для NSIS относительно недавно: »
Поскольку я имею слабое представление, хочу уточнить, правильно ли я понял: написанный Вами плагин предназначен для работы изнутри самой инсталляции, непосредственно в процессе установки, а не для сборки самой инсталляции, так?

kotkovets
18-06-2011, 21:32
а не для сборки самой инсталляции, так? »
да, все верно, даже можно обойтись без сборки самой инсталляции, т.е имеем некий msi продукт в проекте NSIS - в процессе распаковки продукта во временную папку проверяем плагином на предмет нужных задач. Единственный недостаток - пакет msi всегда нужно распаковывать.

Iska
18-06-2011, 21:53
kotkovets, благодарствую за разъяснение.

K.A.V.
30-07-2011, 19:05
Хотелось бы вспомнить вопрос (http://forum.oszone.net/post-1677668.html#post1677668), который я так и не решил, насчет разброса команд по компонентам

Обращаюсь к вам, MKN, т.к. проект кроме вас больше никто не обсуждает, и идеи новые приносите только вы, такое ощущение, что программу только для вас пишу :lol:

Вообщем хочу продолжить разработку программы, т.к. ну просто не могу я вот так смотреть на своё творение, как оно "умирает", хотя на него я потратил очень много времени и сил =)

Будем навёрстывать упущенное :beta:

MKN
30-07-2011, 21:12
K.A.V.,
Думаю, что не один я горячо приветствую любые твои реализации в улучшении и расширении функционала SFX Creator_а.
Другие заинтересованные пользователи NSIS наверное просто молча одобряют твои действия и собираются с мыслями... :)
так и не решил, насчет разброса команд по компонентам »
Это о чём мы говорили... Два месяца уж прошло. О вариантах определения установленного ПО ? Вроде как к уже вышесказанному добавить нечего. Нет, есть чего - добавить в SFX Creator использование замечательного плагина getmsi от kotkovets, для определения установленных MSI пакетов.

Оч. полезно было бы добавить инструментарий для организации ассоциаций файлов.

И есссно дополнить программу необходимыми функциями, как то : выбор устанавливаемых компонентов, работа в x64 ОС, определение типа ОС, выбор различных переменных для разных типов ОС, работа с процессами, с службами, с "сетевыми делами"... Поле дополнений и расширений, не пахано и обширно до бесконечности...

ps А также, на перспективу, возобновить реализацию идеи - при создании инсталлятора предусмотреть создание отдельного пользовательского дистрибутива из выбранных компонентов. Эту идею уже успешно реализовал kotkovets (правда для конкретного ПО). На мой дилетансткий взгляд, реализовал сложновато и не универсально... Наверное, если kotkovets присоединиться к доработке проекта SFX Creator_а, то будет боольшая польза.

А также, очень интересна идея, по упрощению создания различных кастомных страниц с выбираемым набором функций управления.
Типа, как реализовано в NSIS Dialog Designer http://coolsoft.altervista.org/en/nsisdialogdesigner , но лучше... :)

FreshMen85
31-07-2011, 10:21
т.к. проект кроме вас больше никто не обсуждает »
Ну я как бы перестал в эту тему заглядывать, потому что вы как-то писали что ушли служить, вот собственно я и подумал что проект скорей всего загнется, в основном после армии у людей резко меняется мировосприятие, ну а что собственно тогда мне и начинать то было знакомство с вашей программой если до логичного конца я не расчитывал что дело дойдет. Ну теперь вижу вашу четкую позицию по отношению к программе, поэтому буду заходить в эту тему почаще, ну и собственно как-то всё таки вливаться в дискуссию (разбавлять ваш с MKM дует).

HiddeN_Ra
03-08-2011, 01:04
Доброго дня уважаемое сообщество.
Скажите пожалуйста как мне прописать команду в SFX Creator'е,
Как мне прописать, чтоб перед установкой файла сделать проверку запущен он или нет и если он уже исполнятся, пропустить его установку и запуск.
Предполагаю, что делается через if exist. Подскажите как правильно прописать




© OSzone.net 2001-2012