Sign in to follow this  
Followers 0
cherdeg

Unattended Software Installer, my way...

20 posts in this topic

#1 ·  Posted (edited)

This tool installs most Windows tools automatically, you only have to keep them in a specified directory structure (to avoid duplicates you could use hard links) and find out which parameters are needed by each software to install silently and unattended. I'm very sure there is much room for optimization, but today I was so keen to find out my AutoIt skills improved insofar as I was able to reduce my software installation (crap)code from 350 to about 20 lines that I decided to let you take part in this great tool ("ahem..." :P ). So here it is:

;####################################################################
;#
;#  Christoph Herdeg, March 2009
;#  http://www.cs-it-solutions.de
;#
;####################################################################

#include <Array.au3>


$s_OSver = @OSVersion
$i_OSbits = _OSBits()
$s_LineBreak = @CRLF
$s_IniFileName = "U-S-I.ini"
If FileExists($s_IniFileName) = 0 Then 
    MsgBox(64, "cs/IT Unattended Software Installer", "The INI-File is missing...", 5)
    Exit
EndIf
$a_IniSoftware = IniReadSection($s_IniFileName, "SOFTWARE")
_ArrayDelete($a_IniSoftware, 0)


_InstallSoftware($a_IniSoftware)


; Install software
; ==================================================================================================
Func _InstallSoftware($a_IniSoftware)
    
    $s_SoftwareShare = $a_IniSoftware[0][1]
    _ArrayDelete($a_IniSoftware, 0)
    $a_TempSoftware = $a_IniSoftware
    Local $s_CMD, $i_PID
    For $i_i=0 to UBound($a_IniSoftware) -1 Step +2
        If StringInStr($a_TempSoftware[$i_i][1], "OS_Version") > 0 Then $a_TempSoftware[$i_i][1] = StringReplace($a_TempSoftware[$i_i][1], "OS_Version", $s_OSver)
        If StringInStr($a_TempSoftware[$i_i][1], "OS_Bits") > 0 Then $a_TempSoftware[$i_i][1] = StringReplace($a_TempSoftware[$i_i][1], "OS_Bits", $i_OSbits)
        $s_File = $s_SoftwareShare & "\" & $a_TempSoftware[$i_i][1]
        If FileExists($s_File) Then
            If StringInStr($s_File, ".msi") Then
                $s_CMD = "msiexec /i " & $s_SoftwareShare & "\" & $a_TempSoftware[$i_i][1] & " " & $a_TempSoftware[$i_i +1][1]
            Else
                $s_CMD = $s_SoftwareShare & "\" & $a_TempSoftware[$i_i][1] & " " & $a_TempSoftware[$i_i +1][1]
            EndIf
            $i_PID = RunWait($s_CMD, "", @SW_HIDE)
            ProcessWaitClose($i_PID)
        Else
            MsgBox(64, "cs/IT Unattended Software Installer", "There is no file: " & $s_LineBreak & $s_LineBreak & $s_CMD & $s_LineBreak & $s_LineBreak & "Probably there is no version for " & $s_OSver & ", x" & $i_OSbits, 5)
        EndIf
    Next
    
EndFunc   ;==>_InstallSoftware

; Function _OSBits()
; ==============================================================================================
Func _OSBits()
    Local $tOS = DllStructCreate("char[256]")
    Local $aGSWD = DllCall("Kernel32.dll", "int", "GetSystemWow64Directory", "ptr", DllStructGetPtr($tOS), "int", 256)
    If IsArray($aGSWD) And DllStructGetData($tOS, 1) Then Return 64
    Return 32
EndFunc   ;==>_OSBits

And of course you will also need the INI-File ("U-S-I.ini"):

CODE
[sOFTWARE]

;#####################################################################

;#

;# SOFTWARE Settings Section

;#

;#####################################################################

;#

;# The parameter "SoftwareShare" has as value the UNC-Name of the share

;# where all software packages to be installed by this program reside in,

;# e.g. "\\Server\Share\Directory".

;#

;# If you move the contents of this share to another location, please

;# keep the existing directory structure (means: Do only move the whole

;# directory with all content).

;#

;# A software package is defined by two parameters. The "App_N_File"-para-

;# meter contains the name of the application to install and as value its

;# filename, the "App_N_Para"-parameter contains as value the commandline

;# options to setup the application unattended. If the respective appli-

;# cation installer doesn't need options, leave the "App_N_Para"-parameter

;# empty.

;#

;# If there are different versions of one application for several OS'ses,

;# they have to be put in a directory structure like:

;#

;# "Application-Name\OS_Version\OS_Bits\installer-filename"

;#

;# E.g. for the 64bit Version of some ominous "Mozilla Thunderbird for

;# Windows Vista" the "App_N_File"-parameter would have the value:

;#

;# "Thunderbird\OS_Version\OS_Bits\thunderbird-installer.exe"

;#

;# The file would have to reside at the following directory:

;#

;# "\\condor\postinstall\postinstall\StandardSW\Thunderbird\WIN_VISTA\64\thunderbird-installer.exe"

;#

;# You can define as many Software packages as you want; the number is

;# covered by reading the whole section, not only singe parameters. If a

;# software is available only as a Microsoft Installer package (.msi),

;# the utility recognizes it and does the installation via "msiexec /i".

;#

;# One flaw is that the installer-filename has to be the same for each

;# version of an application. Of course you could define, e.g. the VISTA-

;# and the XP-Versions as seperate packages...but that would be boring.

;#

;#####################################################################

SoftwareShare=\\condor\postinstall\postinstall\StandardSW

; Cygwin/SSH

App_0_File=Cygwin\Cygwin20080601-32x64.exe

App_0_Para=

; NagiosAgent

App_1_File=Nagios\NagiosInstaller.exe

App_1_Para=

; Adobe Acobat Reader

App_2_File=Acrobat\OS_Version\Acrobat.exe

App_2_Para=/sALL /rs /rps

; Symantec AntiVirus

App_3_File=Symantec\OS_Version\OS_Bits\setup.exe

App_3_Para=/S /v/qn

; Famatech Remote Admin

App_4_File=RAdmin\OS_Version\rserv30.exe

App_4_Para=/S /v/qn

; Microsoft SupportTools

App_5_File=SupportTools\OS_Version\suptools.msi

App_5_Para=/qn

It would be great to hear some opinions about this from you (please don't shout, please!).

Best Regards,

Chris

Edited by cherdeg

Share this post


Link to post
Share on other sites



Looks neat,

I didn't try it yet but I will as soon as I have something to install.

Thanks for sharing

Greencan


Contributions

CheckUpdate - SelfUpdating script ------- Self updating script

Dynamic input validation ------------------- Use a Input masks can make your life easier and Validation can be as simple

MsgBox with CountDown ------------------- MsgBox with visual countdown

Display Multiline text cells in ListView ---- Example of pop-up or ToolTip for multiline text items in ListView

Presentation Manager ---------------------- Program to display and refresh different Border-less GUI's on a Display (large screen TV)

USB Drive Tools ------------------------------ Tool to help you with your USB drive management

Input Period udf ------------------------------ GUI for a period input

Excel ColorPicker ---------------------------- Color pickup tool will allow you to select a color from the standard Excel color palette

Excel Chart UDF ----------------------------- Collaboration project with water 

GetDateInString ------------------------------ Find date/time in a string using a date format notation like DD Mon YYYY hh:mm

TaskListAllDetailed --------------------------- List All Scheduled Tasks

Computer Info --------------------------------- A collection of information for helpdesk

Shared memory Demo ----------------------- Demo: Two applications communicate with each other through means of a memory share (using Nomad function, 32bit only)

Universal Date Format Conversion -------- Universal date converter from your PC local date format to any format

Disable Windows DetailsPane -------------- Disable Windows Explorer Details Pane

Oracle SQL Report Generator -------------  Oracle Report generator using SQL

SQLite Report Generator -------------------  SQLite Report generator using SQL

SQLite ListView and BLOB demo ---------- Demo: shows how binary (image) objects can be recognized natively in a database BLOB field

DSN-Less Database connection demo --- Demo: ActiveX Data Objects DSN-Less Database access

Animated animals ----------------------------- Fun: Moving animated objects

Perforated image in GUI --------------------- Fun: Perforate your image with image objects

UEZ's Perforator major update ------------- Fun: Pro version of Perforator by UEZ

Visual Crop Tool (GUI) ----------------------- Easy to use Visual Image Crop tool

Visual Image effect (GUI) -------------------- Visually apply effects on an image

 

 

 

Share this post


Link to post
Share on other sites

looks pretty interesting

Share this post


Link to post
Share on other sites

@cherdeg

Nice, But this can be done in 6 lines as well.

Const $ALL_USERS = True 

$strComputer = "atl-dc-02"

$strSoftware = "Cygwin\Cygwin20080601-32x64.exe"

$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$objSoftware = $objWMIService.Get("Win32_Product")
$objSoftware.Install($strSoftware,Default,$ALL_USERS)

Hope this can get you going.

Regards,

ptrex

Share this post


Link to post
Share on other sites

@cherdeg

Nice, But this can be done in 6 lines as well.

Hope this can get you going.

Regards,

ptrex

Hey ptrex,

...yeah, maybe your 6 lines are able to start an installer (great!), but you would still have to click through all the installer dialogues. Which, btw., was the main reason for me to use a few lines more than RunWait(installer.exe). Apart from this my function is able to automatically install the right version of an application for each host (currently there are 12 different supported Microsoft OS'ses 'round here: WNT32, WNT64, W2K32, W2K64, WXP32, WXP64, W2K332, W2K364, WVISTA32, WVISTA64, W2K832, W2K864, not counting the ia64 versions due to irrelevance in numbers and Windows 7 due to its beta stage), using nothing more than two values within an INI-file and a predefined directory structure to contain the installer packages. If you want to urge ppl using WMI, you should present some...hmm...more interesting examples. Cool in this one is WMI's ability to be used on remote hosts (which is not relevant for my situation). Last comment: your method is not available on NT (which is relevant for my situation).

Regards,

Chris

Share this post


Link to post
Share on other sites

Looks interesting. However, "unattended" and "MsgBox" don't mix in my head. Perhaps it would be good to:

[1] Create a log file instead of using message boxes

[2] Allow configuration of what should happen if an installation process fails (end all, continue etc.)

[3] Allow configuration of dependencies between applications

[4] Provide a mechanism which determines whether an installation was successful (checking registry/file versions etc.)

[5] In conjunction with [4], perhaps something that determines whether it's already installed

That way, this could become a bootstrapper. Perhaps it could have a GUI on the front end so you can walk away and come back to see the log on-screen.

Random thoughts

WBD

Share this post


Link to post
Share on other sites

Looks interesting. However, "unattended" and "MsgBox" don't mix in my head. Perhaps it would be good to:

[1] Create a log file instead of using message boxes

[2] Allow configuration of what should happen if an installation process fails (end all, continue etc.)

[3] Allow configuration of dependencies between applications

[4] Provide a mechanism which determines whether an installation was successful (checking registry/file versions etc.)

[5] In conjunction with [4], perhaps something that determines whether it's already installed

That way, this could become a bootstrapper. Perhaps it could have a GUI on the front end so you can walk away and come back to see the log on-screen.

Random thoughts

WBD

To address your points:

I added a timeout to the both MsgBox'es (which btw. state only missing files, if your usage is correct, you would never see them).

[1]: If you like a log file function, feel free to add one.

[2] to [5]: see my comment for [1] and adjust the sentence to match your actual demand

It seems I need to talk about the goal the above lines of code need to reach for me: they are part of a much larger utility (~12000 lines of code) which is used to implement the system configuration and security policy of my current contractee on about 1500 single server systems. My goal is not and will never be to write an application to do unattended software installation with all features a professional tool would need to have. The installer function above installs the (even partly customized) software packages to a fresh windows system. There will never be any errors be be logged. If there are errors, there is a hardware problem or a general incompatibility of the actual OS to the respective system. This is a replacement for [a] connecting to a network share, browsing to the right directory, [c] starting a installer and [d] clicking 20 times. Nothing else. It could become part or core of something else, definitely. But I neither have the time nor the interest in developing that.

Best Regards, Chris

p.s.: you can walk away while it's working.

Share this post


Link to post
Share on other sites

It would be great to hear some opinions about this from you (please don't shout, please!).

Duly given. However:

[1]: If you like a log file function, feel free to add one.

[2] to [5]: see my comment for [1] and adjust the sentence to match your actual demand

Ok. I get the message. Did you only want agreeable opinion? I was trying to suggest improvements which could make this in to a broader application which could be useful in other scenarios. I was thinking about something like this but I guess it's not something you're interested in. No matter.

p.s.: you can walk away while it's working.

But then you'd miss the message boxes! :P

WBD

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

@cherdeg

Nice, But this can be done in 6 lines as well.

Const $ALL_USERS = True 

$strComputer = "atl-dc-02"

$strSoftware = "Cygwin\Cygwin20080601-32x64.exe"

$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$objSoftware = $objWMIService.Get("Win32_Product")
$objSoftware.Install($strSoftware,Default,$ALL_USERS)

Hope this can get you going.

Regards,

ptrex

This is very pertinent to what I'm doing right now. Awesome! I'm not understanding the path though, I think (as the code isn't working for me). I tried a hard path and that doesn't seem to work. You seem to use a relative path, but relative to what?

edit: nevermind. After reading, it seems that any command run will not have network access. CRAP, back to psexec...

Edited by fly

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

@cherdeg

In order to avoid the GUI to pop up.

You need to use the commandline switches that are available. Like "/Quiet" etc ...

See here for more info. Win_Product How To

Regards,

ptrex

@ptrex

Really? Come on, that's unbelievably marvellous!

Hey PT, I would never dare to criticize an expert like you anyhow, but did you give my code just a little look at all? I know how to use an msi-packaged installer quietly. To cite from my 1st posting, from the part of the INI-file:

CODE
; Adobe Acobat Reader

App_2_File=Acrobat\OS_Version\Acrobat.exe

App_2_Para=/sALL /rs /rps

Now what would you think "/sALL /rs /rps" means? Above all...the cygWIN-package you used in your example is custom made (as there usually is no way to install cygWIN unattended) and does not need any parameters to install completely quiet (which of course you could not know). Never the less...

@WideBoyDixon

I probably was unclear in my 1st posting about the fact that the "tool" already does what it is supposed to and therefore from my point of view is no subject of enhancement. What I meant when I called for your opinion was your opinion about the code itself. I don't need any tips how to do the same by WMI (although that posting is missing almost everything my code does), and I don't need suggestions how to enhance the thing. I was up to comment like "Hey, better use a While...Wend-construct, safer to use" or "If you Switch...Case...EndSwitch instead of If, the code will become more readable" or "better read from the INI-file like this"...

@fly

What is your goal? An AutoIt replacement for psexec using WMI to remotely install applications? This definition of task would be no problem at all. Using UNC-paths for the sources of your applications is definitely possible, if you 1st authenticate at the target host and 2nd authenticate the target host against the filer containing the installers. And next, ptrex' code was meant only for local use on the host a software is to be installed. As I understand you, you will have 1) one host containing the installer-files, 2) one host to control all the installations from and 3) a number "n" of hosts to receive the installations. Right? If you need something like that, I could do it for you. You can also get information here: http://msdn.microsoft.com/en-us/library/aa389288(VS.85).aspx

Regards,

Chris

Edited by cherdeg

Share this post


Link to post
Share on other sites

@fly

What is your goal? An AutoIt replacement for psexec using WMI to remotely install applications? This definition of task would be no problem at all. Using UNC-paths for the sources of your applications is definitely possible, if you 1st authenticate at the target host and 2nd authenticate the target host against the filer containing the installers. And next, ptrex' code was meant only for local use on the host a software is to be installed. As I understand you, you will have 1) one host containing the installer-files, 2) one host to control all the installations from and 3) a number "n" of hosts to receive the installations. Right? If you need something like that, I could do it for you. You can also get information here: http://msdn.microsoft.com/en-us/library/aa389288(VS.85).aspx

Regards,

Chris

Yeah, I've had some problems with psexec and AV software. I happened to catch that WMI can spawn remote processes and started to look around. Basically what I have is a server with a ton of silent installs on it (all are run by kicking off a specific batch file). From my computer, I need to be able to force client PCs to run these batch files off the server.

I read the link you posted but have a couple of problems. One, I don't really understand how to make WMI work in AutoIt, but I'm working on that. Two, the link mentions I need to make some AD changes for this to work, which is probably much more work than using psexec.

Suggestions? And if I should start another thread, please let me know. It really wasn't my intention to hijack this thread.

Share this post


Link to post
Share on other sites

@all

ptrex' code was meant only for local use on the host a software is to be installed.

Not correct. My example is for REMOTE installation.

$strComputer = "Computer_01"
$strInstall = "\\Server01\Apps$\SolidWorks\eDrawings 2009\eDrawings.msi"

Const $ALL_USERS = True 
$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
$objSoftware = $objWMIService.Get("Win32_Product")
$Error = $objSoftware.Admin($strInstall,Default,$ALL_USERS) ; Put in your install parameters here.

ConsoleWrite("Installed !! "  & $Error & @CRLF)
ConsoleWrite(@CRLF)

The only problems you might run into is that you are playing with NON .MSI files

regards

ptrex

Share this post


Link to post
Share on other sites

Not correct. My example is for REMOTE installation.

@ptrex

Yeah, you can see that so if you want. But, and again, not meant as an offense, it will only work if you have the same account authenticated on all involved machines. If not, you'd need to use the .ConnectServer-method:

$o_SWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
$o_WMIService = $o_SWbemLocator.ConnectServer($s_ComputerName, "root\CIMV2", $s_AdminUser, $s_AdminLocPW)

@fly

Let the both of us get a nice and restful weekend; next week I'll try to help you out regarding your problem...

Regards, Chris

Share this post


Link to post
Share on other sites

@ptrex

Yeah, you can see that so if you want. But, and again, not meant as an offense, it will only work if you have the same account authenticated on all involved machines. If not, you'd need to use the .ConnectServer-method:

$o_SWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
$o_WMIService = $o_SWbemLocator.ConnectServer($s_ComputerName, "root\CIMV2", $s_AdminUser, $s_AdminLocPW)

@fly

Let the both of us get a nice and restful weekend; next week I'll try to help you out regarding your problem...

Regards, Chris

Thanks. I'll do some more poking around and try to get my little head around this...

Share this post


Link to post
Share on other sites

@fly

Let the both of us get a nice and restful weekend; next week I'll try to help you out regarding your problem...

Regards, Chris

Any more thoughts on this? I'm thoroughly confused at this point.

Share this post


Link to post
Share on other sites

Any more thoughts on this? I'm thoroughly confused at this point.

Hi!

Sorry - tooo many meetings today...but in the meantime:

Regards,

Chris

Share this post


Link to post
Share on other sites

Is changing the computer account the only way to do this with WMI? I doubt I'm going to be able to justify that when I *could* use psexec...

Share this post


Link to post
Share on other sites

Is changing the computer account the only way to do this with WMI? I doubt I'm going to be able to justify that when I *could* use psexec...

If you want to use a tool on your machine to make many clients install software from a file server, this server has to be trusted for delegation. There is no other way. BTW: you don't "change" the computer account, you only set a check.

Share this post


Link to post
Share on other sites

If you want to use a tool on your machine to make many clients install software from a file server, this server has to be trusted for delegation. There is no other way. BTW: you don't "change" the computer account, you only set a check.

I know, but any change I do has to go through change management. I LOVE WORKING FOR BIG COMPANIES! Thanks for your replies, but I think I'll have to stick with psexec for now.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0