Jump to content
Sign in to follow this  
MilesAhead

SaveVersion

Recommended Posts

MilesAhead

Script compiled with AutoIt3 3.3.8.0 32 bit Unicode English US

SaveVersion is a little kludge that copies ahk au3 and exe files that have file version info, to a filename with the version numbers added to the base filename. For example test.au3 version 1.0.0.0 would be copied to test_1_0_0_0.au3.

Mainly it's designed as an alternative to using Save A Copy inside SciTE. You may put a shortcut in SendTo folder to allow multiple file seletion then invoke via right click SendTo.

Usage:

SaveVersion /?

displays About Dialog

SaveVersion file1 file2 file3...

loops through the files prompting to save each. An error is displayed if no file version info found.

This usage has a sanity check. If more than 5 files on command line you are prompted to continue.

SaveVersion - with no args displays File Open Dialog where multiple files may be selected.

Note that for source files it's just a simple substring search. au3 files must have compile directives. Particularly the one with _FileVersion=. ahk files the directive section of the source must start with /* as the first line at start of line, and end with */

the string File_Version= is hunted for to get the file version numbers. If tools change to insert different strings as directives or you wish to enhance the program, that's why the source is provided. For me, simple like this works fine. It's just a convenience so I don't have to save my files with _SAVE or some other klunky device, and has the advantage the version numbers are out where I can see them.

exe files must be compiled with file version info. The dots in the numbers are changed to underscores just in case some code isn't "multi-dot aware" and assumes a dot is automatically followed by the file extension.

(Note the 2nd source file, MilesAheadMisc.au3 contains general purpose functions I include in my scripts. The program uses enough of these that it's better just to include the file instead of pasting at the bottom of the main program.)

Main program - SaveVersion.au3

edit: updated to 1.3.1.0 added All Files fo FileOpenDialog to allow choosing a mix of file types.

#NoTrayIcon
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=floppy.ico
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Res_Fileversion=1.3.1.0
#AutoIt3Wrapper_Res_LegalCopyright=2012  www.favessoft.com
#AutoIt3Wrapper_Res_Language=1033
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <MilesAheadMisc.au3>
Global $version = _ScriptVersion()
Global $fileName = "", $fileArray
Global $msg = _ScriptBaseName() & " " & $version & "  Copyright (c) " & @YEAR & "  www.favessoft.com" & @CRLF & @CRLF
$msg &= "Usage: SaveVersion [ /? ] or [ filename1 .. filename2 ... ]" & @CRLF & @CRLF
$msg &= "filename must be ..exe, .au3 or .ahk with file version info" & @CRLF & @CRLF
$msg &= "Au3 and Ahk requre source directives. Exe must be compiled with file version information" & @CRLF & @CRLF
$msg &= "Copies filname.ext to filename_n_n_n_n.ext (n being version numbers)" & @CRLF & @CRLF
$msg &= "SaveVersion /? shows this About Dialog" & @CRLF & @CRLF
$msg &= "SaveVersion  ( no args displays File Open Dialog )"
If $CmdLine[0] = 1 And $CmdLine[1] = "/?" Then
    _ShowUsage($msg)
EndIf
If Not $CmdLine[0] Or Not FileExists($CmdLine[1]) Then
    $fileName = FileOpenDialog("Select File(s) to Save Versioned", @WorkingDir, "Ahk Files (*.ahk)|Au3 Files (*.au3)|Exe Files (*.exe) |All Files (*.*)", 7)
    If @error Then
        _ShowError("No File Selected")
    EndIf
    If Not StringInStr($fileName, "|") Then
        _CopyVersioned($fileName)
    Else
        $fileArray = StringSplit($fileName, '|')
        For $x = 2 To $fileArray[0]
            _CopyVersioned($fileArray[1] & "" & $fileArray[$x])
        Next
    EndIf
    Exit
EndIf

; Sanity check
If $CmdLine[0] > 5 Then
    If MsgBox(0x1024, _ScriptBaseName(), $CmdLine[0] & " Files On Command Line: Process ??") = 7 Then
        _ShowUsage("User Terminated Processing")
    EndIf
EndIf
For $x = 1 To $CmdLine[0]
    _CopyVersioned($CmdLine[$x])
Next

Func _CopyVersioned($inFile)
    Local $outFile = _FileVersioned($inFile)
    If $inFile = $outFile Then
        _ShowError("No File Version Info Found for:" & @CRLF & @CRLF & $inFile, "", False)
        Return
    EndIf
    If MsgBox(0x1024, _ScriptBaseName(), "Copy " & $inFile & @CRLF & @CRLF & " to " & @CRLF & @CRLF & $outFile) = 6 Then
        If Not FileCopy($inFile, $outFile, 1) Then
            _ShowError("Error Saving Versioned Copy of: " & @CRLF & @CRLF & $inFile, "", False)
        EndIf
    EndIf
EndFunc   ;==>_CopyVersioned

general purpose include file - MilesAheadMisc.au3

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Res_Fileversion=1.1.1.1
#AutoIt3Wrapper_Res_LegalCopyright=2012  www.favessoft.com
#AutoIt3Wrapper_Res_Language=1033
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
;
;MilesAheadMisc.au3
;
;misc useful functions for
;inclusion in scripts.
;
;some functions are totatlly original.
;where adapted or used directly I give
;attribution when possible.
;
;MilesAhead
;
;Note: v.1.1.1.1 set arbitrarily on 2012/05/13 to use with my
;SaveVersion program
;
#include-once
#include <array.au3>
#include <file.au3>
#include <winapi.au3>
#include <apiconstants.au3>
#include <winapiex.au3>

; by ProgAndy on AutoIt3 forums
; returns Int($i) or 0 and sets @error to 1 on invalid input
;
; http://www.autoitscript.com/forum/topic/136142-integer-sets-error/page__view__findpost__p__951086
;
Func _Integer($i)
    If StringRegExp($i, "^s*[-+]?.?d") Then Return Int($i)
    Return SetError(1, 0, 0)
EndFunc   ;==>_Integer

;~ ; Empty Tray Icon Queue of events
;~ Func _EmptyTrayQ()
;~   Local $m = 0
;~   Do
;~       $m = TrayGetMsg()
;~   Until $m = 0
;~ EndFunc   ;==>_EmptyTrayQ

; Empty Tray Icon Queue of events
Func _EmptyTrayQ()
    While TrayGetMsg()
    WEnd
EndFunc   ;==>_EmptyTrayQ

;use Scripting.Dictionary object for simple associative arrays
Func _AssocArray()
    Local $aArray = ObjCreate("Scripting.Dictionary")
    If @error Then
        Return SetError(1, 0, 0)
    EndIf
    $aArray.CompareMode = 1
    Return $aArray
EndFunc   ;==>_AssocArray

Func _AssocArrayDestroy(ByRef $aArray)
    If Not IsObj($aArray) Then
        Return False
    EndIf
    $aArray.RemoveAll()
    $aArray = 0
    Return True
EndFunc   ;==>_AssocArrayDestroy

;filter out empty array strings ("")
Func _ArrayDelBlanks(ByRef $someArray)
    Local $index = -1
    While UBound($someArray) > 0
        $index = _ArraySearch($someArray, "")
        If $index > -1 Then
            _ArrayDelete($someArray, $index)
        Else
            ExitLoop
        EndIf
    WEnd
EndFunc   ;==>_ArrayDelBlanks

; $val is a string read by IniRead that
; should indicate if an option is
; enabled or disabled. The user can
; set it to True or 1 for enabled.
; (e.g. UseMiddleMouseClick=True)
;
; returns True if $val is "True" or "1"
; otherwise returns False
;
Func _IniBool($val)
    If $val = "True" Or $val = "1" Then Return True
    Return False
EndFunc   ;==>_IniBool

; When this is called the Active Window should be
; an Explorer Folder Window
;
; Success: Returns path of current folder
;
; Fail: Returns "" and sets @error
; @error = 1 if window is not an Explorer Window
; otherwise @error is set to 2
;
Func _ActiveFolderPath()
    Local $oldOption = AutoItSetOption("WinTitleMatchMode", 4)
    Local $handle = WinGetHandle("[Active]")
    Local $className = _WinAPI_GetClassName($handle)
    AutoItSetOption("WinTitleMatchMode", $oldOption)

    If $className <> "ExploreWClass" And $className <> "CabinetWClass" Then
        Return SetError(1, 0, "")
    EndIf
    Local $urlPath = _ExplorerURL($handle)
    If $urlPath <> "" Then
        Return _WinAPI_PathCreateFromUrl($urlPath)
    EndIf
    Return SetError(2, 0, "")
EndFunc   ;==>_ActiveFolderPath

; Gets URL path of window that matches $handle
; or "" if no match
;
Func _ExplorerURL($handle)
    Local $shApp = ObjCreate("Shell.Application")
    Local $windows = $shApp.Windows
    For $item In $windows
        ;If Not $item Then ContinueLoop
        If ($item.hwnd = $handle) Then
            Return $item.LocationURL
        EndIf
    Next
    Return ""
EndFunc   ;==>_ExplorerURL

; _PassKey() : Temporarily disables a hotkey, sends
; the key, then enables again.
;
; Returns 0 if either param is blank.
;
; Otherwise Returns the result of the HotKeySet()
; attempt to reset the hotkey.
;
; Not ready for Prime Time due to AutoIt saving state
; of modifier keys
;
;~ Func _PassKey($funcName, $hKey = @HotKeyPressed)
;~   If $funcName = "" Or $hKey = "" Then
;~       Return 0
;~   EndIf
;~   HotKeySet($hKey)
;~   Send($hKey)
;~   Return HotKeySet($hKey, $funcName)
;~ EndFunc   ;==>_PassKey

;confirms that input consists only of valid chars
Func _ValidateInput($inputStr, $validChars)
    For $x = 1 To StringLen($inputStr)
        If Not StringInStr($validChars, StringMid($inputStr, $x, 1)) Then
            Return False
        EndIf
    Next
    Return True
EndFunc   ;==>_ValidateInput

;InputBox to allow user to change hotkey modifier key
;ModKey chars must all be in $validChars string
;Returns $curModKey if user aborts entry
Func _EditHotkeyModifier($curModKey, $validChars)
    Local $newModKey = ""
    $prompt = "Usable Modifiers include:" & @CRLF
    $prompt &= "#   for Win Key" & @CRLF
    $prompt &= "!   for Alt Key" & @CRLF
    $prompt &= "^   for Control Key" & @CRLF
    $prompt &= "^!  for Control-Alt etc.." & @CRLF
    $newModKey = InputBox("Enter HotKey Modifier", $prompt, $curModKey)
    If $newModKey = "" Or $newModKey = $curModKey Then Return $curModKey
    If Not _ValidateInput($newModKey, $validChars) Then
        _ShowError("Invalid Hotkey Modiifer Specified : Keeping Current!", "", False)
        Return $curModKey
    EndIf
    Return $newModKey
EndFunc   ;==>_EditHotkeyModifier

;return the Windows version as a number or string
;according to $retAsString param.
;example 6.1 for Windows7, 6 for Vista,
;5.1 for XP etc.. as number, as string the
;minor version will be preserved even if .0
;(Vista returns "6.0" etc.)
;
Func _WinVersion($retAsString = 0)
    Local $dwVersion = DllCall("kernel32.dll", "dword", "GetVersion")
    Local $versionStr = String(BitAND($dwVersion[0], 0x00FF))
    $versionStr &= "." & String(BitShift(BitAND($dwVersion[0], 0xFF00), 8))
    If $retAsString Then Return $versionStr
    Return Number($versionStr)
EndFunc   ;==>_WinVersion

;_GetVersionEx()
;
;It calls the Ansi version of GetVersionEx() WinAPI
;
;On success returns zero based 5 element array of strings
;element 0 = OS Major;1 = OS Minor; 2 = build; 3 = platform; 4 = Version String
;note Version String may be an empty string or something like "Service Pack 1"
;
;On error returns 0 and sets @error to the value contained in @error macro.
;Sets @extended to 1 if error occurred in DllStructCreate(), 2 if error
;occurred in DllStructSetData(), or 3 if error occurred in DllCall()
;
Func _GetVersionEx()
    Local $OsArray[5] = [""]
    Local $osvi = DllStructCreate("dword size;dword OsMajor;dword OsMinor;dword build;dword platform;char verString[128]")
    If @error Then
        Return SetError(@error, 1, 0)
    EndIf
    DllStructSetData($osvi, "size", 148)
    If @error Then
        $osvi = 0
        Return SetError(@error, 2, 0)
    EndIf
    Local $retVal = DllCall("Kernel32.dll", "int", "GetVersionExA", "ptr", DllStructGetPtr($osvi))
    If @error Then
        $osvi = 0
        Return SetError(@error, 3, 0)
    EndIf
    $OsArray[0] = String(DllStructGetData($osvi, "OsMajor"))
    $OsArray[1] = String(DllStructGetData($osvi, "OsMinor"))
    $OsArray[2] = String(DllStructGetData($osvi, "build"))
    $OsArray[3] = String(DllStructGetData($osvi, "platform"))
    $OsArray[4] = DllStructGetData($osvi, "verString")
    $osvi = 0
    Return $OsArray
EndFunc   ;==>_GetVersionEx

; Call EmptyWorkingSet() API
; Returns
Func _EmptyWorkingSet()
    Local $result = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    Return $result[1]
EndFunc   ;==>_EmptyWorkingSet

; Reduce memory usage via EmptyWorkingSet()
; Author wOuter ( mostly ) on AutoIt3 forum
Func _ReduceMemory($i_PID = -1)
    If _WinVersion() < 5 Then Return False
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf

    Return $ai_Return[0]
EndFunc   ;==>_ReduceMemory

;returns non 0 if Glass is enabled on Vista/W7
Func _GlassEnabled()
    $retValue = DllCall("dwmapi.dll", "int", "DwmIsCompositionEnabled", "int*", "")
    If @error Then Return 0
    Return $retValue[1]
EndFunc   ;==>_GlassEnabled

;from Michael Michta on AutoIt3 forum
Func EnableBlurBehind($hWnd)
    Const $DWM_BB_ENABLE = 0x00000001
    $Struct = DllStructCreate("dword;int;ptr;int")
    DllStructSetData($Struct, 1, $DWM_BB_ENABLE)
    DllStructSetData($Struct, 2, "1")
    DllStructSetData($Struct, 4, "1")
    DllCall("dwmapi.dll", "int", "DwmEnableBlurBehindWindow", "hwnd", $hWnd, "ptr", DllStructGetPtr($Struct))
EndFunc   ;==>EnableBlurBehind

;if $Str contains a space wrap in double quotes
;
;useful for command line params of files that have
;a space in the file path
;
Func _QuoteStr($str)
    If StringInStr($str, " ") Then
        Return '"' & $str & '"'
    EndIf
    Return $str
EndFunc   ;==>_QuoteStr

; _WinAPI_PathFileExists($sFilePath)
; returns 1 if path exists, 0 otherwise
;
; alternative to FileExists function
;
; from guinness on AutoIt3 Forum
; http://www.autoitscript.com/forum/topic/19370-autoit-wrappers/page__view__findpost__p__953856
Func _WinAPI_PathFileExists($sFilePath)
    Local $aReturn = DllCall('shlwapi.dll', 'int', 'PathFileExistsW', 'wstr', $sFilePath)
    If @error Then
        Return SetError(1, 0, 0)
    EndIf
    Return $aReturn[0]
EndFunc   ;==>_WinAPI_PathFileExists

;returns True if $path is a directory
Func _DirectoryExists($path)
    If Not FileExists($path) Then Return False
    If StringInStr(FileGetAttrib($path), "D") > 0 Then Return True
    Return False
EndFunc   ;==>_DirectoryExists

;return True if $path exists and contains "D" directory attribute
Func _IsFolder($path)
    Local $attr = FileGetAttrib($path)
    If $attr = "" Then
        Return SetError(1, 0, False)
    ElseIf StringInStr($attr, "D") Then
        Return True
    Else
        Return False
    EndIf
EndFunc   ;==>_IsFolder

; returns 1 if path is valid, 0 otherwise
;
Func _ValidPath($path)
    If StringLeft($path, 2) = "" And Not StringInStr($path, ".") Then
        Return FileExists($path)
    EndIf
    Return _WinAPI_PathFileExists($path)
EndFunc   ;==>_ValidPath

; A drive passed in that consists of a letter and colon
; ( x: ) will be set to Upper Case and a slash appened ( X: )
;
; A drive passed in as x: will be set to Upper Case.
;
; The Function returns nothing.  Any changes are made to the
; input param.
;
Func _DriveUpSlash(ByRef $drive)
    If StringLen($drive) = 2 And StringRight($drive, 1) = ":" Then
        $drive = StringUpper($drive) & ""
    ElseIf StringRight($drive, 2) = ":" Then
        $drive = StringUpper($drive)
    EndIf
EndFunc   ;==>_DriveUpSlash

; return the basename part of a file path
; works only for files with extension
; e.g. returns "test" for c:foldertest.exe path
;
Func _FileBaseName($path)
    If $path = "" Then Return ""
    If StringLen($path) < 3 Then Return ""

    Local $pos = StringInStr($path, "", 0, -1)
    $pos += 1
    Local $tmp = StringMid($path, $pos)
    Return StringLeft($tmp, StringInStr($tmp, ".", 0, -1) - 1)
EndFunc   ;==>_FileBaseName

; Return Directory part of path with trailing slash
Func _FileDirWSlash($path)
    Return StringLeft($path, StringInStr($path, "", 0, -1))
EndFunc   ;==>_FileDirWSlash

; Return Directory part of path without trailing slash
Func _FileDirNoSlash($path)
    Return StringLeft($path, StringInStr($path, "", 0, -1) - 1)
EndFunc   ;==>_FileDirNoSlash

; return _FileBaseName with hash appended instead of using full path
;
Func _BaseFileStr($path)
    Return _FileBaseName($path) & _HashString32($path)
EndFunc   ;==>_BaseFileStr

; return the '.ext' part of path no matter how long the ext
; as in image.jpg returns '.jpg' or image.jpeg returns '.jpeg'
;
Func _FileExt($path)
    If $path = "" Then Return ""
    Local $pos = StringInStr($path, ".", 0, -1)
    If $pos = 0 Then Return ""
    Return StringMid($path, $pos)
EndFunc   ;==>_FileExt

; return entire path without last extension
; (e.g. c:FolderText.txt returns c:FolderText)
;
Func _PathNoExt($path)
    If Not StringInStr($path, ".") Then Return $path
    Return StringLeft($path, StringInStr($path, ".", 0, -1) - 1)
EndFunc   ;==>_PathNoExt

;returns filename without drive or path
Func _FileNoPath($path)
    Local $pos = StringInStr($path, "", 0, -1)
    If Not $pos Then
        $pos = StringInStr($path, ":")
    EndIf
    If Not $pos Then Return $path
    Return StringMid($path, $pos + 1)
EndFunc   ;==>_FileNoPath

;filter out percent signs, spaces, and illegal filename chars
;and substitute underscores. Optionally chop off return str
;at $maxLen chars.
;
;
Func _NormalizeFilename($inFilename, $maxLen = 0)
    Local Const $illegalFilenameChars = "?[]/=+<>:;"",* %"
    Local $c = ""
    Local $fixedFilename = ""

    For $x = 1 To StringLen($inFilename)
        $c = StringMid($inFilename, $x, 1)
        If StringInStr($illegalFilenameChars, $c) Then
            $c = "_"
        EndIf
        $fixedFilename &= $c
    Next
    If $maxLen Then
        Return StringLeft($fixedFilename, $maxLen)
    EndIf
    Return $fixedFilename
EndFunc   ;==>_NormalizeFilename

;return @ScriptName without extension
;useful for MsgBox titles or path
;building
;
Func _ScriptBaseName()
    Return StringLeft(@ScriptName, (StringInStr(@ScriptName, ".") - 1))
EndFunc   ;==>_ScriptBaseName

;a one-liner but saves thinking about it :)
;
Func _ScriptIniFileName()
    Return @ScriptDir & "" & _ScriptBaseName() & ".ini"
EndFunc   ;==>_ScriptIniFileName

; _ScriptVersion($Script = @ScriptFullPath)
; Returns File Version string from .exe, .au3 or .ahk script.
; Returns "" if no version info available.
;
; Note: The .au3 or .ahk script must contain compiler
; directives with file version info or "" is returned.
;
; Sets @error: 1 = file open error : 2 = unsupported file type
;
Func _ScriptVersion($Script = @ScriptFullPath)
    Local $ver = "", $scriptHandle = -1, $found = False, $sPos = 0
    If StringRight($Script, 4) = ".exe" Then
        Return FileGetVersion($Script)
    ElseIf StringRight($Script, 4) = ".au3" Then
        $scriptHandle = FileOpen($Script)
        If $scriptHandle = -1 Then Return SetError(1, 0, "")
        Do
            $ver = FileReadLine($scriptHandle)
            $sPos = StringInStr($ver, "Fileversion=")
            If $sPos Then
                $ver = StringMid($ver, $sPos + StringLen("Fileversion="))
                $found = True
                ExitLoop
            EndIf
        Until StringLeft($ver, 1) <> "#"
        FileClose($scriptHandle)
    ElseIf StringRight($Script, 4) = ".ahk" Then
        $scriptHandle = FileOpen($Script)
        If $scriptHandle = -1 Then Return SetError(1, 0, "")
        $ver = FileReadLine($scriptHandle)

        If StringLeft($ver, 2) <> "/*" Then Return "" ; lacks directives
        Do
            $ver = FileReadLine($scriptHandle)
            $sPos = StringInStr($ver, "File_Version=")
            If $sPos Then
                $ver = StringMid($ver, $sPos + StringLen("File_Version="))
                $found = True
                ExitLoop
            EndIf
        Until StringLeft($ver, 2) = "*/"
        FileClose($scriptHandle)
    Else
        SetError(2, 0, "")
    EndIf
    If Not $found Then $ver = ""
    Return $ver
EndFunc   ;==>_ScriptVersion

; Returns script with version suffix added before
; the extension. (e.g. script.au3 would return
; script_1_0_0_0.au3 if file version 1.0.0.0
;
; Requires .exe with file version info, au3 or
; .ahk with compiler directives containing
; file version info.
;
; Sets @error to _ScriptVersion() error code.
; If no file info returns $Script unmodified.
;
Func _FileVersioned($Script)
    Local $suffix = _ScriptVersion($Script)
    If @error Or Not $suffix Then Return SetError(@error, 0, $Script)
    Return _PathNoExt($Script) & "_" & StringReplace($suffix, ".", "_") & _FileExt($Script)
EndFunc   ;==>_FileVersioned

; #FUNCTION# ====================================================================================================================
; Name...........: _FileInPath
; Description ...: Returns the location in the PATH environment variable containing a file
; Syntax.........: _FileInPath( $sFilename )
; Parameters ....: $sFilename - The file to search for (filename only, no folders)
; Return values .: Success - Returns the path to the file and set @error=0 (@extended=1 a specified path and the file is there)
;                 Failure - Returns "" and sets @error:
;                 |1 - File not found in @WorkingDir or the PATH (@extended=1 if PATH is blank)
;                 |2 - Could not StringSplit the PATH
; Author ........: Gigglestick (c0deWorm)
; Modified.......: Comments added and logic modified
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _FileInPath($asFilename)
    If StringInStr($asFilename, "") Then
        If FileExists($asFilename) Then
            ; if a full or relative path was specified and the file exists then return the path
            Return SetError(0, 1, $asFilename)
        Else
            ; if a path was specified and the file does not exist then return "file not found" error
            Return SetError(1, 0, "")
        EndIf
    EndIf
    ; if the file is found in the current working directory then return the absolute file path
    If FileExists(@WorkingDir & "" & $asFilename) Then Return SetError(0, 0, @WorkingDir & "" & $asFilename)
    Local $i, $lasPath, $lsPath = EnvGet("PATH")
    ; if variable containing PATH is empty then return "file not found" error and @extended=2
    If StringLen($lsPath) = 0 Then Return SetError(1, 1, "")
    ; if PATH is set but only has one entry then check it
    If StringLen($lsPath) > 0 And Not StringInStr($lsPath, ";") Then
        If FileExists($lsPath & "" & $asFilename) Then
            ; if the filename is found in the single PATH entry then return the file path
            Return SetError(0, 0, $lsPath & "" & $asFilename)
        Else
            ; if PATH is a single entry and does not contain the filename then return "file not found" error
            Return SetError(1, 0, "")
        EndIf
    EndIf
    ; remove any blank entries (double semicolons)
    While StringInStr($lsPath, ";;")
        $lsPath = StringReplace($lsPath, ";;", ";")
    WEnd
    ; split variable containing PATH into an array of single paths
    $lasPath = StringSplit($lsPath, ";")
    ; if ";" not found in split then return error
    If @error Then Return SetError(2, 0, "")
    ; loop through array of single paths, searching for absolute file path and return absolute file path if found
    For $i = 1 To $lasPath[0]
        If FileExists($lasPath[$i] & "" & $asFilename) Then Return SetError(0, 0, $lasPath[$i] & "" & $asFilename)
    Next
    ; unable to find filename in current working directory or PATH so return error
    Return SetError(1, 0, "")
EndFunc   ;==>_FileInPath

; Ascend4nt on AutoIt3 forum
; Open Property Page to specified Tab
; e.g. _FileOpenPropertiesDialog("notepad.exe","Details")
;
; http://www.autoitscript.com/forum/topic/118673-open-a-files-properties-window/page__view__findpost__p__825420
;
Func _FILEPropertiesDialog($sObjName, $sPropPage = "", $iObjType = 0x02, $hWnd = 0)
    Local $sPropPageType = "ptr"
    If IsString($sPropPage) And $sPropPage <> "" Then
        $sPropPageType = "wstr"
    Else
        $sPropPage = 0
    EndIf
    Local $aRet = DllCall("shell32.dll", "bool", "SHObjectProperties", "hwnd", $hWnd, "dword", $iObjType, "wstr", $sObjName, $sPropPageType, $sPropPage)
    If @error Then Return SetError(2, @error, False)
    If Not $aRet[0] Then Return SetError(3, 0, False)
    Return True
EndFunc   ;==>_FILEPropertiesDialog

;Check FavesSoft Server for newer version with optional download
;If user downloads, the script directory and zip file will be
;opened, and the calling program exited.
;
Func _Check4Update($verIniFile = "FavesVersions.ini", $url = "http://www.favessoft.com/", $maxCount = 10)
    Local $count = 0
    Local $iniFile = @ScriptDir & "" & $verIniFile
    Local $hDownload = InetGet($url & $verIniFile, $iniFile, 1, 1)
    Local $localFile = ""
    Do
        $count += 1
        If $count > $maxCount Then ExitLoop
        Sleep(250)
    Until InetGetInfo($hDownload, 2)
    InetClose($hDownload)
    If $count > $maxCount Then
        _ShowError("Server Access Failed!", "", False)
        Return False
    EndIf
    Local $v = IniRead($iniFile, "Versions", _ScriptBaseName(), "")
    If $v = "" Then
        _ShowError("Version Info Not Found!", "", False)
        If FileExists($iniFile) Then
            FileDelete($iniFile)
        EndIf
        Return False
    EndIf
    Local $t = FileGetVersion(@ScriptFullPath)
    If $v > $t Then
        If MsgBox(0x1044, _ScriptBaseName(), "Current Version is " & $t & " Online Version is " & $v & " : Download?") = 6 Then
            $d = IniRead($iniFile, "Downloads", _ScriptBaseName(), "")
            If $d <> "" Then
                $localFile = @ScriptDir & "" & $d
                $hDownload = InetGet($url & $d, $localFile, 1, 1)
                $count = 0
                Do
                    $count += 1
                    If $count > $maxCount Then ExitLoop
                    Sleep(250)
                Until InetGetInfo($hDownload, 2)
                InetClose($hDownload)
                If $count <= $maxCount Then
                    ShellExecute($localFile)
                    ShellExecute(@ScriptDir)
                    If FileExists($iniFile) Then
                        FileDelete($iniFile)
                    EndIf
                    Exit
                Else
                    _ShowError("Download Attempt Failed!", "", False)
                    If FileExists($iniFile) Then
                        FileDelete($iniFile)
                    EndIf
                    Return False
                EndIf
            Else
                _ShowError("Download Info Not Found!", "", False)
                If FileExists($iniFile) Then
                    FileDelete($iniFile)
                EndIf
                Return False
            EndIf
        Else
            If FileExists($iniFile) Then
                FileDelete($iniFile)
            EndIf
            Return True
        EndIf
    Else
        MsgBox(0x1040, _ScriptBaseName(), $t & " is the latest version")
    EndIf
    If FileExists($iniFile) Then
        FileDelete($iniFile)
    EndIf
EndFunc   ;==>_Check4Update

;show an error msg and optionally quit, with optional timeout
Func _ShowError($errorMsg, $title = "", $quit = True, $timeOut = 0)
    If $title = "" Then $title = _ScriptBaseName()
    MsgBox(0x1010, $title, $errorMsg, $timeOut)
    If $quit Then Exit
EndFunc   ;==>_ShowError

;show usage msg and optionally quit with optional timeout
Func _ShowUsage($usageMsg, $title = "", $quit = True, $timeOut = 0)
    If $title = "" Then $title = _ScriptBaseName()
    MsgBox(0x1040, $title, $usageMsg, $timeOut)
    If $quit Then Exit
EndFunc   ;==>_ShowUsage

;write AssocArray to IniFile Section
;returns 1 on success - sets @error on failure
Func _WriteAssocToIni($myAssoc, $myIni, $mySection)
    $retVal = 0
    If $myAssoc.Count() < 1 Then
        Return SetError(1, 0, 0)
    EndIf
    Local $iArray[$myAssoc.Count()][2]
    Local $aArray = $myAssoc.Keys()
    For $x = 0 To UBound($aArray) - 1
        $iArray[$x][0] = $aArray[$x]
        $iArray[$x][1] = _MakePosString($myAssoc($aArray[$x]))
    Next
    $retVal = IniWriteSection($myIni, $mySection, $iArray, 0)
    Return SetError(@error, 0, $retVal)
EndFunc   ;==>_WriteAssocToIni

;read AssocArray from IniFile Section
;returns number of items read - sets @error on failure
Func _ReadAssocFromIni(ByRef $myAssoc, $myIni, $mySection)
    Local $sectionArray = IniReadSection($myIni, $mySection)
    If @error Then Return SetError(1, 0, 0)
    Local $posA[9]
    Local $posS
    For $x = 1 To $sectionArray[0][0]
        $posS = _MakePosArray($sectionArray[$x][1])
        For $y = 0 To UBound($posS) - 1
            $posA[$y] = Number($posS[$y])
            If $posA[$y] < 0 Then ContinueLoop 2
        Next
        $myAssoc($sectionArray[$x][0]) = $posA
    Next
    Return $sectionArray[0][0]
EndFunc   ;==>_ReadAssocFromIni

;from _SDBM32 by trancexx on AutoIt3 forum
Func _HashString32($sString)

    Local $aArray = StringToASCIIArray($sString)
    Local $iHash = 0

    For $i = 0 To UBound($aArray) - 1
        $iHash = $aArray[$i] + BitShift($iHash, -6) + BitShift($iHash, -16) - $iHash
    Next

    Return Hex($iHash)

EndFunc   ;==>_HashString32

;makes a Position string using '#' number separator
Func _MakePosString($posArray)
    Local $str = ""
    For $x = 0 To UBound($posArray) - 2
        $str &= String($posArray[$x]) & "#"
    Next
    $str &= String($posArray[UBound($posArray) - 1])
    Return $str
EndFunc   ;==>_MakePosString

;makes a Position array from a Position string
Func _MakePosArray($posString)
    Return StringSplit($posString, "#", 2)
EndFunc   ;==>_MakePosArray

;show msgbox without sound and optionally quit with optional timeout
Func _ShowSilent($usageMsg, $title = "", $quit = True, $timeOut = 0)
    If $title = "" Then $title = _ScriptBaseName()
    MsgBox(0xA0, $title, $usageMsg, $timeOut)
    If $quit Then Exit
EndFunc   ;==>_ShowSilent

; Get the execuatble path of a window
; Author gafrost on AutoIt3 forum
Func _WinGetPath($title = "", $strComputer = 'localhost')
    Local $win = WinGetTitle($title)
    Local $pid = WinGetProcess($win)
    Local $wbemFlagReturnImmediately = 0x10
    Local $wbemFlagForwardOnly = 0x20
    Local $colItems = ""
    Local $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootCIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE ProcessId = " & $pid, "WQL", _
            $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) Then
        For $objItem In $colItems
            If $objItem.ExecutablePath Then Return $objItem.ExecutablePath
        Next
    EndIf
    Return ""
EndFunc   ;==>_WinGetPath

; _GetWindowExePath($WindowTitle = "[ACTIVE]")
;
; Returns complete path to Exe that owns window
; on error sets @error and returns ""
;
Func _GetWindowExePath($WindowTitle = "[ACTIVE]")
    Local $pid = WinGetProcess($WindowTitle)
    If $pid = -1 Then Return SetError(1, 0, "")
    Local $pHandle = _WinAPI_OpenProcess(0x410, False, $pid)
    If @error Then Return SetError(1, 1, "")
    Local $result = _WinAPI_GetModuleFileNameEx($pHandle)
    _WinAPI_CloseHandle($pHandle)
    If $result = "" Then Return SetError(@error, 2, "")
    Return $result
EndFunc   ;==>_GetWindowExePath

; _GetWindowExeCommandLine($WindowTitle = "[ACTIVE]")
;
; Returns command line for program associated with
; window $WindowTitle, if there is one.  Sets @error
; on failure.
;
Func _GetWindowExeCommandLine($WindowTitle = "[ACTIVE]")
    Local $procCmdLine = ""
    Local $pid = WinGetProcess($WindowTitle)
    If $pid = -1 Then Return SetError(1, 0, "")
    Local $pHandle = _WinAPI_OpenProcess(0x410, False, $pid)
    If @error Then Return SetError(1, 1, "")
    $procCmdLine = _WinAPI_GetProcessCommandLine($pid)
    _WinAPI_CloseHandle($pHandle)
    Return $procCmdLine
EndFunc   ;==>_GetWindowExeCommandLine

; _WindowExeInfo(ByRef $exePath, ByRef $cmdTail, ByRef $workDir, $WindowTitle = "[ACTIVE]")
; on success sets $exePath to executable path of program associated with
; window $WindowTitle and $cmdTail with it's command line args, if any.
;
; Returns 1 on success, 0 otherwise and sets @error.
;
Func _WindowExeInfo(ByRef $exePath, ByRef $cmdTail, ByRef $workDir, $WindowTitle = "[ACTIVE]")
    $exePath = ""
    $cmdTail = ""
    $workDir = ""
    Local $pid = WinGetProcess($WindowTitle)
    If $pid = -1 Then Return SetError(1, 0, 0)
    Local $pHandle = _WinAPI_OpenProcess(0x410, False, $pid)
    If @error Then Return SetError(1, 1, 0)
    $exePath = _WinAPI_GetModuleFileNameEx($pHandle)
    If $exePath = "" Then
        _WinAPI_CloseHandle($pHandle)
        Return SetError(1, 2, 0)
    EndIf
    $workDir = _WinAPI_GetProcessWorkingDirectory($pid)
    If @error Then
        _WinAPI_CloseHandle($pHandle)
        Return SetError(1, 3, 0)
    EndIf
    $cmdTail = _WinAPI_GetProcessCommandLine($pid)
    _WinAPI_CloseHandle($pHandle)
    Return 1
EndFunc   ;==>_WindowExeInfo

;AutoIt3 Forum code to get Desktop WorkArea
Func _GetDesktopWorkArea(ByRef $left, ByRef $top, ByRef $right, ByRef $bottom)
    Local Const $SPI_SETWORKAREA = 47
    Local Const $SPI_GETWORKAREA = 48
    Local $tRcWA = DllStructCreate($tagRECT)

    If _WinAPI_SystemParametersInfo($SPI_GETWORKAREA, 0, DllStructGetPtr($tRcWA)) Then
        $left = DllStructGetData($tRcWA, "Left")
        $right = DllStructGetData($tRcWA, "Right")
        $top = DllStructGetData($tRcWA, "Top")
        $bottom = DllStructGetData($tRcWA, "Bottom")
        Return True
    EndIf
    Return False
EndFunc   ;==>_GetDesktopWorkArea

Func _SetDesktopWorkArea($left, $top, $right, $bottom)
    Local Const $SPI_SETWORKAREA = 47
    Local Const $SPI_GETWORKAREA = 48
    Local $tRcWA = DllStructCreate($tagRECT)

    DllStructSetData($tRcWA, "Left", $left)
    DllStructSetData($tRcWA, "Top", $top)
    DllStructSetData($tRcWA, "Right", $right)
    DllStructSetData($tRcWA, "Bottom", $bottom)

    Return _WinAPI_SystemParametersInfo($SPI_SETWORKAREA, 0, DllStructGetPtr($tRcWA))
EndFunc   ;==>_SetDesktopWorkArea

Func _DesktopMarginArea(ByRef $left, ByRef $top, ByRef $right, ByRef $bottom, $margin = 4)
    Local $l, $t, $r, $b
    Local $m = Int($margin)
    If $m < 0 Or $m > 12 Then $m = 4

    If $m = 0 Then
        _GetDesktopWorkArea($left, $top, $right, $bottom)
    Else
        _GetDesktopWorkArea($l, $t, $r, $b)
        $left = $l + $m
        $top = $t + $m
        $right = $r - $m
        $bottom = $b - $m
    EndIf
EndFunc   ;==>_DesktopMarginArea

Func _DesktopTaskbarGap(ByRef $left, ByRef $top, ByRef $right, ByRef $bottom, $percentMargin = 5)
    _GetDesktopWorkArea($left, $top, $right, $bottom)
    If $right - $left = @DesktopWidth And $bottom - $top = @DesktopHeight Then
        Return
    EndIf
    If $bottom < @DesktopHeight Then
        $bottom -= Int($bottom / 100 * $percentMargin)
    ElseIf $top > 0 Then
        $top += Int(($bottom - $top) / 100 * $percentMargin)
    ElseIf $left > 0 Then
        $left += Int(($right - $left) / 100 * $percentMargin)
    Else
        $right -= Int(($right - $left) / 100 * $percentMargin)
    EndIf
EndFunc   ;==>_DesktopTaskbarGap

; Set Desktop Work Area with percent gap next to Taskbar
Func _DesktopSetTaskbarGap($percentMargin = 5)
    Local $l, $t, $r, $b
    _DesktopTaskbarGap($l, $t, $r, $b, $percentMargin)
    Return _SetDesktopWorkArea($l, $t, $r, $b)
EndFunc   ;==>_DesktopSetTaskbarGap

; _ShowFolders($folders, $percentGap = 5)
;
; Show folders leaving TaskBar Gap
; ---------------------------------
; $folders[0] must have the folder count
; $percentGap is the percent of screen width
; or height to leave next to the Taskbar.
; If TaskbarGap.exe is running, $percentGap
; is set to 0 since it is assumed TaskbarGap
; has set the work area to allow for the gap.
;
; Does not Return a value
;
Func _ShowFolders($folders, $percentGap = 5, $moveOnly = False)
    If Not IsArray($folders) Then Return
    Local $l = -1, $t = -1, $r = -1, $b = -1
    Local $oldMatchMode = AutoItSetOption("WinTitleMatchMode", -3)
    If ProcessExists("TaskbarGap.exe") Then
        $percentGap = 0
    EndIf
    _DesktopTaskbarGap($l, $t, $r, $b, $percentGap)
    Local $sleepVal = 2500
    Local $s = $folders[0]
    Local $h = $b - $t
    Local $w = ($r - $l) / $s
    Local $w3 = 0, $w4 = 0
    $w3 = ($r - $l) / 3
    $w4 = ($r - $l) / 4
    If $s > 4 Then $sleepVal = 4000
    If $s > 6 Then $sleepVal = 4500
    If $s >= 4 Then
        $h = ($b - $t) / 2
    EndIf
    If $s > 8 Then
        WinMinimizeAll()
        Sleep(50)
    EndIf
    If Not $moveOnly Then
        For $x = 1 To $s
            ShellExecute("explorer.exe", "/e," & $folders[$x], "", "open")
        Next
        Sleep($sleepVal)
        WinWait($folders[$s], "", 8)
    EndIf
    If $s > 8 Then
        _TileHorizontal()
    ElseIf $s = 8 Then
        $w *= 2
        WinMove($folders[1], "", $l, $t, $w - 1, $h - 2)
        WinMove($folders[2], "", $l + $w, $t, $w - 1, $h - 2)
        WinMove($folders[3], "", $l + 2 * $w, $t, $w - 1, $h - 2)
        WinMove($folders[4], "", $l + 3 * $w, $t, $w - 1, $h - 2)
        WinMove($folders[5], "", $l, $t + $h, $w - 1, $h - 2)
        WinMove($folders[6], "", $l + $w, $t + $h, $w - 1, $h - 2)
        WinMove($folders[7], "", $l + 2 * $w, $t + $h, $w - 1, $h - 2)
        WinMove($folders[8], "", $l + 3 * $w, $t + $h, $w - 1, $h - 2)
    ElseIf $s = 7 Then
        WinMove($folders[1], "", $l, $t, $w3 - 1, $h - 2)
        WinMove($folders[2], "", $l + $w3, $t, $w3 - 1, $h - 2)
        WinMove($folders[3], "", $l + 2 * $w3, $t, $w3 - 1, $h - 2)
        WinMove($folders[4], "", $l, $t + $h, $w4 - 1, $h - 2)
        WinMove($folders[5], "", $l + $w4, $t + $h, $w4 - 1, $h - 2)
        WinMove($folders[6], "", $l + 2 * $w4, $t + $h, $w4 - 1, $h - 2)
        WinMove($folders[7], "", $l + 3 * $w4, $t + $h, $w4 - 1, $h - 2)
    ElseIf $s = 6 Then
        $w *= 2
        WinMove($folders[1], "", $l, $t, $w - 1, $h - 2)
        WinMove($folders[2], "", $l + $w, $t, $w - 1, $h - 2)
        WinMove($folders[3], "", $l + 2 * $w, $t, $w - 1, $h - 2)
        WinMove($folders[4], "", $l, $t + $h, $w - 1, $h - 2)
        WinMove($folders[5], "", $l + $w, $t + $h, $w - 1, $h - 2)
        WinMove($folders[6], "", $l + 2 * $w, $t + $h, $w - 1, $h - 2)
    ElseIf $s = 5 Then
        WinMove($folders[1], "", $l, $t, $w3 - 1, $h - 2)
        WinMove($folders[2], "", $l + $w3, $t, $w3 - 1, $h - 2)
        WinMove($folders[3], "", $l + 2 * $w3, $t, $w3 - 1, $h - 2)
        WinMove($folders[4], "", $l, $t + $h, (($r - $l) / 2) - 1, $h - 2)
        WinMove($folders[5], "", $l + ($r - $l) / 2, $t + $h, (($r - $l) / 2) - 1, $h - 2)
    ElseIf $s = 4 Then
        $w *= 2
        WinMove($folders[1], "", $l, $t, $w - 1, $h - 2)
        WinMove($folders[2], "", $l + $w, $t, $w - 1, $h - 2)
        WinMove($folders[3], "", $l, $t + $h, $w - 1, $h - 2)
        WinMove($folders[4], "", $l + $w, $t + $h, $w - 1, $h - 2)
    Else
        For $x = 1 To $s
            WinMove($folders[$x], "", $l, $t, $w - 1, $h - 2)
            $l += $w
        Next
    EndIf
    AutoItSetOption("WinTitleMatchMode", $oldMatchMode)
EndFunc   ;==>_ShowFolders

;tile windows horizontally
Func _TileHorizontal()
    DllCall("user32.dll", "int", "TileWindows", "int", 0, "int", 1, "int", 0, "int", 0, "int", 0)
EndFunc   ;==>_TileHorizontal

Func _TileVertical()
    DllCall("user32.dll", "int", "TileWindows", "int", 0, "int", 0, "int", 0, "int", 0, "int", 0)
EndFunc   ;==>_TileVertical

;AutoIt3 Forum code to get multiple monitor metrics
Func _GetVirtualMetrics(ByRef $vWidth, ByRef $vHeight)
    Local Const $SM_VIRTUALWIDTH = 78
    Local Const $SM_VIRTUALHEIGHT = 79
    Local $VirtualDesktopWidth = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_VIRTUALWIDTH)
    Local $VirtualDesktopHeight = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_VIRTUALHEIGHT)
    $vWidth = $VirtualDesktopWidth[0]
    $vHeight = $VirtualDesktopHeight[0]
EndFunc   ;==>_GetVirtualMetrics

; by SmOke_N on AutoIt3 Forum
; http://www.autoitscript.com/forum/topic/41639-windows-from-process/page__view__findpost__p__310089
; set $iPID to program name such as "notepad.exe"
; $nArray = 0 will return 1 base array; leaving it 1 will return the first visible window it finds
Func _WinGetByPID($iPID, $nArray = 1)
    If IsString($iPID) Then $iPID = ProcessExists($iPID)
    Local $aWList = WinList(), $sHold
    For $iCC = 1 To $aWList[0][0]
        If WinGetProcess($aWList[$iCC][1]) = $iPID And _
                BitAND(WinGetState($aWList[$iCC][1]), 2) Then
            If $nArray Then Return $aWList[$iCC][0]
            $sHold &= $aWList[$iCC][0] & Chr(1)
        EndIf
    Next
    If $sHold Then Return StringSplit(StringTrimRight($sHold, 1), Chr(1))
    Return SetError(1, 0, 0)
EndFunc   ;==>_WinGetByPID
Edited by MilesAhead

Share this post


Link to post
Share on other sites
MilesAhead

For those who don't have WinAPIEx.au3 UDF here's the script stripped by Obfuscator and cleaned up a bit. To skip to the main part of the script search "Main Program Start"

edit: Note that when getting the version of an exe, if it's a compiled AutoIt3 the version number returned may be the version of AutoIt3 installed on the system when the program was compiled. I don't know if there's some other property flag that can tell if the version just happens to be 3.3.8.0 or if it signifies the version of AutoIt.

#NoTrayIcon
Global Const $READ_CONTROL = 0x00020000
Global Const $STANDARD_RIGHTS_REQUIRED = 0x000f0000
Global Const $STANDARD_RIGHTS_READ = $READ_CONTROL
Global Const $STANDARD_RIGHTS_WRITE = $READ_CONTROL
Global Const $STANDARD_RIGHTS_ALL = 0x001F0000
Global Const $HGDI_ERROR = Ptr(-1)
Global Const $INVALID_HANDLE_VALUE = Ptr(-1)
Global Const $KF_EXTENDED = 0x0100
Global Const $KF_ALTDOWN = 0x2000
Global Const $KF_UP = 0x8000
Global Const $LLKHF_EXTENDED = BitShift($KF_EXTENDED, 8)
Global Const $LLKHF_ALTDOWN = BitShift($KF_ALTDOWN, 8)
Global Const $LLKHF_UP = BitShift($KF_UP, 8)
Global Const $BF_BOTTOM = 0x8
Global Const $BF_DIAGONAL = 0x10
Global Const $BF_LEFT = 0x1
Global Const $BF_RIGHT = 0x4
Global Const $BF_TOP = 0x2
Global Const $BF_RECT = BitOR($BF_LEFT, $BF_TOP, $BF_RIGHT, $BF_BOTTOM)
Global Const $BF_DIAGONAL_ENDBOTTOMLEFT = BitOR($BF_DIAGONAL, $BF_BOTTOM, $BF_LEFT)
Global Const $BF_DIAGONAL_ENDBOTTOMRIGHT = BitOR($BF_DIAGONAL, $BF_BOTTOM, $BF_RIGHT)
Global Const $BF_DIAGONAL_ENDTOPLEFT = BitOR($BF_DIAGONAL, $BF_TOP, $BF_LEFT)
Global Const $BF_DIAGONAL_ENDTOPRIGHT = BitOR($BF_DIAGONAL, $BF_TOP, $BF_RIGHT)
Global Const $WS_MINIMIZEBOX = 0x00020000
Global Const $WS_SYSMENU = 0x00080000
Global Const $WS_CAPTION = 0x00C00000
Global Const $WS_POPUP = 0x80000000
Global Const $WS_EX_TOOLWINDOW = 0x00000080
Global Const $WS_EX_TOPMOST = 0x00000008
Global Const $WS_EX_WINDOWEDGE = 0x00000100
Global Const $GUI_SS_DEFAULT_GUI = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
Global Const $WS_EX_PALETTEWINDOW = BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)
Global Const $DESKTOP_CREATEMENU = 0x0004
Global Const $DESKTOP_CREATEWINDOW = 0x0002
Global Const $DESKTOP_ENUMERATE = 0x0040
Global Const $DESKTOP_HOOKCONTROL = 0x0008
Global Const $DESKTOP_JOURNALPLAYBACK = 0x0020
Global Const $DESKTOP_JOURNALRECORD = 0x0010
Global Const $DESKTOP_READOBJECTS = 0x0001
Global Const $DESKTOP_SWITCHDESKTOP = 0x0100
Global Const $DESKTOP_WRITEOBJECTS = 0x0080
Global Const $DESKTOP_ALL_ACCESS = BitOR($DESKTOP_CREATEMENU, $DESKTOP_CREATEWINDOW, $DESKTOP_ENUMERATE, $DESKTOP_HOOKCONTROL, $DESKTOP_JOURNALPLAYBACK, $DESKTOP_JOURNALRECORD, $DESKTOP_READOBJECTS, $DESKTOP_SWITCHDESKTOP, $DESKTOP_WRITEOBJECTS)
Global Const $FILE_APPEND_DATA = 0x0004
Global Const $FILE_DELETE_CHILD = 0x0040
Global Const $FILE_EXECUTE = 0x0020
Global Const $FILE_READ_ATTRIBUTES = 0x0080
Global Const $FILE_READ_DATA = 0x0001
Global Const $FILE_READ_EA = 0x0008
Global Const $FILE_WRITE_ATTRIBUTES = 0x0100
Global Const $FILE_WRITE_DATA = 0x0002
Global Const $FILE_WRITE_EA = 0x0010
Global Const $FILE_ALL_ACCESS = BitOR($STANDARD_RIGHTS_ALL, $FILE_APPEND_DATA, $FILE_DELETE_CHILD, $FILE_EXECUTE, $FILE_READ_ATTRIBUTES, $FILE_READ_DATA, $FILE_READ_EA, $FILE_WRITE_ATTRIBUTES, $FILE_WRITE_DATA, $FILE_WRITE_EA)
Global Const $SECTION_EXTEND_SIZE = 0x0010
Global Const $SECTION_MAP_EXECUTE = 0x0008
Global Const $SECTION_MAP_READ = 0x0004
Global Const $SECTION_MAP_WRITE = 0x0002
Global Const $SECTION_QUERY = 0x0001
Global Const $SECTION_ALL_ACCESS = BitOR($STANDARD_RIGHTS_REQUIRED, $SECTION_EXTEND_SIZE, $SECTION_MAP_EXECUTE, $SECTION_MAP_READ, $SECTION_MAP_WRITE, $SECTION_QUERY)
Global Const $WINSTA_ACCESSCLIPBOARD = 0x0004
Global Const $WINSTA_ACCESSGLOBALATOMS = 0x0020
Global Const $WINSTA_CREATEDESKTOP = 0x0008
Global Const $WINSTA_ENUMDESKTOPS = 0x0001
Global Const $WINSTA_ENUMERATE = 0x0100
Global Const $WINSTA_EXITWINDOWS = 0x0040
Global Const $WINSTA_READATTRIBUTES = 0x0002
Global Const $WINSTA_READSCREEN = 0x0200
Global Const $WINSTA_WRITEATTRIBUTES = 0x0010
Global Const $WINSTA_ALL_ACCESS = BitOR($WINSTA_ACCESSCLIPBOARD, $WINSTA_ACCESSGLOBALATOMS, $WINSTA_CREATEDESKTOP, $WINSTA_ENUMDESKTOPS, $WINSTA_ENUMERATE, $WINSTA_EXITWINDOWS, $WINSTA_READATTRIBUTES, $WINSTA_READSCREEN, $WINSTA_WRITEATTRIBUTES)
Global Const $DTT_TEXTCOLOR = 0x00000001
Global Const $DTT_BORDERCOLOR = 0x00000002
Global Const $DTT_SHADOWCOLOR = 0x00000004
Global Const $DTT_SHADOWTYPE = 0x00000008
Global Const $DTT_SHADOWOFFSET = 0x00000010
Global Const $DTT_BORDERSIZE = 0x00000020
Global Const $DTT_FONTPROP = 0x00000040
Global Const $DTT_COLORPROP = 0x00000080
Global Const $DTT_STATEID = 0x00000100
Global Const $DTT_CALCRECT = 0x00000200
Global Const $DTT_APPLYOVERLAY = 0x00000400
Global Const $DTT_GLOWSIZE = 0x00000800
Global Const $DTT_COMPOSITED = 0x00002000
Global Const $DTT_VALIDBITS = BitOR($DTT_TEXTCOLOR, $DTT_BORDERCOLOR, $DTT_SHADOWCOLOR, $DTT_SHADOWTYPE, $DTT_SHADOWOFFSET, $DTT_BORDERSIZE, $DTT_FONTPROP, $DTT_COLORPROP, $DTT_STATEID, $DTT_CALCRECT, $DTT_APPLYOVERLAY, $DTT_GLOWSIZE, $DTT_COMPOSITED)
Global Const $JOB_OBJECT_ASSIGN_PROCESS = 0x0001
Global Const $JOB_OBJECT_QUERY = 0x0004
Global Const $JOB_OBJECT_SET_ATTRIBUTES = 0x0002
Global Const $JOB_OBJECT_SET_SECURITY_ATTRIBUTES = 0x0010
Global Const $JOB_OBJECT_TERMINATE = 0x0008
Global Const $JOB_OBJECT_ALL_ACCESS = BitOR($STANDARD_RIGHTS_ALL, $JOB_OBJECT_ASSIGN_PROCESS, $JOB_OBJECT_QUERY, $JOB_OBJECT_SET_ATTRIBUTES, $JOB_OBJECT_SET_SECURITY_ATTRIBUTES, $JOB_OBJECT_TERMINATE)
Global Const $SEMAPHORE_MODIFY_STATE = 0x0002
Global Const $SEMAPHORE_QUERY_STATE = 0x0001
Global Const $SEMAPHORE_ALL_ACCESS = BitOR($STANDARD_RIGHTS_ALL, $SEMAPHORE_MODIFY_STATE, $SEMAPHORE_QUERY_STATE)
Global Const $KEY_CREATE_LINK = 0x0020
Global Const $KEY_CREATE_SUB_KEY = 0x0004
Global Const $KEY_ENUMERATE_SUB_KEYS = 0x0008
Global Const $KEY_NOTIFY = 0x0010
Global Const $KEY_QUERY_VALUE = 0x0001
Global Const $KEY_SET_VALUE = 0x0002
Global Const $KEY_READ = BitOR($STANDARD_RIGHTS_READ, $KEY_ENUMERATE_SUB_KEYS, $KEY_NOTIFY, $KEY_QUERY_VALUE)
Global Const $KEY_WRITE = BitOR($STANDARD_RIGHTS_WRITE, $KEY_CREATE_SUB_KEY, $KEY_SET_VALUE)
Global Const $KEY_ALL_ACCESS = BitOR($STANDARD_RIGHTS_REQUIRED, $KEY_CREATE_LINK, $KEY_CREATE_SUB_KEY, $KEY_ENUMERATE_SUB_KEYS, $KEY_NOTIFY, $KEY_QUERY_VALUE, $KEY_SET_VALUE)
Global Const $SHERB_NOCONFIRMATION = 0x01
Global Const $SHERB_NOPROGRESSUI = 0x02
Global Const $SHERB_NOSOUND = 0x04
Global Const $SHERB_NO_UI = BitOR($SHERB_NOCONFIRMATION, $SHERB_NOPROGRESSUI, $SHERB_NOSOUND)
Global Const $FOF_NOCONFIRMATION = 0x0010
Global Const $FOF_NOCONFIRMMKDIR = 0x0200
Global Const $FOF_NOERRORUI = 0x0400
Global Const $FOF_SILENT = 0x0004
Global Const $FOF_NO_UI = BitOR($FOF_NOCONFIRMATION, $FOF_NOCONFIRMMKDIR, $FOF_NOERRORUI, $FOF_SILENT)
Global Const $SFGAO_CANCOPY = 0x00000001
Global Const $SFGAO_CANMOVE = 0x00000002
Global Const $SFGAO_CANLINK = 0x00000004
Global Const $SFGAO_STORAGE = 0x00000008
Global Const $SFGAO_CANRENAME = 0x00000010
Global Const $SFGAO_CANDELETE = 0x00000020
Global Const $SFGAO_HASPROPSHEET = 0x00000040
Global Const $SFGAO_DROPTARGET = 0x00000100
Global Const $SFGAO_CAPABILITYMASK = BitOR($SFGAO_CANCOPY, $SFGAO_CANMOVE, $SFGAO_CANLINK, $SFGAO_CANRENAME, $SFGAO_CANDELETE, $SFGAO_HASPROPSHEET, $SFGAO_DROPTARGET)
Global Const $SFGAO_ISSLOW = 0x00004000
Global Const $SFGAO_GHOSTED = 0x00008000
Global Const $SFGAO_LINK = 0x00010000
Global Const $SFGAO_SHARE = 0x00020000
Global Const $SFGAO_READONLY = 0x00040000
Global Const $SFGAO_HIDDEN = 0x00080000
Global Const $SFGAO_DISPLAYATTRMASK = BitOR($SFGAO_ISSLOW, $SFGAO_GHOSTED, $SFGAO_LINK, $SFGAO_SHARE, $SFGAO_READONLY, $SFGAO_HIDDEN)
Global Const $SFGAO_STREAM = 0x00400000
Global Const $SFGAO_STORAGEANCESTOR = 0x00800000
Global Const $SFGAO_VALIDATE = 0x01000000
Global Const $SFGAO_FILESYSANCESTOR = 0x10000000
Global Const $SFGAO_FOLDER = 0x20000000
Global Const $SFGAO_FILESYSTEM = 0x40000000
Global Const $SFGAO_STORAGECAPMASK = BitOR($SFGAO_STORAGE, $SFGAO_LINK, $SFGAO_READONLY, $SFGAO_STREAM, $SFGAO_STORAGEANCESTOR, $SFGAO_FILESYSANCESTOR, $SFGAO_FOLDER, $SFGAO_FILESYSTEM)
Global Const $SFGAO_HASSUBFOLDER = 0x80000000
Global Const $SFGAO_PKEYSFGAOMASK = BitOR($SFGAO_ISSLOW, $SFGAO_READONLY, $SFGAO_HASSUBFOLDER, $SFGAO_VALIDATE)
Global Const $UHID_MB = 0x0000
Global Const $UHID_BIOS = 0x0001
Global Const $UHID_CPU = 0x0002
Global Const $UHID_HDD = 0x0004
Global Const $UHID_All = BitOR($UHID_MB, $UHID_BIOS, $UHID_CPU, $UHID_HDD)
Global Const $__WINVER = __Ver()
Global Const $tagPRINTDLG = 'align 2;dword_ptr Size;hwnd hOwner;ptr hDevMode;ptr hDevNames;hwnd hDC;dword Flags;ushort FromPage;ushort ToPage;ushort MinPage;ushort MaxPage;' & __Iif(@AutoItX64, 'uint', 'ushort') & ' Copies;ptr hInstance;lparam lParam;ptr PrintHook;ptr SetupHook;ptr PrintTemplateName;ptr SetupTemplateName;ptr hPrintTemplate;ptr hSetupTemplate;'
Func __Iif($fTest, $iTrue, $iFalse)
    If $fTest Then
        Return $iTrue
    Else
        Return $iFalse
    EndIf
EndFunc   ;==>__Iif

Func __Ver()
    Local $tOSVI = DllStructCreate('dword;dword;dword;dword;dword;wchar[128]')
    DllStructSetData($tOSVI, 1, DllStructGetSize($tOSVI))
    Local $Ret = DllCall('kernel32.dll', 'int', 'GetVersionExW', 'ptr', DllStructGetPtr($tOSVI))
    If (@error) Or (Not $Ret[0]) Then
        Return SetError(1, 0, 0)
    EndIf
    Return BitOR(BitShift(DllStructGetData($tOSVI, 2), -8), DllStructGetData($tOSVI, 3))
EndFunc   ;==>__Ver

Func _FileExt($path)
    If $path = "" Then Return ""
    Local $pos = StringInStr($path, ".", 0, -1)
    If $pos = 0 Then Return ""
    Return StringMid($path, $pos)
EndFunc   ;==>_FileExt

Func _PathNoExt($path)
    If Not StringInStr($path, ".") Then Return $path
    Return StringLeft($path, StringInStr($path, ".", 0, -1) - 1)
EndFunc   ;==>_PathNoExt

Func _ScriptBaseName()
    Return StringLeft(@ScriptName, (StringInStr(@ScriptName, ".") - 1))
EndFunc   ;==>_ScriptBaseName

Func _ScriptVersion($Script = @ScriptFullPath)
    Local $ver = "", $scriptHandle = -1, $found = False, $sPos = 0
    If StringRight($Script, 4) = ".exe" Then
        Return FileGetVersion($Script)
    ElseIf StringRight($Script, 4) = ".au3" Then
        $scriptHandle = FileOpen($Script)
        If $scriptHandle = -1 Then Return SetError(1, 0, "")
        Do
            $ver = FileReadLine($scriptHandle)
            $sPos = StringInStr($ver, "Fileversion=")
            If $sPos Then
                $ver = StringMid($ver, $sPos + StringLen("Fileversion="))
                $found = True
                ExitLoop
            EndIf
        Until StringLeft($ver, 1) <> "#"
        FileClose($scriptHandle)
    ElseIf StringRight($Script, 4) = ".ahk" Then
        $scriptHandle = FileOpen($Script)
        If $scriptHandle = -1 Then Return SetError(1, 0, "")
        $ver = FileReadLine($scriptHandle)
        If StringLeft($ver, 2) <> "/*" Then Return ""
        Do
            $ver = FileReadLine($scriptHandle)
            $sPos = StringInStr($ver, "File_Version=")
            If $sPos Then
                $ver = StringMid($ver, $sPos + StringLen("File_Version="))
                $found = True
                ExitLoop
            EndIf
        Until StringLeft($ver, 2) = "*/"
        FileClose($scriptHandle)
    Else
        SetError(2, 0, "")
    EndIf
    If Not $found Then $ver = ""
    Return $ver
EndFunc   ;==>_ScriptVersion

Func _FileVersioned($Script)
    Local $suffix = _ScriptVersion($Script)
    If @error Or Not $suffix Then Return SetError(@error, 0, $Script)
    Return _PathNoExt($Script) & "_" & StringReplace($suffix, ".", "_") & _FileExt($Script)
EndFunc   ;==>_FileVersioned

Func _ShowError($errorMsg, $title = "", $quit = True, $timeOut = 0)
    If $title = "" Then $title = _ScriptBaseName()
    MsgBox(0x1010, $title, $errorMsg, $timeOut)
    If $quit Then Exit
EndFunc   ;==>_ShowError

Func _ShowUsage($usageMsg, $title = "", $quit = True, $timeOut = 0)
    If $title = "" Then $title = _ScriptBaseName()
    MsgBox(0x1040, $title, $usageMsg, $timeOut)
    If $quit Then Exit
EndFunc   ;==>_ShowUsage

; Main Program Start

Global $version = _ScriptVersion()
Global $fileName = "", $fileArray
Global $msg = "SaveVersion" & $version & "  Copyright (c) " & @YEAR & "  www.favessoft.com" & @CRLF & @CRLF
$msg &= "Usage: SaveVersion [ /? ] or [ filename1 .. filename2 ... ]" & @CRLF & @CRLF
$msg &= "filename must be ..exe, .au3 or .ahk with file version info" & @CRLF & @CRLF
$msg &= "Au3 and Ahk requre source directives. Exe must be compiled with file version information" & @CRLF & @CRLF
$msg &= "Copies filname.ext to filename_n_n_n_n.ext (n being version numbers)" & @CRLF & @CRLF
$msg &= "SaveVersion /? shows this About Dialog" & @CRLF & @CRLF
$msg &= "SaveVersion  ( no args displays File Open Dialog )"
If $CmdLine[0] = 1 And $CmdLine[1] = "/?" Then
    _ShowUsage($msg)
EndIf
If Not $CmdLine[0] Or Not FileExists($CmdLine[1]) Then
    $fileName = FileOpenDialog("Select File(s) to Save Versioned", @WorkingDir, "Ahk Files (*.ahk)|Au3 Files (*.au3)|Exe Files (*.exe) |All Files (*.*)", 7)
    If @error Then
        _ShowError("No File Selected")
    EndIf
    If Not StringInStr($fileName, "|") Then
        _CopyVersioned($fileName)
    Else
        $fileArray = StringSplit($fileName, '|')
        For $x = 2 To $fileArray[0]
            _CopyVersioned($fileArray[1] & "" & $fileArray[$x])
        Next
    EndIf
    Exit
EndIf
If $CmdLine[0] > 5 Then
    If MsgBox(0x1024, _ScriptBaseName(), $CmdLine[0] & " Files On Command Line: Process ??") = 7 Then
        _ShowUsage("User Terminated Processing")
    EndIf
EndIf
For $x = 1 To $CmdLine[0]
    _CopyVersioned($CmdLine[$x])
Next
Func _CopyVersioned($inFile)
    Local $outFile = _FileVersioned($inFile)
    If $inFile = $outFile Then
        _ShowError("No File Version Info Found for:" & @CRLF & @CRLF & $inFile, "", False)
        Return
    EndIf
    If MsgBox(0x1024, _ScriptBaseName(), "Copy " & $inFile & @CRLF & @CRLF & " to " & @CRLF & @CRLF & $outFile) = 6 Then
        If Not FileCopy($inFile, $outFile, 1) Then
            _ShowError("Error Saving Versioned Copy of: " & @CRLF & @CRLF & $inFile, "", False)
        EndIf
    EndIf
EndFunc   ;==>_CopyVersioned
Edited by MilesAhead

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  

×