jwseek Posted May 5, 2009 Share Posted May 5, 2009 So I've been working on this script today to install a number of programs on a new Windows install. Basically, I'd like to be able to keep track of some files on a server and simply run this script to install all of them with no interaction. The catch is, I'm trying to avoid using the macro and interaction tools in auto-it. The reason behind that is it allows me to add programs to the script without rewriting it if I can find an unattended command line switch for them. I simply add them to an .ini file that the program reads and run through the array in that particular section with IniReadSection().So the problem is, some of the programs don't run and install properly. I've tested each of the programs that I'm currently trying to install, and they all succeed individually but they won't install if run in the program...[Global] ServerName=server InstallFolder=install PatchesFolder=patches InstallDrive=V: PatchesDrive=Y: [Patches] .NET Framework 1.1=dotnetfx11.exe /q ;.NET Framework 1.1 Service Pack 1=Service Packs\dotnet11sp1.exe /q .NET Framework 3.5=dotnetfx35.exe /passive /norestart Visual C++ Redistributable 2005=vcredist_x86.exe /q Windows Media Player 11=wmp11-windowsxp-x86-enu.exe /q [Installs] 7zip=7zip.msi /passive Firefox=Freeware\Firefox.msi /passive Internet Explorer Flash Plugin=flash-ie.exe /S Mozilla Flash Plugin=flash-mozilla.exe /S Sun Java=java.exe /passive Adobe Acrobat Reader=Productivity\AdbeRdr.msi /passive ;HTMLSlideshow=HTMLSlideShowSetup.exe ;Synctoy=SyncToySetupPackage.exe ;TweakUI=TweakUiPowertoySetup.exe ;Image Resizer Powertoy=ImageResizerPowertoySetup.exe /S /v /qn ;Slideshow Powertoy=SlideshowPowertoySetup.exe /S /v /qnSo am I doing something wrong? Is this an issue more with msiexec than with AutoIT? What would you guys do?AutoInstaller.au3 Link to comment Share on other sites More sharing options...
Authenticity Posted May 5, 2009 Share Posted May 5, 2009 I think this: Func LoadINIFile() ;determine whether the sections with in the ini file are correct for this particular ini load $iniSectionList = IniReadSectionNames($iniFile) If $iniSectionList[0] = $iniSections And $iniSectionList[1] = "Global" Then $loadINI = MsgBox(1, "Loading INI File...", "This will change all initialized data (including networking data)", 3) $serverName = "\\" & IniRead($iniFile, "Global", "ServerName", "") $installFolder = $serverName & IniRead($iniFile, "Global", "InstallFolder", "") $patchesFolder = $serverName & IniRead($iniFile, "Global", "PatchesFolder", "") $installDrive = IniRead($iniFile, "Global", "InstallDrive", "Z:\") $patchesDrive = IniRead($iniFile, "Global", "patchesDrive", "Y:\") $patchesSetup = IniReadSection($iniFile, "Patches") $installSetup = IniReadSection($iniFile, "Installs") Else MsgBox(48, "Invalid Program INI File", "The file you selected does not contain the proper formatting for loading as an INI file") EndIf EndFunc ;==>LoadINIFileoÝ÷ ÚÈhºW[z·°®+mzv¬jëh×6Func LoadINIFile() ;determine whether the sections with in the ini file are correct for this particular ini load $iniSectionList = IniReadSectionNames($iniFile) If $iniSectionList[0] = $iniSections And $iniSectionList[1] = "Global" Then $loadINI = MsgBox(1, "Loading INI File...", "This will change all initialized data (including networking data)", 3) $serverName = "\\" & IniRead($iniFile, "Global", "ServerName", "") $installFolder = $serverName & "\" & IniRead($iniFile, "Global", "InstallFolder", "") $patchesFolder = $serverName & "\" & IniRead($iniFile, "Global", "PatchesFolder", "") $installDrive = IniRead($iniFile, "Global", "InstallDrive", "Z:") $patchesDrive = IniRead($iniFile, "Global", "patchesDrive", "Y:") $patchesSetup = IniReadSection($iniFile, "Patches") $installSetup = IniReadSection($iniFile, "Installs") Else MsgBox(48, "Invalid Program INI File", "The file you selected does not contain the proper formatting for loading as an INI file") EndIf EndFunc ;==>LoadINIFile Don't know if it has anything to do with the problem... Link to comment Share on other sites More sharing options...
bo8ster Posted May 5, 2009 Share Posted May 5, 2009 I would suggest adding some scaffolding to nail down your problem. ConsoleWrite or debug messages are good. Below is taken from the FAQs. Func dbg($msg) DllCall("kernel32.dll", "none", "OutputDebugString", "str", $msg) EndFunc Very hard to fix if you don't know where it is broken. Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic] Link to comment Share on other sites More sharing options...
jwseek Posted May 6, 2009 Author Share Posted May 6, 2009 First off, thanks to Authenticity for pointing out some bits I missed in the ini load function. I loaded the default ini at startup, and since I wasn't deviating from that behaviour (even though I might need to in the future), I didn't notice the mistakes. Unfortunately... So I want to reiterate that this problem is with the installation of programs through AutoIt. Installing these programs one at a time with these switches results in a successful install. Installing these programs with the following loops causes some of the programs to fail: For $i = 1 To $patchesSetup[0][0] ProgressSet($i, "Installing " & $patchesSetup[$i][0]) $PID = Run($patchesFolder & '\' & $patchesSetup[$i][1], $patchesFolder) ProcessWaitClose($PID) Next ProgressSet(33, "Copying install folder to " & $copyLocation) DirCopy($installFolder, $copyLocation, 1) ProgressSet(66, "Installing Software...") For $i = 1 To $installSetup[0][0] ProgressSet(33 + $i, "Installing " & $installSetup[$i][0]) $PID = Run($installFolder & '\' & $installSetup[$i][1], $installFolder) ProcessWaitClose($PID) Next When I'm using this ini file to define what should be installed: [Global] ServerName=server InstallFolder=install PatchesFolder=patches InstallDrive=V: PatchesDrive=Y: [Patches] .NET Framework 1.1=dotnetfx11.exe /q ;.NET Framework 1.1 Service Pack 1=Service Packs\dotnet11sp1.exe /q .NET Framework 3.5=dotnetfx35.exe /passive /norestart Visual C++ Redistributable 2005=vcredist_x86.exe /q Windows Media Player 11=wmp11-windowsxp-x86-enu.exe /q [Installs] 7zip=7zip.msi /passive Firefox=Freeware\Firefox.msi /passive Internet Explorer Flash Plugin=flash-ie.exe /S Mozilla Flash Plugin=flash-mozilla.exe /S Sun Java=java.exe /passive Adobe Acrobat Reader=Productivity\AdbeRdr.msi /passive For instance, the patches all seem to install with the exception of the .NET Framework 1.1 service pack. Then 7-zip, Firefox and Adobe all won't install. I assumed it was because some of the installs are spawning processes that lock access to msiexec, but I don't know. Also, bo8ster's recommendation sounds promising, but I don't entirely understand how to implement it. Link to comment Share on other sites More sharing options...
Authenticity Posted May 6, 2009 Share Posted May 6, 2009 Maybe the Installs path doesn't exists and making Run fail? Link to comment Share on other sites More sharing options...
jwseek Posted May 6, 2009 Author Share Posted May 6, 2009 No...they're all there in the same path. I checked three times. The installs actually start, they just fail. Like I said, this may actually be an issue with msiexec and not AutoIt, but I was hoping somebody could help me narrow it down... Link to comment Share on other sites More sharing options...
jwseek Posted May 6, 2009 Author Share Posted May 6, 2009 So there are moments in my life where I find myself extremely embarrassed. This is one of those moments. I mentioned the msiexec process about 5 times in this thread, and I just realized that to properly execute .msi files, one has to execute them like this: msiexec /i filename.msi Pretty silly thing to forget, but there it is... The corrected code: expandcollapse popup#Region;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=favicon.ico #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Res_Description=Script to install all needed software on new computers #AutoIt3Wrapper_Res_Fileversion=0.3.0.7 #AutoIt3Wrapper_Res_FileVersion_AutoIncrement=y #AutoIt3Wrapper_Res_SaveSource=y #AutoIt3Wrapper_Res_Language=1033 #AutoIt3Wrapper_res_requestedExecutionLevel=requireAdministrator #AutoIt3Wrapper_Run_Tidy=y #EndRegion;**** Directives created by AutoIt3Wrapper_GUI **** #Region Include Statements #include <GUIConstants.au3> #EndRegion Include Statements #Region Variable Declarations $programTitle = "AutoInstaller" $iniFile = "autoinstaller.ini" $iniSections = IniRead($iniFile, "Global", "IniSections", "3") $serverName = "\\" & IniRead($iniFile, "Global", "ServerName", "") $installFolder = $serverName & "\" & IniRead($iniFile, "Global", "InstallFolder", "install") $patchesFolder = $serverName & "\" & IniRead($iniFile, "Global", "PatchesFolder", "patches") $installDrive = IniRead($iniFile, "Global", "InstallDrive", "Z:") $patchesDrive = IniRead($iniFile, "Global", "patchesDrive", "Y:") $patchesSetup = IniReadSection($iniFile, "Patches") $installSetup = IniReadSection($iniFile, "Installs") $copyLocation = "D:\BIN" $BaseX = 20 $BaseY = 15 $CurX = 0 $CurY = 0 Dim $driveMapErrors[6] $driveMapErrors[0] = "Undefined or Other" $driveMapErrors[1] = "Access to the remote share was denied" $driveMapErrors[2] = "The device is already assigned" $driveMapErrors[3] = "Invalid device name" $driveMapErrors[4] = "Invalid remote share" $driveMapErrors[5] = "Invalid password" #EndRegion Variable Declarations Opt("TrayIconHide", 1) $hGUI = GUICreate($programTitle, 280, 210) Opt("GUICoordMode", 1) #Region Drop-Down Menu $fileMenu = GUICtrlCreateMenu("&File") $iniLoadMenuItem = GUICtrlCreateMenuItem("&Load Ini File", $fileMenu) $exitProgramMenuItem = GUICtrlCreateMenuItem("E&xit", $fileMenu) $helpMenu = GUICtrlCreateMenu("&Help") $aboutMenuItem = GUICtrlCreateMenuItem("About...", $helpMenu) #EndRegion Drop-Down Menu #Region Create GUI $CurX = $BaseX $CurY = $BaseY $computerTypeHomeRadio = GUICtrlCreateRadio("Home System", $CurX, $CurY) $CurY += 25 $computerTypeWorkRadio = GUICtrlCreateRadio("Business System", $CurX, $CurY) $CurY += 35 GUICtrlCreateLabel("Destination for BIN directory:", $CurX, $CurY) $CurY += 20 $copyLocationInput = GUICtrlCreateInput($copyLocation, $CurX, $CurY, 150) $CurX += 160 $browseCopyLocation = GUICtrlCreateButton("Browse...", $CurX, $CurY - 3) $CurX = $BaseX $CurY += 45 $executeButton = GUICtrlCreateButton("Install Software", $CurX, $CurY) $CurX += 135 $exitButton = GUICtrlCreateButton("Exit Program", $CurX, $CurY) #EndRegion Create GUI GUISetState() GUICtrlSetState($computerTypeHomeRadio, $GUI_DISABLE) GUICtrlSetState($computerTypeWorkRadio, $GUI_DISABLE) ; Run the GUI until the dialog is closed Do $msg = GUIGetMsg() Switch $msg Case $aboutMenuItem MsgBox(0, "", "Version: " & FileGetVersion("AutoInstaller.exe")) Case $exitProgramMenuItem $msg = $GUI_EVENT_CLOSE Case $exitButton $msg = $GUI_EVENT_CLOSE Case $iniLoadMenuItem $iniFile = FileOpenDialog("Select config file", @ScriptDir, "INI files (*.ini)", 1) If $iniFile Then LoadINIFile() EndIf Case $browseCopyLocation $copyLocation = browseFolder() If StringCompare($copyLocation, "") <> 0 Then GUICtrlSetData($copyLocationInput, $copyLocation) Else $copyLocation = GUICtrlRead($copyLocationInput) EndIf Case $executeButton modCallingWindow("AutoInstaller.exe", @SW_MINIMIZE) ProgressOn("Installing patches and software...", "Mapping Network Drives...") $temp = MapDrives() If $temp = 1 Then ProgressSet(10, "", "Installing Windows patches...") For $i = 1 To $patchesSetup[0][0] ;MsgBox(0, "", $patchesFolder & '\' & $patchesSetup[$i][1] & @LF & $patchesSetup[$i][0]) ProgressSet($i, "Installing " & $patchesSetup[$i][0]) If StringInStr($patchesSetup[$i][1], "msi", 2) = 0 Then $PID = Run($patchesFolder & '\' & $patchesSetup[$i][1], $patchesFolder) Else $PID = Run("msiexec /i " & $patchesFolder & '\' & $patchesSetup[$i][1], $patchesFolder) EndIf ProcessWaitClose($PID) Next ProgressSet(33, "Copying install folder to " & $copyLocation) ;MsgBox(0, "", "Copy from " & $installFolder & " to " & $copyLocation) DirCopy($installFolder, $copyLocation, 1) ProgressSet(66, "Installing Software...") For $i = 1 To $installSetup[0][0] ;MsgBox(0, "", $installFolder & '\' & $installSetup[$i][1] & @LF & $installSetup[$i][0]) ProgressSet(66 + $i, "Installing " & $installSetup[$i][0]) If StringInStr($installSetup[$i][1], "msi", 2) = 0 Then $PID = Run($installFolder & '\' & $installSetup[$i][1], $installFolder) Else $PID = Run("msiexec /i " & $installFolder & "\" & $installSetup[$i][1], $installFolder) EndIf ProcessWaitClose($PID) Next ProgressSet(100, "Done", "Completed!") Sleep(3000) ProgressOff() modCallingWindow("AutoInstaller.exe", @SW_RESTORE) MsgBox(64, "Completed Installation", "Successfully completed installation and copying procedures...") Else MsgBox(48, "Failed Networking!", "Networking drives to install directories failed...") EndIf EndSwitch Until $msg = $GUI_EVENT_CLOSE DriveMapDel($installDrive) DriveMapDel($patchesDrive) GUIDelete() #Region General Functions Func browseFolder() Local $tempFolder = "" $tempFolder = FileSelectFolder("Select Location for BIN Directory:", "") Return $tempFolder EndFunc ;==>browseFolder Func LoadINIFile() ;determine whether the sections with in the ini file are correct for this particular ini load $iniSectionList = IniReadSectionNames($iniFile) If $iniSectionList[0] = $iniSections And $iniSectionList[1] = "Global" Then $loadINI = MsgBox(1, "Loading INI File...", "This will change all initialized data (including networking data)", 3) $serverName = "\\" & IniRead($iniFile, "Global", "ServerName", "") $installFolder = $serverName & "\" & IniRead($iniFile, "Global", "InstallFolder", "install") $patchesFolder = $serverName & "\" & IniRead($iniFile, "Global", "PatchesFolder", "patches") $installDrive = IniRead($iniFile, "Global", "InstallDrive", "Z:") $patchesDrive = IniRead($iniFile, "Global", "patchesDrive", "Y:") $patchesSetup = IniReadSection($iniFile, "Patches") $installSetup = IniReadSection($iniFile, "Installs") Else MsgBox(48, "Invalid Program INI File", "The file you selected does not contain the proper formatting for loading as an INI file") EndIf EndFunc ;==>LoadINIFile Func IsVisible($handle) If BitAND(WinGetState($handle), 2) Then Return 1 Else Return 0 EndIf EndFunc ;==>IsVisible Func modCallingWindow($title, $state) Local $activeWindowList = WinList() Local $windowNumber = 0 For $i = 1 To $activeWindowList[0][0] If $activeWindowList[$i][0] <> "" And IsVisible($activeWindowList[$i][1]) Then Local $windowTitle = StringTrimLeft($activeWindowList[$i][0], StringLen($activeWindowList[$i][0]) - StringLen($title)) If $windowTitle = $title Then $windowNumber = $i WinSetState($activeWindowList[$i][0], "", $state) EndIf EndIf Next EndFunc ;==>modCallingWindow #EndRegion General Functions #Region Networking Functions Func MapDrives() DriveMapDel($installDrive) DriveMapDel($patchesDrive) $res = DriveMapAdd($installDrive, $installFolder) If $res <> 1 Then SplashOff() MsgBox(16, "Drive Mapping", "Error mapping drive!" & @LF & "Error Code: " & $driveMapErrors[@error]) Return $res EndIf $res = DriveMapAdd($patchesDrive, $patchesFolder) If $res <> 1 Then SplashOff() MsgBox(16, "Drive Mapping", "Error mapping drive!" & @LF & "Error Code: " & $driveMapErrors[@error]) Return $res EndIf Return $res EndFunc ;==>MapDrives #EndRegion Networking Functions Link to comment Share on other sites More sharing options...
Danny35d Posted May 6, 2009 Share Posted May 6, 2009 So there are moments in my life where I find myself extremely embarrassed. This is one of those moments. I mentioned the msiexec process about 5 times in this thread, and I just realized that to properly execute .msi files, one has to execute them like this: msiexec /i filename.msi Pretty silly thing to forget, but there it is...Or instead of Run() use ShellExecute() and you don't have to worry about .exe or .msi AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line Link to comment Share on other sites More sharing options...
jwseek Posted May 6, 2009 Author Share Posted May 6, 2009 But then I'd have to parse the arguments that I add to the end of every install procedure to make them non-interactive. This is also pretty easy, and there's less string manipulation. Although, I wish I would have noticed that sooner... Link to comment Share on other sites More sharing options...
bo8ster Posted May 6, 2009 Share Posted May 6, 2009 I do some installing of programs in batch files - i know AutoIt is the way but thats just how it turned out. To install postgres I do the following in the batch file CODEmsiexec /q /i postgresql-8.3-int.msi INTERNALLAUNCH=1 ADDLOCAL=server,nls,psql,pgadmin DOSERVICE="1" SERVICEDOMAIN="%COMPUTERNAME%" SERVICEACCOUNT="postgres" SERVICEPASSWORD="AdminUser" CREATESERVICEUSER="1" SUPERPASSWORD="mypassword" PL_PGSQL="1" DATADIR="E:\dbpath" If I where to do this in AutoIt I would do something like ShellExecuteWait('msiexec', ' /q /i postgresql-8.3-int.msi INTERNALLAUNCH=1 ADDLOCAL=server,nls,psql,pgadmin DOSERVICE="1" SERVICEDOMAIN="%COMPUTERNAME%" SERVICEACCOUNT="postgres" SERVICEPASSWORD="AdminUser" CREATESERVICEUSER="1" SUPERPASSWORD="mypassword" PL_PGSQL="1" DATADIR="E:\dbpath") The use of ProcessWaitClose is good but I believe ShellExecuiteWait is more flexible. You don't get the pid, but you should not need it. Hope that helps. Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic] Link to comment Share on other sites More sharing options...
Danny35d Posted May 7, 2009 Share Posted May 7, 2009 ShellExecuteWait('postgresql-8.3-int.msi', 'INTERNALLAUNCH=1 ADDLOCAL=server,nls,psql,pgadmin DOSERVICE="1" SERVICEDOMAIN="'& @ComputerName & '" SERVICEACCOUNT="postgres" SERVICEPASSWORD="AdminUser" CREATESERVICEUSER="1" SUPERPASSWORD="mypassword" PL_PGSQL="1" DATADIR="E:\dbpath" /qr', @ScriptDir) AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now