Opt("ExpandVarStrings", 1)

#include-once
#include <String.au3>
#include <Array.au3>
#include <Math.au3>

#cs
Global $installedSoft, $lastLogToMainSource = ""

Func _TryAutoInstallExe($dir = @ScriptDir, $timelimit = 30, $testmode = False)
	_debug("_TryAutoInstallExe($dir$, $timelimit$)", $testmode)
	$file = _getExeOrMSI($dir)
	Return _TryAutoInstall($file, $timelimit, $testmode)
EndFunc   ;==>_TryAutoInstallExe

Func _TryAutoInstallExeRun($dir = @ScriptDir)
	$file = _getExeOrMSI($dir)
	Return _TryAutoInstallRun($file)
EndFunc   ;==>_TryAutoInstallExeRun

Func _getExeOrMSI($dir = @ScriptDir)
	$search = FileFindFirstFile($dir & "\*.*")
	Do
		$file = FileFindNextFile($search)
		If @error Then Return ""
	Until StringRight($file, 4) = ".exe" Or StringRight($file, 4) = ".msi"
	Return $dir & "\" & $file
EndFunc   ;==>_getExeOrMSI

Func _TryAutoInstall($filename, $timelimit = 30, $testmode = False)
	_debug("_TryAutoInstall($filename$, $timelimit$)", $testmode)
	$type = _GetInstallType($filename)
	_LogToMain("Installler-Typ: " & $type)
	$filename = FileGetShortName($filename)
	$filedir = _ParentDir($filename)

	Switch $type
		Case "Nullsoft Installer"
			_RunWorkingDir("$filename$ /S", $filedir, "", $timelimit, $testmode)
			Return True
		Case "Inno Setup"
			_RunWorkingDir("$filename$ /VERYSILENT /SP- /NORESTART", $filedir, "", $timelimit, $testmode)
			Return True
		Case "InstallShield (exe)"
			_RunWorkingDir('$filename$ /s /v"/qn"', $filedir, "", $timelimit, $testmode)
			Return True
		Case "InstallShield (msi)"
			_RunWorkingDir("msiexec.exe /i $filename$ /qn", $filedir, "", $timelimit, $testmode)
			Return True
		Case "Wise Installer"
			_RunWorkingDir("$filename$ /S", $filedir, "", $timelimit, $testmode)
			Return True
		Case "RAR SFX"
			_RunWorkingDir("$filename$ /s", $filedir, "", $timelimit, $testmode)
			Return True
		Case "MSI-Paket"
			_RunWorkingDir("msiexec.exe /i $filename$ /qb /norestart", $filedir, "", $timelimit, $testmode)
			Return True
	EndSwitch

	Return False
EndFunc   ;==>_TryAutoInstall

Func _TryAutoInstallRun($filename)
	$type = _GetInstallType($filename)
	_LogToMain("Installler-Typ: " & $type)
	$filename = FileGetShortName($filename)

	Switch $type
		Case "Nullsoft"
			Return Run("$filename$ /S")
		Case "Inno Setup"
			Return Run("$filename$ /VERYSILENT /SP- /NORESTART")
		Case "InstallShield (exe)"
			Return Run('$filename$ /s /v"/qn"')
		Case "InstallShield (msi)"
			Return Run("msiexec.exe /i $filename$ /qn")
		Case "Wise Installer"
			Return Run("$filename$ /S")
		Case "RAR SFX"
			Return Run("$filename$ /s")
		Case "MSI-Paket"
			Return Run("msiexec.exe /i $filename$ /qb /norestart")
	EndSwitch

	Return -1
EndFunc   ;==>_TryAutoInstallRun


Func _GetInstallTypeExe($dir)
	Return _GetInstallType(_getExeOrMSI($dir))
EndFunc   ;==>_GetInstallTypeExe

Func _GetInstallType($filename)
	If $filename = "" Then Return "unbekannt"
	$filename = FileGetShortName($filename)

	$type = DllCall(_FindFileUp("\Sonstiges\PEiDLL\PEiDLL.DLL"), "str", "Scan_Hard", "str", $filename)
	If Not IsArray($type) Then Return "unbekannt"
	$type = $type[0]

	If StringInStr($type, "Nullsoft", True) Then
		Return "Nullsoft Installer"
	EndIf
	If StringInStr($type, "Inno", True) Or StringInStr($type, "Borland Delphi 6.0 - 7.0 [Overlay]", True) Or StringInStr($type, "Borland Delphi 2.0 [Overlay]", True) Then
		Return "Inno Setup"
	EndIf
	If StringInStr($type, "InstallShield", True) Then
		If StringRight($filename, 4) = ".exe" Then
			Return "InstallShield (exe)"
		Else
			Return "InstallShield (msi)"
		EndIf
	EndIf
	If StringInStr($type, "Wise Installer", True) Then
		Return "Wise Installer"
	EndIf
	If StringInStr($type, "[RAR SFX]", True) Then
		Return "RAR SFX"
	EndIf

	If StringRight($filename, 4) = ".msi" Then
		Return "MSI-Paket"
	EndIf

	Return "unbekannt"
EndFunc   ;==>_GetInstallType

Func _isLivingOnCD()
	FileWrite(@ScriptDir & "\temp.tmp", "")
	If Not FileExists(@ScriptDir & "\temp.tmp") Then Return True
	FileDelete(@ScriptDir & "\temp.tmp")
	Return False
EndFunc   ;==>_isLivingOnCD

Func _istOnline($_server = "http://google.de")
	Return InetGet($_server, @TempDir & "\WSK\foo.tmp", 1)
EndFunc   ;==>_istOnline

Func _FindFileUp($filename)
	$up = "\"
	For $i = 0 To 4
		If FileExists(@ScriptDir & $up & $filename) Then Return FileGetShortName(@ScriptDir & $up & $filename)
		$up &= "..\"
	Next
	Return ""
EndFunc   ;==>_FindFileUp
#ce

Func _LogToMain($_message, $_source = "")
	Opt("WinDetectHiddenText", 1)
	$_mm = Opt("WinTitleMatchMode", 2)

	$_win = WinGetHandle("Johannes Mitlmeier für das PC Magazin")
	If $_source = "" Then $_source = ControlGetText($_win, "", "[CLASSNN:Static1]")
	If $_source = "dir" Then $_source = _ParentDirName(@ScriptDir)
	ControlSetText($_win, "", "[CLASSNN:Static1]", $_source)

	$_text = ControlGetText($_win, "", "[CLASSNN:Edit5]")
	$_text = @HOUR & ":" & @MIN & ":" & @SEC & " [" & $_source & "]: " & $_message & @CRLF & $_text
	ControlSetText($_win, "", "[CLASSNN:Edit5]", $_text)
	Opt("WinTitleMatchMode", $_mm)
EndFunc   ;==>_LogToMain

#cs
Func _RunScript($_script_dateiname, $params = "", $workingDir = "none")
	If _FindFileUp("Sonstiges\AutoIt3.exe") <> "" Then
		If $workingDir = "none" Then
			Run(_FindFileUp("Sonstiges\AutoIt3.exe") & ' "' & $_script_dateiname & '" ' & $params)
		Else
			Run(_FindFileUp("Sonstiges\AutoIt3.exe") & ' "' & $_script_dateiname & '" ' & $params, $workingDir)
		EndIf
	Else
		Return 0
	EndIf
	Return 1
EndFunc   ;==>_RunScript


Func _RunScriptWait($_script_dateiname, $params = "")
	If _FindFileUp("Sonstiges\AutoIt3.exe") <> "" Then
		ShellExecuteWait(_FindFileUp("Sonstiges\AutoIt3.exe"), '"' & $_script_dateiname & '"' & $params)
	Else
		Return 0
	EndIf
	Return 1
EndFunc   ;==>_RunScriptWait

Func _RunScriptWaitWorkingDir($_script_dateiname, $workingDir)
	ShellExecuteWait(_FindFileUp("\Sonstiges\AutoIt3.exe"), $_script_dateiname, $workingDir)
	Return 1
EndFunc   ;==>_RunScriptWaitWorkingDir

Func _RunScriptWorkingDir($_script_dateiname, $workingDir, $parameters = "", $timelimit = 999999999)
	$runPID = Run(FileGetShortName(_FindFileUp("\Sonstiges\AutoIt3.exe")) & ' "$_script_dateiname$" $parameters$', $workingDir)

	; Warten
	$zero = TimerInit()
	While ProcessExists($runPID) And TimerDiff($zero) < 60000 * $timelimit
		Sleep(1000)
	WEnd
	If ProcessExists($runPID) Then ProcessClose($runPID)

	Return 1
EndFunc   ;==>_RunScriptWorkingDir

Func _RunWorkingDir($_dateiname, $workingDir, $parameters = "", $timelimit = 999999999, $testmode = False)
	_debug("_RunWorkingDir($_dateiname$, $workingDir$, $parameters$, $timelimit$)", $testmode)
	If $testmode Then Return

	$runPID = Run(FileGetShortName($_dateiname) & " $parameters$", $workingDir)

	; Warten
	$zero = TimerInit()
	While ProcessExists($runPID) And TimerDiff($zero) < 60000 * $timelimit
		Sleep(1000)
	WEnd
	If ProcessExists($runPID) Then ProcessClose($runPID)

	Return 1
EndFunc   ;==>_RunWorkingDir

Func _Slash($_bs_text)
	If StringRight($_bs_text, 1) <> "/" Then
		Return $_bs_text & "/"
	Else
		Return $_bs_text
	EndIf
EndFunc   ;==>_Slash

Func _Backslash($_bs_text)
	If StringRight($_bs_text, 1) <> "\" Then
		Return $_bs_text & "\"
	Else
		Return $_bs_text
	EndIf
EndFunc   ;==>_Backslash

Func _NoBackslash($_bs_text)
	If StringRight($_bs_text, 1) <> "\" Then
		Return $_bs_text
	Else
		Return StringTrimRight($_bs_text, 1)
	EndIf
EndFunc   ;==>_NoBackslash

Func _Splash($_title, $_text)
	$_wtmm = Opt("WinTitleMatchMode", 4)
	$taskbar_pos = WinGetPos("classname=Shell_TrayWnd")
	Opt("WinTitleMatchMode", $_wtmm)
	SplashTextOn($_title, $_text, 400, 75, @DesktopWidth - 410, @DesktopHeight - 110 - $taskbar_pos[3], 32)
EndFunc   ;==>_Splash

Func _ToolTip($_text)
	Opt("WinTitleMatchMode", 4)
	$taskbar_pos = WinGetPos("classname=Shell_TrayWnd")
	Opt("WinTitleMatchMode", 1)
	ToolTip($_text, @DesktopWidth - 30, @DesktopHeight - 20 - $taskbar_pos[3])
EndFunc   ;==>_ToolTip

Func _Strip($_text)
	Return StringReplace($_text, '"', '')
EndFunc   ;==>_Strip

Func _Run($exe)
	Return Run(FileGetShortName($exe))
EndFunc   ;==>_Run
#ce

Func _InstallExeParam($paramString, $search = "*.exe")
	; Datei suchen
	$search = FileFindFirstFile(@ScriptDir & "\" & $search)
	$datei = FileFindNextFile($search)
	FileClose($search)
	If @error Then
		_LogToMain("Keine Installationsdatei gefunden")
	Else
		_LogToMain("Starte Datei " & $datei)
		ShellExecuteWait(@ScriptDir & "\" & $datei, $paramString)
	EndIf
EndFunc   ;==>_InstallExeParam

#cs
Func _MSIInstall($search = "*.msi")
	; Datei suchen
	$search = FileFindFirstFile(@ScriptDir & "\" & $search)
	$datei = FileFindNextFile($search)
	FileClose($search)
	If @error Then
		_LogToMain("Keine Installationsdatei gefunden")
	Else
		_LogToMain("Starte Datei " & $datei)
		ShellExecuteWait("msiexec", "/i " & $datei & " /qn")
	EndIf
EndFunc   ;==>_MSIInstall

Func _FileCopy($search, $destFolder, $linkToPrograms = True)
	; Datei suchen
	$search = FileFindFirstFile(@ScriptDir & "\" & $search)
	$datei = FileFindNextFile($search)
	FileClose($search)
	; kopieren
	FileCopy(@ScriptDir & "\" & $datei, @ProgramFilesDir & "\" & $destFolder & "\", 9)
	; linken
	DirCreate(@StartMenuCommonDir & "\" & $destFolder)
	FileCreateShortcut(@ProgramFilesDir & "\" & $destFolder & "\" & $datei, _
			@StartMenuCommonDir & "\" & $destFolder & "\" & StringLeft($datei, StringInStr($datei, ".", True, -1) - 1) & ".lnk")
EndFunc   ;==>_FileCopy

Func _getUpdatableFilePath($_filename, $_relativeDirectory)
	If FileExists(@TempDir & "\WSK\" & _Backslash($_relativeDirectory) & $_filename) Then
		Return FileGetShortName(@TempDir & "\WSK\" & _Backslash($_relativeDirectory) & $_filename)
	EndIf
	Return FileGetShortName(@ScriptDir & "\" & _Backslash($_relativeDirectory) & $_filename)
EndFunc   ;==>_getUpdatableFilePath

Func _ParentDirName($path)
	Return StringTrimLeft($path, StringInStr(@ScriptDir, "\", True, -1))
EndFunc   ;==>_ParentDirName

Func _ParentDir($path)
	Return StringLeft($path, StringInStr($path, "\", True, -1) - 1)
EndFunc   ;==>_ParentDir

Func _getInstallDir()
	Return RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion", "ProgramFilesDir")
EndFunc   ;==>_getInstallDir

Func _getUninstallString($string)
	_scanInstalledSoftware()

	Local $_result[1]
	; suchen
	For $el In $installedSoft
		$_parts = StringSplit($el, "|")
		If StringInStr($_parts[1], $string) Then
			_ArrayAdd($_result, $_parts[2])
		EndIf
	Next
	_ArrayDelete($_result, 0)
	Return $_result
EndFunc   ;==>_getUninstallString

Func _isInstalled($string)
	_scanInstalledSoftware()

	; suchen
	For $el In $installedSoft
		If StringInStr($el, $string) Then Return True
	Next
	Return False
EndFunc   ;==>_isInstalled

Func _scanInstalledSoftware()
	; zusammensuchen
	If Not IsObj($installedSoft) Then
		$installedSoft = ObjCreate("System.Collections.ArrayList")

		$i = 1
		While True
			$value = RegEnumKey("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall", $i)
			If @error <> 0 Then ExitLoop
			$value2 = RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\$value$", "DisplayName")
			$value3 = RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\$value$", "QuietUninstallString")
			If $value3 = "" Then $value3 = RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\$value$", "UninstallString")
			If (StringLeft($value, 1) <> "{") And ($value2 = "") Then $installedSoft.add($value)
			If $value2 <> "" Then $installedSoft.add($value2 & "|" & $value3)
			$i += 1
		WEnd
	EndIf
EndFunc   ;==>_scanInstalledSoftware


; by MrCreatoR: http://www.autoitscript.com/forum/index.php?showtopic=84190&view=findpost&p=603068
Func _ProcessCloseTree($iPID)
	If IsString($iPID) Then $iPID = ProcessExists($iPID) ;To get PID
	If Not $iPID Then Return SetError(1, 0, 0)

	Local $aProc_List = ProcessList()

	For $i = 1 To $aProc_List[0][0]
		If _ProcessGetParent($aProc_List[$i][1]) = $iPID Then ProcessClose($aProc_List[$i][1])
	Next

	ProcessClose($iPID)
EndFunc   ;==>_ProcessCloseTree

; by MrCreatoR: http://www.autoitscript.com/forum/index.php?showtopic=84190&view=findpost&p=603068
Func _ProcessGetParent($iPID)
	Local $wbemFlagReturnImmediately = 0x10
	Local $wbemFlagForwardOnly = 0x20
	Local $colItems = ""
	Local $strComputer = "localhost"

	$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
	$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

	If IsObj($colItems) Then
		For $objItem In $colItems
			If $objItem.ProcessID = $iPID Then Return $objItem.ParentProcessID
		Next
	EndIf

	Return SetError(1, 0, 0)
EndFunc   ;==>_ProcessGetParent


Func _isNewerVersion($_local, $_online)
	$parts1 = StringSplit($_local, ".")
	$parts2 = StringSplit($_online, ".")
	For $i = 1 To _Min(UBound($parts1), UBound($parts2)) - 1
		If Number($parts2[$i]) > Number($parts1[$i]) Then Return True
	Next
	If UBound($parts2) > UBound($parts1) Then Return True
	Return False
EndFunc   ;==>_isNewerVersion
#ce
Func ConsoleWriteLine($__text)
	ConsoleWrite($__text & @CRLF)
EndFunc   ;==>ConsoleWriteLine
#cs
Func _debug($_debug_msg, $_do = False)
	If $_do Then
		_LogToMain($_debug_msg)
	EndIf
EndFunc   ;==>_debug
#ce