Jump to content



Photo

ASI / AutoIt Software Installer


  • Please log in to reply
No replies to this topic

#1 CaptainClucks

CaptainClucks

    Unum Cavillator Spuria

  • Active Members
  • PipPipPipPipPipPip
  • 1,216 posts

Posted 09 March 2012 - 09:45 AM

This is just a concept script I guess, it helps you register an application to the windows "add and remove software" control panel applet, it copies itself into the directory where you specify the installation to occur and registers a command line parameter to uninstall the software when the user requests so.

The download comes with a precompiled x86 assembly application that is just there to test the installation, when run, it's brings up a message box stating it was installed properly, source included.

One problem though, the script will also create a short cut on the desktop and a start menu entry with a link to uninstall, problem is I don't know how to have the script delete the lnk files and start menu entry, if someone can help, that'd be awesome!

Here's the full source with example script and application.
Attached File  AutoIt Software Installer.rar   19.57K   307 downloads

For those who'd rather just save the UDF and example without the example app~

Example usage.

AutoIt         
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=shell32_271.ico #AutoIt3Wrapper_Outfile=SetUp.exe #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include "ASI.au3" #cs     Run this once and it will install itselfe to program files under the value of $Intsallation_ID.     Then go to the "Add Or Remove Programs" control panel applet and click remove. #ce ; Variable used to identify this installation and the name it will have under the uninstallation entry in the ; control panel and also the directory name that will be used. ; Make sure to use a unique identifying name as this script will not work if there are any entried that have the same name Global $Intsallation_ID = "AutoIt Test Application" ; In example: this script will not make any changes and will fail operation if anything is going to be over written ; so it is up to you, the user, to handle the required name change for installing any of your software. ; You should make a function that saves this ID somewhere it can always get it so as to avoid any confusion and errors ; because the script will not handle this type of error and you will be faced with a broken setup... _Commence_Operation() Func _Commence_Operation()     Local $RetVal     If Not $CMDLINERAW Then         $RetVal = _Install($Intsallation_ID, "AutoIt Community", 0, "", "", "", "", "_OurUserSuppliedInstallationFunction")         Switch @error             Case 0                 MsgBox(64, "Operation Compleated!", "The operation compleated successfully!" & @CRLF & 'You may now remove the application through the "Add or Remove Software" control panel applet.')             Case 1                 MsgBox(48, "Error: _Install", "This error can be several things, such as the script not being compiled" & @CRLF & "or an empty display name or incorrect HKxx key base.")             Case 2                 MsgBox(48, "Error: _Install", "Explicitly an incorrect base key format or name")             Case 3                 MsgBox(48, "Error: _Install", "Application has detected that it previously installed flawlessly.")             Case 4                 MsgBox(48, "Error: _Install", "another program seems to be using the registry key you are trying to use." & @CRLF & "It's up to you to take care of this type of error, I.E., use a function to generate a unique installation name.")             Case 5                 MsgBox(48, "Error: _Install", 'Installation directory does not have the directory attribute "D"' & @CRLF & "meaning destination may be a file.")             Case 6                 MsgBox(48, "Error: _Install", "Installation directory already exists, I'll leave it up to you to handle this.")             Case 7                 MsgBox(48, "Error: _Install", "Isntallation dorectory may be read only or user does not" & @CRLF & "have sufficiant privilages to create a directory at specified location.")             Case 8                 MsgBox(48, "Error: _Install", "Failed to make a copy of this script to the uninstall directory for use as the uninstaller.")             Case 9                 MsgBox(48, "Error: _Install", "User supplied installation function does not exist.")             Case 10                 MsgBox(48, "Error: _Install", "Something is wrong with the registry value being used.")             Case 100                 MsgBox(48, "Error: _Install", "The suppliad user function returned Error Code: " & @extended & @CRLF & "Return Value: " & $RetVal)         EndSwitch     Else         ;If StringLen($CMDLINERAW) > 15 Then Return         $RetVal = CheckUninstallRequest($Intsallation_ID, "", "_OurUserSuppliedUninstallationFunction")         Switch @error             Case 0                 MsgBox(64, "Operation Compleated!", "The operation compleated successfully!" & @CRLF & "Click ok to continue with the uninstaller removal.")                 _SelfDelete()             Case 1                 MsgBox(48, "Error: CheckUninstallRequest", "We're not compiled.")             Case 2                 MsgBox(48, "Error: CheckUninstallRequest", "You will get this error only if you supplied" & @CRLF & " an uninstall function and the function supplied does not exist.")             Case 3                 MsgBox(48, "Error: CheckUninstallRequest", "Explicitly an incorrect base key format or name.")             Case 4                 MsgBox(48, "Error: CheckUninstallRequest", "Failed to read the registry key that has the install location defined" & @CRLF & "this is needed in order to know what directory should" & @CRLF & "be cleaned up and removed.")             Case 5                 MsgBox(48, "Error: CheckUninstallRequest", "Failed to delete the installation directory where the program is located.")             Case 6                 MsgBox(48, "Error: CheckUninstallRequest", "Failed to delete registry modification that were made when installing the application!")             Case 100                 MsgBox(48, "Error: CheckUninstallRequest", "The supplied user uninstalltion function set an error")         EndSwitch     EndIf     Return EndFunc   ;==>_Commence_Operation Func _OurUserSuppliedInstallationFunction()     Local $TestAppLnk = @DesktopDir & "TestApp.lnk"     If Not FileInstall(".testapp.exe","TestApp.exe") Then Return SetError(1,0,False)     FileInstall(".TestApp Source Code.zip","TestApp Source Code.zip")     If FileExists($TestAppLnk) Then         For $I = 0 To 99999999             $TestAppLnk = @TempDir & "TestApp(" & $I & ").lnk"             If Not FileExists($TestAppLnk) Then ExitLoop         Next     EndIf     If Not FileCreateShortcut(@WorkingDir & "testapp.exe",$TestAppLnk) Then Return SetError(2,0,False)     If Not DirCreate(@StartMenuDir & "Programs" & $Intsallation_ID) Then Return SetError(3,0,False)     FileCreateShortcut(@ProgramFilesDir & "" & $Intsallation_ID & "Uninstall.exe",@StartMenuDir & "Programs" & $Intsallation_ID & "Uninstall.lnk","","--uninstall","Uninstall")     Return SetError(0,0,True) EndFunc Func _OurUserSuppliedUninstallationFunction()     Return SetError(0,0,True) EndFunc


The UDF.
AutoIt         
#include-once ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Install ; Description ...: ; Syntax ........: _Install($DisplayName, $Publisher, $DisplayIcon, $InstallLocation[, $HKType = "HKCU"[, $DisplayVersion = ""[, ;                  $HelpLink = False[, $InstallFunc]]]]) ; ; Parameters ....: $DisplayName         - [ByRef] Registry sub key name used and Software removal entry name that will be shown. ;                  $Publisher           - Publisher name to show in the control panel software removal applet. ;                  $DisplayIcon         - Icon to show in the software removal applet, should be icon index number or name. ;                                               Syntax can be (@SystemDir & "shell32.dll,0") or just leave blank to use ;                                               the scripts default icon. ;                  $InstallLocation     - [optional] Location to set the uninstaller and to install files. Default ;                                                       is @ProgramFilesDir ;                  $HKType              - [optional] Registry key base to set the installation for. Default is ;                                                       "HKCU", (I.E., current user). ;                  $DisplayVersion      - [optional] Version display entry. Default is the compiled application version. ;                  $HelpLink            - [optional] A link to where a user may get help. Default is none. ;                  $InstallFunc         - [optional] Your function to call that will install the program or required files. ;                                                       Default is none. You should only use this function if it has proper ;                                                       error checking and return values, I would recommend that you have ;                                                       the suppled func return an error only if its something ;                                                       critical (I.E., anything that would break the installation.) ;                                                       But this can be handy if you configure your function correctly ;                                                       so as to allow this function to remove anything it may have done ;                                                       in case your function fails for some reason. ; ; Return values .: True if operation compleated successfully, false if errors occured and error set to one of positive ;                       values listed below unless you supplied an installation function which will return its error and ;                       set the @Extended macro to a positive value. ; ;                    @Error ~ ;                       1 - Can be several things, such as the script not being compiled or an empty display name ;                               value or incorrect base key format. ;                       2 - Explicitly an incorrect base key format or name. ;                       3 - Application has detected that it previously installed flawlessly. ;                       4 - Another program seems to be using the registry key you are trying to use. It's up to you to ;                               take care of this type of error, I.E., use a function to generate a unique installation name. ;                       5 - Installation directory does not have the directory attribute "D", meaning destination ;                               may be a file. ;                       6 - Installation directory already exists, I'll leave it up to you to handle this just like ;                               the registry. ;                       7 - Isntallation directory may be read only or user does not have sufficiant privilages to ;                               create a directory at specified location. ;                       8 - Failed to make a copy of this script to the uninstall directory for use as the uninstaller. ;                       9 - User supplied installation function does not exist. ;                       10 - something is wrong with the registry value being used. ;                       100 - The supplied installtion function returned an error, if this value is positive, the ;                               @Extended macro is set to the supplied installation functions @Error return code ;                               while also returning its return value. ; ; Author ........: THAT1ANONYMOUSDUDE, zorphnog ; Modified ......: ; Remarks .......: You are responsible for handling the files to be installed, this just registers your uninstallation function. ; Related .......: None ; Link ..........: ; Example .......: Depends on you, but mostly yes. ; =============================================================================================================================== Func _Install(ByRef $DisplayName, $Publisher, $DisplayIcon, $InstallLocation = @ProgramFilesDir, $HKType = "HKCU", $DisplayVersion = Default, $HelpLink = False, $InstallFunc = False)     #region - Variable Verification / Correction -     If Not $HKType Then $HKType = "HKCU"     If Not $InstallLocation Then $InstallLocation = @ProgramFilesDir     If Not $DisplayVersion Then $DisplayVersion = Default     If Not $HelpLink Then $HelpLink = False     If Not $InstallFunc Then $InstallFunc = False     If (IsString($HKType) = False) Or (StringLen($HKType) < 4) Or (StringLen($DisplayName) = 0) Or Not @Compiled Then Return SetError(1, 0, False)     $HKType = _CheckBaseKey($HKType)     If @error Then         Return SetError(2, 0, False)     EndIf     #endregion - Variable Verification / Correction -     Local $Key = $HKType & "SoftwareMicrosoftWindowsCurrentVersionUninstall" & $DisplayName     For $I = 1 To 999999         $Ret = RegEnumKey($HKType & "SoftwareMicrosoftWindowsCurrentVersionUninstall",$I)         If @error Then ExitLoop         If $Ret == $DisplayName Then             $CHECK = RegRead($HKType & "SoftwareMicrosoftWindowsCurrentVersionUninstall" & $DisplayName,"ID")             If $CHECK = "0x6175746F6974" Then; autoit in binary format                 Return SetError(3,0,True)             Else                 Return SetError(4,0,False)             EndIf         EndIf     Next     If StringTrimLeft($InstallLocation, StringLen($InstallLocation) - 1) == '' Then         Local $SP = StringSplit($InstallLocation, "", 2)         Local $NM = UBound($SP) - 1         $InstallLocation = ''         For $I = 0 To $NM             $InstallLocation &= $SP[$I]             If ($I + 1) = $NM Then ExitLoop             $InstallLocation &= ""         Next     EndIf     Local $CHECK = False     If FileExists($InstallLocation) Then         $CHECK = FileGetAttrib($InstallLocation)         If Not StringInStr($CHECK, "D", 2) Then Return SetError(5, 0, False)         $CHECK = $InstallLocation & "" & $DisplayName         If FileExists($CHECK) Then Return SetError(6, 0, False)         If Not DirCreate($CHECK) Then Return SetError(7, 0, False)     Else         $CHECK = $InstallLocation & "" & $DisplayName         If Not DirCreate($CHECK) Then Return SetError(7, 0, False)     EndIf     If Not FileCopy(@AutoItExe, $CHECK & "" & "Uninstall.exe") then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(8,0,False)     EndIf     If $InstallFunc Then         Local $Workingdir = @WorkingDir         FileChangeDir($CHECK)         ; change working directory to our new installation directory and call user         ; supplied function to install required files to this directory.         Local $Return = Call($InstallFunc)         Local $Error = @error         FileChangeDir($Workingdir)         If $Error Then             Switch $Error                 Case 0xDEAD                     DirRemove($CHECK)                     Return SetError(9, 0, False)                 Case Else                     DirRemove($CHECK)                     Return SetError(100, $Error, $Return)             EndSwitch         Else             ;Continue operation         EndIf     EndIf     #cs         When a user clicks the uninstall button in the control panel applet         this parameter below will be passed to our compiled application letting         us know we should uninstall our software from their machine...     #ce     RegWrite($Key, "UninstallString", "REG_SZ", $CHECK & "Uninstall.exe --uninstall")     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     RegWrite($Key, "InstallLocation", "REG_SZ", $CHECK)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     RegWrite($Key, "DisplayName", "REG_SZ", $DisplayName)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     If Not $DisplayIcon Then         $DisplayIcon = $CHECK & "Uninstall.exe"     EndIf     RegWrite($Key, "DisplayIcon", "REG_SZ", $DisplayIcon)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     RegWrite($Key, "Publisher", "REG_SZ", $Publisher)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     If $HelpLink Then         RegWrite($Key, "HelpLink", "REG_SZ", $HelpLink)         If @error Then             RegDelete($Key)             DirRemove($CHECK)             Return SetError(10, 0, False)         EndIf     EndIf     Switch $DisplayVersion         Case Default, ""             $DisplayVersion = FileGetVersion(@AutoItExe, "FileVersion")             If @error Then $DisplayVersion = FileGetVersion(@AutoItExe, "ProductVersion")             $DisplayVersion = StringReplace($DisplayVersion,",",".")     EndSwitch     RegWrite($Key, "DisplayVersion", "REG_SZ", $DisplayVersion)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     RegWrite($Key, "Version", "REG_SZ", $DisplayVersion)     If @error Then         RegDelete($Key)         DirRemove($CHECK)         Return SetError(10, 0, False)     EndIf     RegWrite($Key, "NoModify", "REG_DWORD", 1); No modification options     RegWrite($Key, "NoRepair", "REG_DWORD", 1); No repair options     RegWrite($Key, "InstallDate", "REG_SZ", @YEAR & @MON & @MDAY); I have no idea if this is the correct format.     RegWrite($Key, "ID", "REG_BINARY", "0x6175746F6974"); Used to identify ourselves, says "autoit" in binary format     Return SetError(0, 0, True) EndFunc   ;==>_Install ; #FUNCTION# ==================================================================================================================== ; Name ..........: CheckUninstallRequest ; Description ...: ; Syntax ........: CheckUninstallRequest($DisplayName[, $HKType = "HKCU"[, $Function = ""]]) ; Parameters ....: $DisplayName         - [ByRef] Registry sub key name used and Software removal entry name that will be shown. ;                  $HKType              - [optional] Registry key base to set the installation for. Default is ;                                                       "HKCU", (I.E., current user). ;                  $Function            - [optional] Your function to call that will uninstall program changes that were made. ;                                                       Default is none. You should only use this function if it has proper ;                                                       error checking and return values. ; Return values .: Returns true if operation compleated successfully, false if errors occure and sets error level to one of below. ; ;                    @Error ~ ;                       1 - We're not compiled. ;                       2 - You will get this error only if you supplied an uninstall function and the function supplied ;                                does not exist. ;                       3 - Explicitly an incorrect base key format or name. ;                       4 - Failed to read the registry key that has the install location defined, this is needed in order to ;                                know what directory should be cleaned up and removed. ;                       5 - Failed to delete the installation directory where the program is located. ;                       6 - Failed to delete registry modification that were made when installing the application! ;                       100 - The supplied uninstalltion function set an error, if this value is positive, maybe even 0, the ;                                @extended macro is set to the supplied installation functions @Error return code ;                                and return value is also passed, make sure to set your functions error level to ;                                a correct value for this to work, this function will also still execute after yours is called ;                                and no errors were returned. ; ; Author ........: THAT1ANONYMOUSDUDE, zorphnog ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: Depends on you, again... ; =============================================================================================================================== Func CheckUninstallRequest($DisplayName, $HKType = "HKCU", $Function = "")     If Not @Compiled Then Return SetError(1, 0, False)     If $CmdLineRaw Then         Local $Return = StringSplit($CmdLineRaw, "--", 2)         If IsArray($Return) Then             If (UBound($Return) - 1) > 1 Then                 If $Return[2] == "uninstall" Then; no other paramaters should have been passed, so we                     If Not $Function Then; we will attempt to delete everything in our installation directory                         #region - Application Removal -                         If FileGetShortName(@ScriptDir) <> FileGetShortName(@TempDir) Then; move a copy of this file to the temp directory so we can uninstall properly from there.                             Local $TmpFile = @TempDir & "Uninstall.exe"                             If FileExists($TmpFile) Then                                 For $I = 0 To 99999999                                     $TmpFile = @TempDir & "Uninstall(" & $I & ").exe"                                     If Not FileExists($TmpFile) Then ExitLoop                                 Next                                 Sleep(500)                             EndIf                             FileCopy(@ScriptFullPath, $TmpFile)                             If Not ProcessExists(Run(FileGetShortName($TmpFile) & " --uninstall", @WorkingDir)) Then Return SetError(1, 0, False)                             Exit                         Else; we are already in the temp directory, commence operation to remove everything possible.                             If Not $HKType Then $HKType = "HKCU"                             $HKType = _CheckBaseKey($HKType)                             If @error Then Return SetError(3, 0, False)                             Local $Key = $HKType & "SoftwareMicrosoftWindowsCurrentVersionUninstall" & $DisplayName                             Local $Directory = RegRead($Key, "InstallLocation")                             If $Directory = @error Then SetError(4, 0, False)                             If Not DirRemove($Directory, 1) Then                                 CloseExecMods($Directory); maybe we're locked because an application is running in our dir, lets locate exes and close them.                                 If Not DirRemove($Directory, 1) Then Return SetError(5, 0, False)                             EndIf                             If RegDelete($Key) <> 1 Then Return SetError(6, 0, False)                             Return SetError(0, 0, True)                         EndIf                         #endregion - Application Removal -                     Else; you supplied a function, we'll use that and finish operation after it successfully executed.                         #region - User Supplied Function -                         #cs                             This is useful if you have a function that will delete other files outside the installation directory. After it's done                             It will run itslef again and finish the deal.                         #ce                         $Return = Call($Function)                         If @error Then                             Switch @error                                 Case 0xDEAD                                     Return SetError(2, 0, False)                                 Case Else                                     Return SetError(100, @error, $Return)                             EndSwitch                         Else                             CheckUninstallRequest($DisplayName, $HKType)                             ;Continue with our part of the uninstallation                         EndIf                         #endregion - User Supplied Function -                     EndIf                 EndIf             EndIf         EndIf     EndIf     Return SetError(0, 0, False) EndFunc   ;==>CheckUninstallRequest #region - Internal - ; #INTERNAL FUNCTION# =========================================================================================================== ; Name ..........: _CheckBaseKey ; Description ...: Fixes key base for registry ; Syntax ........: _CheckBaseKey($HKType) ; Parameters ....: $HKType              - Registry key to check. ; Return values .: The correct base key. ; Author ........: THAT1ANONYMOUSDUDE ; Modified ......: ; Remarks .......: This function is supposed to check if things are going to be written to the correct registry area. ; Related .......: None ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _CheckBaseKey($HKType)     Local $CHECK = False     If (@OSArch <> "X86") And @AutoItX64 Then         If Number(StringTrimLeft($HKType, StringLen($HKType) - 2)) <> 64 Then             #cs                 Jon once said somewhere that if running a compiled autoit script with an x86 interpreter                 the x64 OS will manually correct the key destination unless running with the x64 interpreter                 the system will assume the destination is correct, so just in case, we will attempt a correction                 manually in this area just for the heck of it..                 Also note: If no match is found, we will throw an error because this shouldn't be written anywhere else.             #ce             Local Const $KeyVal[4][2] = [ _                     ["HKCU", "HKCU64"], _                     ["HKLM", "HKLM64"], _                     ["HKEY_LOCAL_MACHINE", "HKEY_LOCAL_MACHINE64"], _                     ["HKEY_CURRENT_USER", "HKEY_CURRENT_USER64"] _                     ]             For $I = 0 To UBound($KeyVal, 1) - 1                 If StringInStr($KeyVal[$I][0], $HKType, 2) Then                     $HKType = $KeyVal[$I][1]                     $CHECK = True                     ExitLoop                 EndIf             Next             If Not $CHECK Then Return SetError(1, 0, False)         EndIf     EndIf     Return SetError(0, 0, $HKType) EndFunc   ;==>_CheckBaseKey ; #INTERNAL FUNCTION# =========================================================================================================== ; Name ..........: CloseExecMods ; Description ...: closes exe programs in a directory. ; Syntax ........: CloseExecMods($Dir) ; Parameters ....: $Dir                 - the directory to recurse for executable moduluals ; Return values .: None ; Author ........: AutoIt Community ; Example .......: No ; =============================================================================================================================== Func CloseExecMods($Dir)     Local $FILE     Local $SEARCH = FileFindFirstFile($Dir & "*.*")     If $SEARCH = -1 Then Return     While 1         Sleep(0)         $FILE = FileFindNextFile($SEARCH)         If @error Then ExitLoop         If @extended Then             CloseExecMods($Dir & "" & $FILE)         Else             If StringInStr(StringRight($FILE, 4), "exe", 2) Then                 ProcessClose($FILE)             EndIf         EndIf     WEnd EndFunc   ;==>CloseExecMods ; #INTERNAL FUNCTION# =========================================================================================================== ; Name ..........: _SelfDelete ; Description ...: Deletes the running script ; Syntax ........: _SelfDelete() ; Parameters ....: None ; Return values .: None ; Author ........: MHz ; Modified ......: N/A ; Link ..........: <a href='http://www.autoitscript.com/forum/topic/19370-autoit-wrappers/page__view__findpost__p__199605' class='bbc_url' title=''>http://www.autoitscript.com/forum/topic/19370-autoit-wrappers/page__view__findpost__p__199605</a> ; Example .......: No ; =============================================================================================================================== Func _SelfDelete($iDelay = 0)     Local $sCmdFile     FileDelete(@TempDir & "scratch.bat")     $sCmdFile = 'ping -n ' & $iDelay & '127.0.0.1 > nul' & @CRLF _              & ':loop' & @CRLF _              & 'del "' & @ScriptFullPath & '"' & @CRLF _              & 'if exist "' & @ScriptFullPath & '" goto loop' & @CRLF _              & 'del ' & @TempDir & 'scratch.bat'     FileWrite(@TempDir & "scratch.bat", $sCmdFile)     Run(@TempDir & "scratch.bat", @TempDir, @SW_HIDE) EndFunc   ;==>_SelfDelete #endregion - Internal -

Edited by THAT1ANONYMOUSEDUDE, 09 March 2012 - 08:43 PM.

Spoiler
Warning: Posts by this user are subject to change or may disappear without notice.








0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users