Archive

Posts Tagged ‘autoit’

AutoIt script to export a Testing Anywhere tamx codebase to text files

  1. Being confronted with a legacy codebase of over 750 tamx automated test scripts and
  2. the limited Testing Anywhere IDE .
    1. Normal view – essentially links to property dialogues – without helpful search,
    2. Expert view not being used with no cross-file, let alone codebase search, and just another partial view of the actual underlying code which is only available encrypted in the tamx files;
    3. Server Backup diff feature rudimentary and not being used.
  3. I came up with this AutoIT script (Testing Anywhere – but not Anything – won’t allow automation of its own window) which:
    1. collects, given a flat file listing of their paths, the Testing Anywhere (tested with 9.2) automated test scripts (tamx),
    2. from a list of networked (and drive-letter-mapped: fill out hash to guide the path translation) test automation computers,
    3. to a local directory (root=$localpathpattern, plus remote path) as
      1. .txt, using  TA‘s built-in export function) and
      2. .tax (using line-by-line copy from TA expert view).
    4. To improve resilience despite automation errors, the script keeps track of files exported in 2 ways, through
      1. a list tamxlistdone.txt
      2. comparison of file dates and exports only tamx files updated since last save as txt/tax.
    5. You can try the script out opening the tamx files in a text editor instead of the Testing Anywhere editor if you set $isdryrun = True.
  4. Compile this script to an AutoIt exe and make it a Scheduled Task to update your searchable codebase overnight.
  5. Benefits:
    1. Use for better cross automation project search (e.g. for magic strings and other literals, like log messages emitted)
    2. and to put into better source control than TA provides: Export the .txt./.tax  into a Git repository, to be able to monitor your progress/collaborators.
  6. Sorry: no round tripping.
    1. There are some stubs in the script to implement uploading changes, since Expert view allows line-by-line paste from the clipboard.
    2. However, it seems Expert view represents only another partial view of the underlying code which a textual paste is likely to break.
    3. In addition, even with test scripts that are run, switching to Expert View can result in intractable syntax errors that prevent user from saving, even from switching back to normal view without.
  7. Had to obfuscate the script – message me if you cannot figure how to fill in the config section at the top.
     
    Global Const $0 = 1
    Global Const $1 = 0
    Global Const $2 = 1
    Global Const $3 = 2
    Func _0($4, $5, $6 = 0, $7 = 0, $8 = 0, $9 = "wparam", $a = "lparam", $b = "lresult")
    	Local $c = DllCall("user32.dll", $b, "SendMessageW", "hwnd", $4, "uint", $5, $9, $6, $a, $7)
    	If @error Then Return SetError(@error, @extended, "")
    	If $8 >= 0 And $8 <= 4 Then Return $c[$8]
    	Return $c
    EndFunc   ;==>_0
    Global Const $d = 1
    Global Const $e = 2
    Global Const $f = 0
    Global Const $g = 1
    Global Const $h = 2
    Global Const $i = 0
    Global Const $j = 1
    Func _2(Const $k = @error, Const $l = @extended)
    	Local $c = DllCall("kernel32.dll", "dword", "GetLastError")
    	Return SetError($k, $l, $c[0])
    EndFunc   ;==>_2
    Global Const $m = "Debug Window hidden text"
    Global $n = "AutoIt Debug Report"
    Global $o = 0
    Global $p = True, $q = True
    Global $r = 0
    Global $s
    Global $t = False
    Func _8(Const $u, Const $k = @error, Const $l = @extended)
    	If IsNumber($u) = 0 And IsString($u) = 0 And IsBool($u) = 0 Then Return SetError(1, 0, 0)
    	If _a($u) = 0 Then Return SetError(3, 0, 0)
    	Return SetError($k, $l, 1)
    EndFunc   ;==>_8
    Func _a($v, $w = False, $x = False, Const $k = @error, $l = @extended)
    	If $o <= 0 Or $o > 6 Then Return SetError($k, $l, 0)
    	$l = _k($v, $w)
    	If $x Then Exit
    	Return SetError($k, $l, 1)
    EndFunc   ;==>_a
    Func _h()
    	Local $y = Opt("WinDetectHiddenText", $0)
    	Local $0z = WinExists($n, $m)
    	If $0z Then
    		If $r = 0 Then
    			$r = ControlGetHandle($n, $m, "Edit1")
    			$p = False
    		EndIf
    	EndIf
    	Opt("WinDetectHiddenText", $y)
    	$q = False
    	If Not $p Then Return 0
    	Local Const $10 = 0x00CF0000
    	Local Const $11 = 0x00100000
    	Local Const $12 = 0x00200000
    	Local Const $13 = 2048
    	Local Const $14 = 0xC5
    	Local Const $15 = 32
    	Local $16 = 580, $17 = 280
    	GUICreate($n, $16, $17, -1, -1, $10)
    	Local $18 = GUICtrlCreateLabel($m, 0, 0, 1, 1)
    	GUICtrlSetState($18, $15)
    	Local $19 = GUICtrlCreateEdit("", 4, 4, $16 - 8, $17 - 8, BitOR($11, $12, $13))
    	$r = GUICtrlGetHandle($19)
    	GUICtrlSetBkColor($19, 0xFFFFFF)
    	GUICtrlSendMsg($19, $14, 0, 0)
    	GUISetState()
    	$p = True
    	Return 1
    EndFunc   ;==>_h
    #Au3Stripper_Off
    Func __Debug_ReportWindowWrite($sData)
    	#Au3Stripper_On
    	If $q Then _h()
    	Local Const $1a = 0x000E
    	Local Const $1b = 0xB1
    	Local Const $1c = 0xC2
    	Local $1d = _0($r, $1a, 0, 0, 0, "int", "int")
    	_0($r, $1b, $1d, $1d, 0, "int", "int")
    	_0($r, $1c, True, $v, 0, "int", "wstr")
    EndFunc   ;==>__Debug_ReportWindowWrite
    Func _j()
    	Local $0z = WinExists($n)
    	If $0z Then
    		If $r = 0 Then
    			$r = WinGetHandle($n)
    			Return 0
    		EndIf
    	EndIf
    	Local $1e = Run("Notepad.exe")
    	$r = WinWait("[CLASS:Notepad]")
    	If $1e <> WinGetProcess($r) Then
    		Return SetError(3, 0, 0)
    	EndIf
    	WinActivate($r)
    	WinSetTitle($r, "", String($n))
    	Return 1
    EndFunc   ;==>_j
    #Au3Stripper_Off
    Func __Debug_ReportNotepadWrite($sData)
    	#Au3Stripper_On
    	If $r = 0 Then _j()
    	ControlCommand($r, "", "Edit1", "EditPaste", String($v))
    EndFunc   ;==>__Debug_ReportNotepadWrite
    Func _k($v, $w = False, $1f = @extended)
    	Local $1g = @CRLF
    	If $t And ($v <> "") Then $v = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & $v
    	If $w Then
    		$1f = _2()
    		Local Const $1h = 0x1000
    		Local $c = DllCall("kernel32.dll", "dword", "FormatMessageW", "dword", $1h, "ptr", 0, "dword", $1f, "dword", 0, "wstr", "", "dword", 4096, "ptr", 0)
    		$1g = " : " & $c[5]
    	EndIf
    	$v &= $1g
    	Local $1i = BlockInput(1)
    	BlockInput(0)
    	$v = StringReplace($v, "'", "''")
    	Execute($s & "'" & $v & "')")
    	If Not $1i Then BlockInput(1)
    	Return $1f
    EndFunc   ;==>_k
    Func _r(ByRef $1j, $1k)
    	If Not IsArray($1j) Then Return SetError(1, 0, -1)
    	Local $1l = UBound($1j, $2) - 1
    	If IsArray($1k) Then
    		If UBound($1k, $1) <> 1 Or UBound($1k, $2) < 2 Then Return SetError(4, 0, -1)
    	Else
    		Local $1m, $1n, $1o
    		$1k = StringStripWS($1k, 8)
    		$1n = StringSplit($1k, ";")
    		$1k = ""
    		For $1p = 1 To $1n[0]
    			If Not StringRegExp($1n[$1p], "^\d+(-\d+)?$") Then Return SetError(3, 0, -1)
    			$1o = StringSplit($1n[$1p], "-")
    			Switch $1o[0]
    				Case 1
    					$1k &= $1o[1] & ";"
    				Case 2
    					If Number($1o[2]) >= Number($1o[1]) Then
    						$1m = $1o[1] - 1
    						Do
    							$1m += 1
    							$1k &= $1m & ";"
    						Until $1m = $1o[2]
    					EndIf
    			EndSwitch
    		Next
    		$1k = StringSplit(StringTrimRight($1k, 1), ";")
    	EndIf
    	If $1k[1] < 0 Or $1k[$1k[0]] > $1l Then Return SetError(5, 0, -1)
    	Local $1q = 0
    	Switch UBound($1j, $1)
    		Case 1
    			For $1p = 1 To $1k[0]
    				$1j[$1k[$1p]] = ChrW(0xFAB1)
    			Next
    			For $1r = 0 To $1l
    				If $1j[$1r] == ChrW(0xFAB1) Then
    					ContinueLoop
    				Else
    					If $1r <> $1q Then
    						$1j[$1q] = $1j[$1r]
    					EndIf
    					$1q += 1
    				EndIf
    			Next
    			ReDim $1j[$1l - $1k[0] + 1]
    		Case 2
    			Local $1s = UBound($1j, $3) - 1
    			For $1p = 1 To $1k[0]
    				$1j[$1k[$1p]][0] = ChrW(0xFAB1)
    			Next
    			For $1r = 0 To $1l
    				If $1j[$1r][0] == ChrW(0xFAB1) Then
    					ContinueLoop
    				Else
    					If $1r <> $1q Then
    						For $1t = 0 To $1s
    							$1j[$1q][$1t] = $1j[$1r][$1t]
    						Next
    					EndIf
    					$1q += 1
    				EndIf
    			Next
    			ReDim $1j[$1l - $1k[0] + 1][$1s + 1]
    		Case Else
    			Return SetError(2, 0, False)
    	EndSwitch
    	Return UBound($1j, $2)
    EndFunc   ;==>_r
    Func _14(Const ByRef $1j, $1u, $1v = 0, $1w = 0, $1x = 0, $1y = 0, $1z = 1, $20 = -1, $21 = False)
    	If $1v = Default Then $1v = 0
    	If $1w = Default Then $1w = 0
    	If $1x = Default Then $1x = 0
    	If $1y = Default Then $1y = 0
    	If $1z = Default Then $1z = 1
    	If $20 = Default Then $20 = -1
    	If $21 = Default Then $21 = False
    	If Not IsArray($1j) Then Return SetError(1, 0, -1)
    	Local $1l = UBound($1j) - 1
    	If $1l = -1 Then Return SetError(3, 0, -1)
    	Local $1s = UBound($1j, $3) - 1
    	Local $22 = False
    	If $1y = 2 Then
    		$1y = 0
    		$22 = True
    	EndIf
    	If $21 Then
    		If UBound($1j, $1) = 1 Then Return SetError(5, 0, -1)
    		If $1w < 1 Or $1w > $1s Then $1w = $1s
    		If $1v < 0 Then $1v = 0
    		If $1v > $1w Then Return SetError(4, 0, -1)
    	Else
    		If $1w < 1 Or $1w > $1l Then $1w = $1l
    		If $1v < 0 Then $1v = 0
    		If $1v > $1w Then Return SetError(4, 0, -1)
    	EndIf
    	Local $23 = 1
    	If Not $1z Then
    		Local $24 = $1v
    		$1v = $1w
    		$1w = $24
    		$23 = -1
    	EndIf
    	Switch UBound($1j, $1)
    		Case 1
    			If Not $1y Then
    				If Not $1x Then
    					For $1p = $1v To $1w Step $23
    						If $22 And VarGetType($1j[$1p]) <> VarGetType($1u) Then ContinueLoop
    						If $1j[$1p] = $1u Then Return $1p
    					Next
    				Else
    					For $1p = $1v To $1w Step $23
    						If $22 And VarGetType($1j[$1p]) <> VarGetType($1u) Then ContinueLoop
    						If $1j[$1p] == $1u Then Return $1p
    					Next
    				EndIf
    			Else
    				For $1p = $1v To $1w Step $23
    					If $1y = 3 Then
    						If StringRegExp($1j[$1p], $1u) Then Return $1p
    					Else
    						If StringInStr($1j[$1p], $1u, $1x) > 0 Then Return $1p
    					EndIf
    				Next
    			EndIf
    		Case 2
    			Local $25
    			If $21 Then
    				$25 = $1l
    				If $20 > $25 Then $20 = $25
    				If $20 < 0 Then
    					$20 = 0
    				Else
    					$25 = $20
    				EndIf
    			Else
    				$25 = $1s
    				If $20 > $25 Then $20 = $25
    				If $20 < 0 Then
    					$20 = 0
    				Else
    					$25 = $20
    				EndIf
    			EndIf
    			For $1t = $20 To $25
    				If Not $1y Then
    					If Not $1x Then
    						For $1p = $1v To $1w Step $23
    							If $21 Then
    								If $22 And VarGetType($1j[$1t][$1t]) <> VarGetType($1u) Then ContinueLoop
    								If $1j[$1t][$1p] = $1u Then Return $1p
    							Else
    								If $22 And VarGetType($1j[$1p][$1t]) <> VarGetType($1u) Then ContinueLoop
    								If $1j[$1p][$1t] = $1u Then Return $1p
    							EndIf
    						Next
    					Else
    						For $1p = $1v To $1w Step $23
    							If $21 Then
    								If $22 And VarGetType($1j[$1t][$1p]) <> VarGetType($1u) Then ContinueLoop
    								If $1j[$1t][$1p] == $1u Then Return $1p
    							Else
    								If $22 And VarGetType($1j[$1p][$1t]) <> VarGetType($1u) Then ContinueLoop
    								If $1j[$1p][$1t] == $1u Then Return $1p
    							EndIf
    						Next
    					EndIf
    				Else
    					For $1p = $1v To $1w Step $23
    						If $1y = 3 Then
    							If $21 Then
    								If StringRegExp($1j[$1t][$1p], $1u) Then Return $1p
    							Else
    								If StringRegExp($1j[$1p][$1t], $1u) Then Return $1p
    							EndIf
    						Else
    							If $21 Then
    								If StringInStr($1j[$1t][$1p], $1u, $1x) > 0 Then Return $1p
    							Else
    								If StringInStr($1j[$1p][$1t], $1u, $1x) > 0 Then Return $1p
    							EndIf
    						EndIf
    					Next
    				EndIf
    			Next
    		Case Else
    			Return SetError(2, 0, -1)
    	EndSwitch
    	Return SetError(6, 0, -1)
    EndFunc   ;==>_14
    Global Const $26 = 0
    Global Const $27 = 1
    Global Const $28 = 0
    Global Const $29 = 2
    Global Const $2a = 0
    Global Const $2b = 1
    Global Const $2c = 2
    Global Const $2d = 4
    Func _1x($2e, ByRef $2f, $2g = $2b, $2h = "")
    	$2f = 0
    	If $2g = Default Then $2g = $2b
    	If $2h = Default Then $2h = ""
    	Local $2i = True
    	If BitAND($2g, $2c) Then
    		$2i = False
    		$2g -= $2c
    	EndIf
    	Local $2j = $f
    	If BitAND($2g, $2d) Then
    		$2j = $g
    		$2g -= $2d
    	EndIf
    	Local $2k = 0
    	If $2g <> $2b Then
    		$2g = $2a
    		$2k = $h
    	EndIf
    	If $2h Then
    		Local $2l = FileReadToArray($2e)
    		If @error Then Return SetError(@error, 0, 0)
    		Local $1l = UBound($2l) + $2g
    		If $2i Then
    			Local $1s = UBound(StringSplit($2l[0], $2h, $2j + $h))
    			Local $2m[$1l][$1s]
    			Local $2n, $2o
    			For $1p = 0 To $1l - $2g - 1
    				$2o = StringSplit($2l[$1p], $2h, $2j + $h)
    				$2n = UBound($2o)
    				If $2n <> $1s Then
    					Return SetError(3, 0, 0)
    				EndIf
    				For $1t = 0 To $2n - 1
    					$2m[$1p + $2g][$1t] = $2o[$1t]
    				Next
    			Next
    			If $1s < 2 Then Return SetError(4, 0, 0)
    			If $2g Then
    				$2m[0][0] = $1l - $2g
    				$2m[0][1] = $1s
    			EndIf
    		Else
    			Local $2m[$1l]
    			For $1p = 0 To $1l - $2g - 1
    				$2m[$1p + $2g] = StringSplit($2l[$1p], $2h, $2j + $2k)
    			Next
    			If $2g Then
    				$2m[0] = $1l - $2g
    			EndIf
    		EndIf
    		$2f = $2m
    	Else
    		If $2g Then
    			Local $2p = FileOpen($2e, $28)
    			If $2p = -1 Then Return SetError(1, 0, 0)
    			Local $2q = FileRead($2p)
    			FileClose($2p)
    			If StringLen($2q) Then
    				$2f = StringRegExp(@LF & $2q, "(?|(\N+)\z|(\N*)(?:\R))", 3)
    				$2f[0] = UBound($2f) - 1
    			Else
    				Return SetError(2, 0, 0)
    			EndIf
    		Else
    			$2f = FileReadToArray($2e)
    			If @error Then
    				$2f = 0
    				Return SetError(@error, 0, 0)
    			EndIf
    		EndIf
    	EndIf
    	Return 1
    EndFunc   ;==>_1x
    Func _1y($2e, Const ByRef $1j, $2r = Default, $2s = Default, $2h = "|")
    	Local $8 = 0
    	If Not IsArray($1j) Then Return SetError(2, 0, $8)
    	Local $2t = UBound($1j, $1)
    	If $2t > 2 Then Return SetError(4, 0, 0)
    	Local $2u = UBound($1j) - 1
    	If $2s = Default Or $2s > $2u Then $2s = $2u
    	If $2r < 0 Or $2r = Default Then $2r = 0
    	If $2r > $2s Then Return SetError(5, 0, $8)
    	If $2h = Default Then $2h = "|"
    	Local $2p = $2e
    	If IsString($2e) Then
    		$2p = FileOpen($2e, $29)
    		If $2p = -1 Then Return SetError(1, 0, $8)
    	EndIf
    	Local $2v = 0
    	$8 = 1
    	Switch $2t
    		Case 1
    			For $1p = $2r To $2s
    				If Not FileWrite($2p, $1j[$1p] & @CRLF) Then
    					$2v = 3
    					$8 = 0
    					ExitLoop
    				EndIf
    			Next
    		Case 2
    			Local $2w = ""
    			For $1p = $2r To $2s
    				$2w = $1j[$1p][0]
    				For $1t = 1 To UBound($1j, $3) - 1
    					$2w &= $2h & $1j[$1p][$1t]
    				Next
    				If Not FileWrite($2p, $2w & @CRLF) Then
    					$2v = 3
    					$8 = 0
    					ExitLoop
    				EndIf
    			Next
    	EndSwitch
    	If IsString($2e) Then FileClose($2p)
    	Return SetError($2v, 0, $8)
    EndFunc   ;==>_1y
    Func _24($2e, ByRef $2x, ByRef $2y, ByRef $2z, ByRef $30)
    	Local $1j = StringRegExp($2e, "^\h*((?:\\\\\?\\)*(\\\\[^\?\/\\]+|[A-Za-z]:)?(.*[\/\\]\h*)?((?:[^\.\/\\]|(?(?=\.[^\/\\]*\.)\.))*)?([^\/\\]*))$", $j)
    	If @error Then
    		ReDim $1j[5]
    		$1j[0] = $2e
    	EndIf
    	$2x = $1j[1]
    	If StringLeft($1j[2], 1) == "/" Then
    		$2y = StringRegExpReplace($1j[2], "\h*[\/\\]+\h*", "\/")
    	Else
    		$2y = StringRegExpReplace($1j[2], "\h*[\/\\]+\h*", "\\")
    	EndIf
    	$1j[2] = $2y
    	$2z = $1j[3]
    	$30 = $1j[4]
    	Return $1j
    EndFunc   ;==>_24
    Global Const $31 = '{66087055-AD66-4C7C-9A18-38A2310B8337}'
    Global Const $32 = '{E09D739D-CCD4-44EE-8EBA-3FBF8BE4FC58}'
    Global Const $33 = '{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}'
    Global Const $34 = 4
    Global Const $35 = 2
    Global Const $36 = 0x00021808
    Global Const $37 = "struct;long X;long Y;endstruct"
    Global Const $38 = "struct;long Left;long Top;long Right;long Bottom;endstruct"
    Global Const $39 = "struct;word Year;word Month;word Dow;word Day;word Hour;word Minute;word Second;word MSeconds;endstruct"
    Global Const $3a = "struct;byte GUID[16];ulong NumberOfValues;ulong Type;ptr Values;endstruct"
    Global Const $3b = "uint Count;" & $3a
    Global Const $3c = "uint Version;ptr Callback;bool NoThread;bool NoCodecs"
    Global Const $3d = "byte CLSID[16];byte FormatID[16];ptr CodecName;ptr DllName;ptr FormatDesc;ptr FileExt;" & "ptr MimeType;dword Flags;dword Version;dword SigCount;dword SigSize;ptr SigPattern;ptr SigMask"
    Global Const $3e = "uint cbSize;uint fMask;uint fStyle;dword clrFore;dword clrBack;ptr lpText;uint cch;" & "int iImage;hwnd hwndChild;uint cxMinChild;uint cyMinChild;uint cx;handle hbmBack;uint wID;uint cyChild;uint cyMaxChild;" & "uint cyIntegral;uint cxIdeal;lparam lParam;uint cxHeader" & ((@OSVersion = "WIN_XP") ? "" : ";" & $38 & ";uint uChevronState")
    Global Const $3f = "struct;ulong Data1;ushort Data2;ushort Data3;byte Data4[8];endstruct"
    Global Const $3g = Ptr(-1)
    Global Const $3h = Ptr(-1)
    Global Const $3i = 0x0100
    Global Const $3j = 0x2000
    Global Const $3k = 0x8000
    Global Const $3l = BitShift($3i, 8)
    Global Const $3m = BitShift($3j, 8)
    Global Const $3n = BitShift($3k, 8)
    Global Const $3o = "dword Size;dword Flags;handle hCursor;" & $37
    Global Const $3p = "bool Icon;dword XHotSpot;dword YHotSpot;handle hMask;handle hColor"
    Func _2t($3q, $3r, $3s, $3t, $3u, $3v, $3w, $3x, $3y)
    	Local $c = DllCall("gdi32.dll", "bool", "BitBlt", "handle", $3q, "int", $3r, "int", $3s, "int", $3t, "int", $3u, "handle", $3v, "int", $3w, "int", $3x, "dword", $3y)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_2t
    Func _30($3z)
    	Local $c = DllCall("user32.dll", "handle", "CopyIcon", "handle", $3z)
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_30
    Func _32($40, $3t, $3u)
    	Local $c = DllCall("gdi32.dll", "handle", "CreateCompatibleBitmap", "handle", $40, "int", $3t, "int", $3u)
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_32
    Func _33($40)
    	Local $c = DllCall("gdi32.dll", "handle", "CreateCompatibleDC", "handle", $40)
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_33
    Func _3g($40)
    	Local $c = DllCall("gdi32.dll", "bool", "DeleteDC", "handle", $40)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_3g
    Func _3h($41)
    	Local $c = DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $41)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_3h
    Func _3i($3z)
    	Local $c = DllCall("user32.dll", "bool", "DestroyIcon", "handle", $3z)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_3i
    Func _3m($40, $42, $43, $3z)
    	Local $c = DllCall("user32.dll", "bool", "DrawIcon", "handle", $40, "int", $42, "int", $43, "handle", $3z)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_3m
    Func _4n()
    	Local $44 = DllStructCreate($3o)
    	Local $45 = DllStructGetSize($44)
    	DllStructSetData($44, "Size", $45)
    	Local $46 = DllCall("user32.dll", "bool", "GetCursorInfo", "struct*", $44)
    	If @error Or Not $46[0] Then Return SetError(@error + 10, @extended, 0)
    	Local $47[5]
    	$47[0] = True
    	$47[1] = DllStructGetData($44, "Flags") <> 0
    	$47[2] = DllStructGetData($44, "hCursor")
    	$47[3] = DllStructGetData($44, "X")
    	$47[4] = DllStructGetData($44, "Y")
    	Return $47
    EndFunc   ;==>_4n
    Func _4o($4)
    	Local $c = DllCall("user32.dll", "handle", "GetDC", "hwnd", $4)
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_4o
    Func _4p()
    	Local $c = DllCall("user32.dll", "hwnd", "GetDesktopWindow")
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_4p
    Func _4y($3z)
    	Local $48 = DllStructCreate($3p)
    	Local $46 = DllCall("user32.dll", "bool", "GetIconInfo", "handle", $3z, "struct*", $48)
    	If @error Or Not $46[0] Then Return SetError(@error + 10, @extended, 0)
    	Local $49[6]
    	$49[0] = True
    	$49[1] = DllStructGetData($48, "Icon") <> 0
    	$49[2] = DllStructGetData($48, "XHotSpot")
    	$49[3] = DllStructGetData($48, "YHotSpot")
    	$49[4] = DllStructGetData($48, "hMask")
    	$49[5] = DllStructGetData($48, "hColor")
    	Return $49
    EndFunc   ;==>_4y
    Func _5g($4a)
    	Local $c = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $4a)
    	If @error Then Return SetError(@error, @extended, 0)
    	Return $c[0]
    EndFunc   ;==>_5g
    Func _5v($4b)
    	Local $4c = DllStructCreate($3f)
    	_5w($4b, $4c)
    	If @error Then Return SetError(@error + 10, @extended, 0)
    	Return $4c
    EndFunc   ;==>_5v
    Func _5w($4b, $4c)
    	Local $c = DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $4b, "struct*", $4c)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_5w
    Func _72($4, $40)
    	Local $c = DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $4, "handle", $40)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_72
    Func _74($40, $4d)
    	Local $c = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $40, "handle", $4d)
    	If @error Then Return SetError(@error, @extended, False)
    	Return $c[0]
    EndFunc   ;==>_74
    Func _7w($4c)
    	Local $c = DllCall("ole32.dll", "int", "StringFromGUID2", "struct*", $4c, "wstr", "", "int", 40)
    	If @error Or Not $c[0] Then Return SetError(@error, @extended, "")
    	Return SetExtended($c[0], $c[2])
    EndFunc   ;==>_7w
    Func _89($4e, $4f = 0, $4g = True)
    	Local $4h = "wstr"
    	If Not IsString($4e) Then $4h = "struct*"
    	Local $c = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", $4f, "dword", 0, $4h, $4e, "int", -1, "ptr", 0, "int", 0, "ptr", 0, "ptr", 0)
    	If @error Or Not $c[0] Then Return SetError(@error + 20, @extended, "")
    	Local $4i = DllStructCreate("char[" & $c[0] & "]")
    	$c = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", $4f, "dword", 0, $4h, $4e, "int", -1, "struct*", $4i, "int", $c[0], "ptr", 0, "ptr", 0)
    	If @error Or Not $c[0] Then Return SetError(@error + 10, @extended, "")
    	If $4g Then Return DllStructGetData($4i, 1)
    	Return $4i
    EndFunc   ;==>_89
    Global Const $4j = 'struct;dword OSVersionInfoSize;dword MajorVersion;dword MinorVersion;dword BuildNumber;dword PlatformId;wchar CSDVersion[128];endstruct'
    Global Const $4k = _9d()
    Func _9d()
    	Local $4l = DllStructCreate($4j)
    	DllStructSetData($4l, 1, DllStructGetSize($4l))
    	Local $46 = DllCall('kernel32.dll', 'bool', 'GetVersionExW', 'struct*', $4l)
    	If @error Or Not $46[0] Then Return SetError(@error, @extended, 0)
    	Return BitOR(BitShift(DllStructGetData($4l, 2), -8), DllStructGetData($4l, 3))
    EndFunc   ;==>_9d
    Global $4m = 0
    Global $4n = 0
    Global $4o = 0
    Global $4p = True
    Func _gg($4q, $4r, $4s, $4t, $4u, $4v = 0x00021808)
    	Local $c = DllCall($4m, "int", "GdipCloneBitmapArea", "float", $4r, "float", $4s, "float", $4t, "float", $4u, "int", $4v, "handle", $4q, "handle*", 0)
    	If @error Then Return SetError(@error, @extended, 0)
    	If $c[0] Then Return SetError(10, $c[0], 0)
    	Return $c[7]
    EndFunc   ;==>_gg
    Func _gk($4q, $4w = 0)
    	Local $c = DllCall($4m, "int", "GdipCreateBitmapFromHBITMAP", "handle", $4q, "handle", $4w, "handle*", 0)
    	If @error Then Return SetError(@error, @extended, 0)
    	If $c[0] Then Return SetError(10, $c[0], 0)
    	Return $c[3]
    EndFunc   ;==>_gk
    Func _hi()
    	Local $4x = _hk()
    	Local $4y = _hn()
    	Local $4z = DllStructCreate("byte[" & $4y & "]")
    	Local $c = DllCall($4m, "int", "GdipGetImageEncoders", "uint", $4x, "uint", $4y, "struct*", $4z)
    	If @error Then Return SetError(@error, @extended, 0)
    	If $c[0] Then Return SetError(10, $c[0], 0)
    	Local $50 = DllStructGetPtr($4z)
    	Local $51, $52[$4x + 1][14]
    	$52[0][0] = $4x
    	For $53 = 1 To $4x
    		$51 = DllStructCreate($3d, $50)
    		$52[$53][1] = _7w(DllStructGetPtr($51, "CLSID"))
    		$52[$53][2] = _7w(DllStructGetPtr($51, "FormatID"))
    		$52[$53][3] = _89(DllStructGetData($51, "CodecName"))
    		$52[$53][4] = _89(DllStructGetData($51, "DllName"))
    		$52[$53][5] = _89(DllStructGetData($51, "FormatDesc"))
    		$52[$53][6] = _89(DllStructGetData($51, "FileExt"))
    		$52[$53][7] = _89(DllStructGetData($51, "MimeType"))
    		$52[$53][8] = DllStructGetData($51, "Flags")
    		$52[$53][9] = DllStructGetData($51, "Version")
    		$52[$53][10] = DllStructGetData($51, "SigCount")
    		$52[$53][11] = DllStructGetData($51, "SigSize")
    		$52[$53][12] = DllStructGetData($51, "SigPattern")
    		$52[$53][13] = DllStructGetData($51, "SigMask")
    		$50 += DllStructGetSize($51)
    	Next
    	Return $52
    EndFunc   ;==>_hi
    Func _hj($54)
    	Local $55 = _hi()
    	If @error Then Return SetError(@error, 0, "")
    	For $53 = 1 To $55[0][0]
    		If StringInStr($55[$53][6], "*." & $54) > 0 Then Return $55[$53][1]
    	Next
    	Return SetError(-1, -1, "")
    EndFunc   ;==>_hj
    Func _hk()
    	Local $c = DllCall($4m, "int", "GdipGetImageEncodersSize", "uint*", 0, "uint*", 0)
    	If @error Then Return SetError(@error, @extended, -1)
    	If $c[0] Then Return SetError(10, $c[0], -1)
    	Return $c[1]
    EndFunc   ;==>_hk
    Func _hn()
    	Local $c = DllCall($4m, "int", "GdipGetImageEncodersSize", "uint*", 0, "uint*", 0)
    	If @error Then Return SetError(@error, @extended, -1)
    	If $c[0] Then Return SetError(10, $c[0], -1)
    	Return $c[2]
    EndFunc   ;==>_hn
    Func _jt($56)
    	Local $c = DllCall($4m, "int", "GdipDisposeImage", "handle", $56)
    	If @error Then Return SetError(@error, @extended, False)
    	If $c[0] Then Return SetError(10, $c[0], False)
    	Return True
    EndFunc   ;==>_jt
    Func _jx($56)
    	Local $c = DllCall($4m, "int", "GdipGetImageHeight", "handle", $56, "uint*", 0)
    	If @error Then Return SetError(@error, @extended, -1)
    	If $c[0] Then Return SetError(10, $c[0], -1)
    	Return $c[2]
    EndFunc   ;==>_jx
    Func _k4($56)
    	Local $c = DllCall($4m, "int", "GdipGetImageWidth", "handle", $56, "uint*", -1)
    	If @error Then Return SetError(@error, @extended, -1)
    	If $c[0] Then Return SetError(10, $c[0], -1)
    	Return $c[2]
    EndFunc   ;==>_k4
    Func _k9($56, $2z, $57, $58 = 0)
    	Local $4c = _5v($57)
    	Local $c = DllCall($4m, "int", "GdipSaveImageToFile", "handle", $56, "wstr", $2z, "struct*", $4c, "struct*", $58)
    	If @error Then Return SetError(@error, @extended, False)
    	If $c[0] Then Return SetError(10, $c[0], False)
    	Return True
    EndFunc   ;==>_k9
    Func _l3(ByRef $58, $4b, $59, $5a, $5b)
    	Local $4x = DllStructGetData($58, "Count")
    	Local $5c = DllStructGetPtr($58, "GUID") + ($4x * _l5())
    	Local $5d = DllStructCreate($3a, $5c)
    	_5w($4b, $5c)
    	DllStructSetData($5d, "Type", $5a)
    	DllStructSetData($5d, "NumberOfValues", $59)
    	DllStructSetData($5d, "Values", $5b)
    	DllStructSetData($58, "Count", $4x + 1)
    EndFunc   ;==>_l3
    Func _l4($4x)
    	Local $5e = $3b
    	For $1p = 2 To $4x
    		$5e &= ";struct;byte[16];ulong;ulong;ptr;endstruct"
    	Next
    	Return DllStructCreate($5e)
    EndFunc   ;==>_l4
    Func _l5()
    	Local $5d = DllStructCreate($3a)
    	Return DllStructGetSize($5d)
    EndFunc   ;==>_l5
    Func _ny()
    	If $4m = 0 Then Return SetError(-1, -1, False)
    	$4n -= 1
    	If $4n = 0 Then
    		DllCall($4m, "none", "GdiplusShutdown", "ulong_ptr", $4o)
    		DllClose($4m)
    		$4m = 0
    	EndIf
    	Return True
    EndFunc   ;==>_ny
    Func _nz($5f = Default, $5g = False)
    	$4n += 1
    	If $4n > 1 Then Return True
    	If $5f = Default Then $5f = "gdiplus.dll"
    	$4m = DllOpen($5f)
    	If $4m = -1 Then
    		$4n = 0
    		Return SetError(1, 2, False)
    	EndIf
    	Local $5h = FileGetVersion($5f)
    	$5h = StringSplit($5h, ".")
    	If $5h[1] > 5 Then $4p = False
    	Local $5i = DllStructCreate($3c)
    	Local $5j = DllStructCreate("ulong_ptr Data")
    	DllStructSetData($5i, "Version", 1)
    	Local $c = DllCall($4m, "int", "GdiplusStartup", "struct*", $5j, "struct*", $5i, "ptr", 0)
    	If @error Then Return SetError(@error, @extended, False)
    	If $c[0] Then Return SetError(10, $c[0], False)
    	$4o = DllStructGetData($5j, "Data")
    	If $5g Then Return $4m
    	Return SetExtended($5h[1], True)
    EndFunc   ;==>_nz
    Func _ob($2z, $5k = True)
    	Local $4a = _oc(".\:", $2z)
    	If ($4a > 0) And (StringMid($2z, $4a, 1) = '.') Then
    		If $5k Then
    			Return StringMid($2z, $4a + 1)
    		Else
    			Return StringMid($2z, $4a)
    		EndIf
    	Else
    		Return ""
    	EndIf
    EndFunc   ;==>_ob
    Func _oc($5l, $5m)
    	Local $2h, $5n
    	For $53 = 1 To StringLen($5l)
    		$2h = StringMid($5l, $53, 1)
    		$5n = StringInStr($5m, $2h, 0, -1)
    		If $5n > 0 Then Return $5n
    	Next
    EndFunc   ;==>_oc
    Global $5o = $36
    Global $5p = 100
    Global $5q = 24
    Global $5r = $35
    Global Const $5s = 0
    Global Const $5t = 1
    Global Const $5u = 0x00CC0020
    Func _p6($2z = "", $5v = 0, $5w = 0, $5x = -1, $5y = -1, $5z = True)
    	Local $60 = False
    	If $5x = -1 Then $5x = _5g($5s) - 1
    	If $5y = -1 Then $5y = _5g($5t) - 1
    	If $5x < $5v Then Return SetError(-1, 0, $60)
    	If $5y < $5w Then Return SetError(-2, 0, $60)
    	Local $61 = ($5x - $5v) + 1
    	Local $62 = ($5y - $5w) + 1
    	Local $4 = _4p()
    	Local $63 = _4o($4)
    	Local $64 = _33($63)
    	Local $65 = _32($63, $61, $62)
    	_74($64, $65)
    	_2t($64, 0, 0, $61, $62, $63, $5v, $5w, $5u)
    	If $5z Then
    		Local $47 = _4n()
    		If Not @error And $47[1] Then
    			$5z = True
    			Local $3z = _30($47[2])
    			Local $49 = _4y($3z)
    			If Not @error Then
    				_3h($49[4])
    				If $49[5] <> 0 Then _3h($49[5])
    				_3m($64, $47[3] - $49[2] - $5v, $47[4] - $49[3] - $5w, $3z)
    			EndIf
    			_3i($3z)
    		EndIf
    	EndIf
    	_72($4, $63)
    	_3g($64)
    	If $2z = "" Then Return $65
    	$60 = _p8($2z, $65, True)
    	Return SetError(@error, @extended, $60)
    EndFunc   ;==>_p6
    Func _p8($2z, $4q, $66 = True)
    	_nz()
    	If @error Then Return SetError(-1, -1, False)
    	Local $67 = StringUpper(_ob($2z))
    	Local $68 = _hj($67)
    	If $68 = "" Then Return SetError(-2, -2, False)
    	Local $56 = _gk($4q)
    	If @error Then Return SetError(-3, -3, False)
    	Local $69, $58
    	Switch $67
    		Case "BMP"
    			Local $42 = _k4($56)
    			Local $43 = _jx($56)
    			Local $6a = _gg($56, 0, 0, $42, $43, $5o)
    			_jt($56)
    			$56 = $6a
    		Case "JPG", "JPEG"
    			$58 = _l4(1)
    			$69 = DllStructCreate("int Quality")
    			DllStructSetData($69, "Quality", $5p)
    			_l3($58, $33, 1, $34, DllStructGetPtr($69))
    		Case "TIF", "TIFF"
    			$58 = _l4(2)
    			$69 = DllStructCreate("int ColorDepth;int Compression")
    			DllStructSetData($69, "ColorDepth", $5q)
    			DllStructSetData($69, "Compression", $5r)
    			_l3($58, $31, 1, $34, DllStructGetPtr($69, "ColorDepth"))
    			_l3($58, $32, 1, $34, DllStructGetPtr($69, "Compression"))
    	EndSwitch
    	Local $6b = 0
    	If IsDllStruct($58) Then $6b = $58
    	Local $60 = _k9($56, $2z, $68, $6b)
    	_jt($56)
    	If $66 Then _3h($4q)
    	_ny()
    	Return SetError($60 = False, 0, $60)
    EndFunc   ;==>_p8
    Global Const $6c = 1
    Global Const $6d = 2
    Global Const $6e = 0x001D
    Global Const $6f = 0x001E
    Global Const $6g = 0x001F
    Global Const $6h = 0x0020
    Global Const $6i = 0x1003
    Global Const $6j = 0x0028
    Global Const $6k = 0x0029
    Global Const $6l = 0x007F
    Global Const $6m = 0x0400
    Func _q5($6n = 0, $6o = 0, $2g = 0, $6p = '')
    	If Not $6n Then $6n = 0x0400
    	Local $6q = 'wstr'
    	If Not StringStripWS($6p, $d + $e) Then
    		$6q = 'ptr'
    		$6p = 0
    	EndIf
    	Local $46 = DllCall('kernel32.dll', 'int', 'GetDateFormatW', 'dword', $6n, 'dword', $2g, 'struct*', $6o, $6q, $6p, 'wstr', '', 'int', 2048)
    	If @error Or Not $46[0] Then Return SetError(@error, @extended, '')
    	Return $46[5]
    EndFunc   ;==>_q5
    Func _q8($6n, $5a)
    	Local $46 = DllCall('kernel32.dll', 'int', 'GetLocaleInfoW', 'dword', $6n, 'dword', $5a, 'wstr', '', 'int', 2048)
    	If @error Or Not $46[0] Then Return SetError(@error + 10, @extended, '')
    	Return $46[3]
    EndFunc   ;==>_q8
    Func _qt($6r, $4v = Default)
    	Local Const $6s = 128
    	If $4v = Default Then $4v = 0
    	$6r = Int($6r)
    	If $6r < 1 Or $6r > 7 Then Return SetError(1, 0, "")
    	Local $6o = DllStructCreate($39)
    	DllStructSetData($6o, "Year", BitAND($4v, $6s) ? 2007 : 2006)
    	DllStructSetData($6o, "Month", 1)
    	DllStructSetData($6o, "Day", $6r)
    	Return _q5(BitAND($4v, $6d) ? $6m : $6l, $6o, 0, BitAND($4v, $6c) ? "ddd" : "dddd")
    EndFunc   ;==>_qt
    Func _qw($6t)
    	If StringIsInt($6t) Then
    		Select
    			Case Mod($6t, 4) = 0 And Mod($6t, 100) <> 0
    				Return 1
    			Case Mod($6t, 400) = 0
    				Return 1
    			Case Else
    				Return 0
    		EndSelect
    	EndIf
    	Return SetError(1, 0, 0)
    EndFunc   ;==>_qw
    Func _qx($1m)
    	$1m = Int($1m)
    	Return $1m >= 1 And $1m <= 12
    EndFunc   ;==>_qx
    Func _qy($6u)
    	Local $6v[4], $6w[4]
    	_r7($6u, $6v, $6w)
    	If Not StringIsInt($6v[1]) Then Return 0
    	If Not StringIsInt($6v[2]) Then Return 0
    	If Not StringIsInt($6v[3]) Then Return 0
    	$6v[1] = Int($6v[1])
    	$6v[2] = Int($6v[2])
    	$6v[3] = Int($6v[3])
    	Local $6x = _rq($6v[1])
    	If $6v[1] < 1000 Or $6v[1] > 2999 Then Return 0
    	If $6v[2] < 1 Or $6v[2] > 12 Then Return 0
    	If $6v[3] < 1 Or $6v[3] > $6x[$6v[2]] Then Return 0
    	If $6w[0] < 1 Then Return 1
    	If $6w[0] < 2 Then Return 0
    	If $6w[0] = 2 Then $6w[3] = "00"
    	If Not StringIsInt($6w[1]) Then Return 0
    	If Not StringIsInt($6w[2]) Then Return 0
    	If Not StringIsInt($6w[3]) Then Return 0
    	$6w[1] = Int($6w[1])
    	$6w[2] = Int($6w[2])
    	$6w[3] = Int($6w[3])
    	If $6w[1] < 0 Or $6w[1] > 23 Then Return 0
    	If $6w[2] < 0 Or $6w[2] > 59 Then Return 0
    	If $6w[3] < 0 Or $6w[3] > 59 Then Return 0
    	Return 1
    EndFunc   ;==>_qy
    Func _r6($6u, $6y)
    	Local $6v[4], $6w[4]
    	Local $6z = "", $70 = ""
    	Local $71, $72, $73 = ""
    	If Not _qy($6u) Then
    		Return SetError(1, 0, "")
    	EndIf
    	If $6y < 0 Or $6y > 5 Or Not IsInt($6y) Then
    		Return SetError(2, 0, "")
    	EndIf
    	_r7($6u, $6v, $6w)
    	Switch $6y
    		Case 0
    			$73 = _q8($6m, $6g)
    			If Not @error And Not ($73 = '') Then
    				$6z = $73
    			Else
    				$6z = "M/d/yyyy"
    			EndIf
    			If $6w[0] > 1 Then
    				$73 = _q8($6m, $6i)
    				If Not @error And Not ($73 = '') Then
    					$70 = $73
    				Else
    					$70 = "h:mm:ss tt"
    				EndIf
    			EndIf
    		Case 1
    			$73 = _q8($6m, $6h)
    			If Not @error And Not ($73 = '') Then
    				$6z = $73
    			Else
    				$6z = "dddd, MMMM dd, yyyy"
    			EndIf
    		Case 2
    			$73 = _q8($6m, $6g)
    			If Not @error And Not ($73 = '') Then
    				$6z = $73
    			Else
    				$6z = "M/d/yyyy"
    			EndIf
    		Case 3
    			If $6w[0] > 1 Then
    				$73 = _q8($6m, $6i)
    				If Not @error And Not ($73 = '') Then
    					$70 = $73
    				Else
    					$70 = "h:mm:ss tt"
    				EndIf
    			EndIf
    		Case 4
    			If $6w[0] > 1 Then
    				$70 = "hh:mm"
    			EndIf
    		Case 5
    			If $6w[0] > 1 Then
    				$70 = "hh:mm:ss"
    			EndIf
    	EndSwitch
    	If $6z <> "" Then
    		$73 = _q8($6m, $6e)
    		If Not @error And Not ($73 = '') Then
    			$6z = StringReplace($6z, "/", $73)
    		EndIf
    		Local $74 = _r8($6v[1], $6v[2], $6v[3])
    		$6v[3] = StringRight("0" & $6v[3], 2)
    		$6v[2] = StringRight("0" & $6v[2], 2)
    		$6z = StringReplace($6z, "d", "@")
    		$6z = StringReplace($6z, "m", "#")
    		$6z = StringReplace($6z, "y", "&")
    		$6z = StringReplace($6z, "@@@@", _qt($74, 0))
    		$6z = StringReplace($6z, "@@@", _qt($74, 1))
    		$6z = StringReplace($6z, "@@", $6v[3])
    		$6z = StringReplace($6z, "@", StringReplace(StringLeft($6v[3], 1), "0", "") & StringRight($6v[3], 1))
    		$6z = StringReplace($6z, "####", _rb($6v[2], 0))
    		$6z = StringReplace($6z, "###", _rb($6v[2], 1))
    		$6z = StringReplace($6z, "##", $6v[2])
    		$6z = StringReplace($6z, "#", StringReplace(StringLeft($6v[2], 1), "0", "") & StringRight($6v[2], 1))
    		$6z = StringReplace($6z, "&&&&", $6v[1])
    		$6z = StringReplace($6z, "&&", StringRight($6v[1], 2))
    	EndIf
    	If $70 <> "" Then
    		$73 = _q8($6m, $6j)
    		If Not @error And Not ($73 = '') Then
    			$71 = $73
    		Else
    			$71 = "AM"
    		EndIf
    		$73 = _q8($6m, $6k)
    		If Not @error And Not ($73 = '') Then
    			$72 = $73
    		Else
    			$72 = "PM"
    		EndIf
    		$73 = _q8($6m, $6f)
    		If Not @error And Not ($73 = '') Then
    			$70 = StringReplace($70, ":", $73)
    		EndIf
    		If StringInStr($70, "tt") Then
    			If $6w[1] < 12 Then
    				$70 = StringReplace($70, "tt", $71)
    				If $6w[1] = 0 Then $6w[1] = 12
    			Else
    				$70 = StringReplace($70, "tt", $72)
    				If $6w[1] > 12 Then $6w[1] = $6w[1] - 12
    			EndIf
    		EndIf
    		$6w[1] = StringRight("0" & $6w[1], 2)
    		$6w[2] = StringRight("0" & $6w[2], 2)
    		$6w[3] = StringRight("0" & $6w[3], 2)
    		$70 = StringReplace($70, "hh", StringFormat("%02d", $6w[1]))
    		$70 = StringReplace($70, "h", StringReplace(StringLeft($6w[1], 1), "0", "") & StringRight($6w[1], 1))
    		$70 = StringReplace($70, "mm", StringFormat("%02d", $6w[2]))
    		$70 = StringReplace($70, "ss", StringFormat("%02d", $6w[3]))
    		$6z = StringStripWS($6z & " " & $70, $d + $e)
    	EndIf
    	Return $6z
    EndFunc   ;==>_r6
    Func _r7($6u, ByRef $75, ByRef $76)
    	Local $77 = StringSplit($6u, " T")
    	If $77[0] > 0 Then $75 = StringSplit($77[1], "/-.")
    	If $77[0] > 1 Then
    		$76 = StringSplit($77[2], ":")
    		If UBound($76) < 4 Then ReDim $76[4]
    	Else
    		Dim $76[4]
    	EndIf
    	If UBound($75) < 4 Then ReDim $75[4]
    	For $78 = 1 To 3
    		If StringIsInt($75[$78]) Then
    			$75[$78] = Int($75[$78])
    		Else
    			$75[$78] = -1
    		EndIf
    		If StringIsInt($76[$78]) Then
    			$76[$78] = Int($76[$78])
    		Else
    			$76[$78] = 0
    		EndIf
    	Next
    	Return 1
    EndFunc   ;==>_r7
    Func _r8($6t, $79, $7a)
    	If Not _qy($6t & "/" & $79 & "/" & $7a) Then
    		Return SetError(1, 0, "")
    	EndIf
    	Local $7b = Int((14 - $79) / 12)
    	Local $7c = $6t - $7b
    	Local $7d = $79 + (12 * $7b) - 2
    	Local $7e = Mod($7a + $7c + Int($7c / 4) - Int($7c / 100) + Int($7c / 400) + Int((31 * $7d) / 12), 7)
    	Return $7e + 1
    EndFunc   ;==>_r8
    Func _rb($7f, $4v = Default)
    	If $4v = Default Then $4v = 0
    	$7f = Int($7f)
    	If Not _qx($7f) Then Return SetError(1, 0, "")
    	Local $6o = DllStructCreate($39)
    	DllStructSetData($6o, "Year", @YEAR)
    	DllStructSetData($6o, "Month", $7f)
    	DllStructSetData($6o, "Day", 1)
    	Return _q5(BitAND($4v, $6d) ? $6m : $6l, $6o, 0, BitAND($4v, $6c) ? "MMM" : "MMMM")
    EndFunc   ;==>_rb
    Func _rf()
    	Return _r6(@YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC, 0)
    EndFunc   ;==>_rf
    Func _rq($6t)
    	Local $7g = [12, 31, (_qw($6t) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    	Return $7g
    EndFunc   ;==>_rq
    Opt("wintitlematchmode", 2)
    Global $7h = 5
    Global $7i
    Global $7j
    Global $1p
    Global $7k
    Global $7l
    $7m = True
    Global $7n = "c:\temp"
    Global $7o = "debugconsole"
    Global $7p = "(?i)(?:ares|midas)"
    Global $7q = "(?i)(g:|b:)"
    Global $7r = "G:\skydrive\conf\lang\autoit\tamx2txt\tamxlist.txt"
    Global $7s = "G:\skydrive\conf\lang\autoit\tamx2txt\tamxlistdone.txt"
    Global $7t = "G:;;skydrive;;conf;;lang;;autoit;;tamx2txt"
    Global $7u[2][2] = [["ares;;g", "midas;;c"], ["G:", "B:"]]
    Global $7k
    Global $7v, $7w
    Global $7x = 100
    Global $7y = "(?i).*"
    Global $7z = True
    Global $80 = True
    Global $7m = True
    Local $81 = True
    Global $82 = True
    Global $83
    Global $84
    Global $85
    If $82 Then
    	$83 = ""
    	$84 = "notepad.exe"
    	If @ComputerName = "ARES" Then
    		$85 = "TextPad"
    	Else
    		$85 = "Notepad"
    	EndIf
    Else
    	$83 = "C:\Program Files (x86)\Testing Anywhere 9.2\Testing Anywhere"
    	$84 = "TATestEditor.exe"
    	$85 = "Testing Anywhere Client - Test Editor"
    EndIf
    _tv($7y, 1)
    Func _tq($86, $7u)
    	Local $87
    	$87 = StringStripWS($86, 3)
    	$87 = StringRegExpReplace($87, "^file://", "")
    	$87 = StringStripWS($87, 3)
    	For $1p = 0 To UBound($7u, 2) - 1
    		$88 = $7u[1][$1p]
    		$89 = $7u[0][$1p]
    		_tw(1149, "cleanedpath~~" & $87 & "~~$searchstring~~" & "^\b" & $88 & "\b" & "~~$replacestring:" & $89)
    		$87 = StringRegExpReplace($87, "(?i)^" & $88 & "", ";;;;" & $89)
    		$8a = @error
    		If @extended And $7m Then _tw(1152, "~~replaced:$toclean~~" & $86 & "~~$cleaned~~" & $87)
    		If $8a Then
    			_tw(1154, "~~pathconversion~~@error~~" & @error & "~~extended~~" & @extended)
    			Return 0
    		EndIf
    	Next
    	Return $87
    EndFunc   ;==>_tq
    Func _tr($8b, $7t = "g:;;skydrive;;conf;;lang;;autoit;;tamx2txt")
    	$8c = _tq($8b, $7p)
    	_tw(1162, "input:$txtpath~~" & $8c & "~~$searchstring~~" & "(?:;;{2})(" & $7p & ".*)" & "~~replace~~" & $7t & ";;" & "$1" & ".txt")
    	$8c = StringRegExpReplace($8c, "(?:;;{2})(" & $7p & ".*)", $7t & ";;" & "$1" & ".txt")
    	$8a = @error
    	If @extended And $7m Then _tw(1165, "~~replaced $tamxpath~~" & $8b & "~~$txtpath~~" & $8c)
    	If $8a Then
    		_tw(1167, "~~pathconversion~~$tamxpath~~" & $8b & "~~@error~~" & @error & "~~extended~~" & @extended)
    		Return 0
    	Else
    		If $7m Then _tw(1170, "result:$txtpath~~" & $8c)
    		Return $8c
    	EndIf
    EndFunc   ;==>_tr
    Func _ts($8c, $7t = "g:;;skydrive;;conf;;lang;;autoit;;tamx2txt")
    	$8b = _tq($8c, $7q)
    	_tw(1176, "~~pathconversion~~$tamxpath~~" & $8b & @CRLF)
    	_tw(1177, "$tamxpath~~" & $8b & "~~$searchstring" & "(?i:)(?:;;{2})(" & $7t & ";;" & $7p & ".*)" & ".(txt|tax)" & "~~$replacestring~~" & "$1" & ".tamx")
    	$8b = StringRegExpReplace($8b, "(?i:)(?:;;{2})" & $7t & ";;(" & $7p & ".*)" & ".(txt|tax)", "$1" & ".tamx")
    	$8a = @error
    	If @extended Or $7m Then _tw(1180, "~~replaced $txtpath~~" & $8c & "~~to $tamxpath~~" & $8b)
    	If $8a Then
    		_tw(1182, "~~pathconversion~~$txtpath~~" & $8c & "~~@error~~" & @error & "~~extended~~" & @extended)
    		Return 0
    	Else
    		Return $8b
    	EndIf
    EndFunc   ;==>_ts
    Func _tt($8d, $7z = 1)
    	Local $8c, $8b, $8e, $8f, $8g, $7i
    	$7i = _tu($8d, $8c, $8b)
    	If ($7i = 0) Then
    		_tw(1192, "getistoeclude return for $path~~" & $8d & "~~WARNING: cannot convert")
    		Return 1
    	EndIf
    	$8g = Not (FileExists($8b))
    	If $8g Then
    		_tw(1197, "getistoeclude return for $path~~" & $8d & "~~WARNING: excluding not found $tamxpath~~" & $8b)
    		Return 1
    	EndIf
    	$8f = Not (FileExists($8c))
    	If $8f Then
    		_tw(1202, "getistoeclude:$txtdoesnotexist: let's include it to make it exist~~" & $8c)
    		Return 0
    	Else
    		$8h = FileGetTime($8b, $26, $27)
    		$8i = FileGetTime($8c, $26, $27)
    		$8e = ($8h <= $8i) And (Not $7z) Or ((Not ($8h > $8i)) And $7z)
    		_tw(1208, "getistoeclude return for $path~~" & $8d & "~~$isnotupdated~~" & $8e)
    		Return $8e
    	EndIf
    EndFunc   ;==>_tt
    Func _tu($8d, ByRef $8c, ByRef $8b)
    	$8j = _tq($8d, $7q)
    	_tw(1214, "~~pathconversion~~$path~~" & $8d & "~~$cleanedpath~~" & $8j)
    	If ($7z And (StringRight($8d, 5) = ".tamx")) Then
    		$8b = $8d
    		$8c = _tr($8d)
    	Else
    		If (Not $7z) And ((StringRight($8d, 4) = ".txt") Or (StringRight($8d, 4) = ".tax")) Then
    			$8c = $8d
    			$8b = _ts($8d)
    		Else
    			_tw(1223, "~~bad path~~@error~~" & $8d & @CRLF)
    			Return 0
    		EndIf
    	EndIf
    	Return 1
    EndFunc   ;==>_tu
    Func _tv($7y, $7z = 1)
    	$7x = $7h * $7x
    	_1x($7r, $7k, 0)
    	Local $8j
    	Local $8k = 0
    	Local $8l = 0
    	Local $8m = (UBound($7k) - 1)
    	_tw(1236, "$upper" & $8m)
    	For $1p = $8m To 0 Step -1
    		$8j = _tq($7k[$1p], $7u)
    		_tw(1239, "$cleanedpath~~" & $8j)
    		$8k = Not (StringRegExp($8j, $7y, $i))
    		If Not $8k Then $8l = _tt($8j, $7z)
    		If $8k Or $8l Then
    			_tw(1243, "~~At least 1 Sanity Check failed for:~~" & $7k[$1p] & "~~$isexcludedbyfilemaskregex~~" & $8k & "~~$istoExclude~~" & $8l)
    			$7i = _r($7k, $1p)
    			If @error Then
    				_tw(1246, "~~deleting~~" & $7k[$1p] & "~~@error~~" & @error & "~~extended~~" & @extended & @CRLF)
    			Else
    				_tw(1248, "~~deleted~~" & $8j & "~~files left:" & $7i)
    			EndIf
    		Else
    			$7k[$1p] = $8j
    		EndIf
    	Next
    	For $1p = 0 To UBound($7k) - 1
    		Local $8n = $7k[$1p]
    		_tw(1256, "Worker thread for $filepath~~" & $8n)
    		$8o = FileReadToArray($7s)
    		If @error Then
    			_tw(1259, "error opening~~" & $7s)
    		Else
    			If (_14($8o, $8n) > 0) Then
    				_tw(1262, "skipping~~" & $8n)
    				ContinueLoop
    			EndIf
    		EndIf
    		$7v = ProcessExists($84)
    		_tw(1267, "for clean slate close $taepid ~~" & $7v)
    		While $7v
    			ProcessClose($7v)
    			_tw(1270, "processclosed for:" & $7v)
    			$7v = ProcessExists($84)
    			If @error Then _tw(1272, "prcoessclose error~~" & @error)
    			_tw(1273, "processexists still?~~" & $7v)
    			If @error Then _tw(1274, "prcoessclose error~~" & @error)
    		WEnd
    		Local $8p
    		If (StringLen($83) > 0) Then $8p = "\"
    		$8q = '"' & $83 & $8p & $84 & '" "' & $8n & '"'
    		$7v = Run($8q)
    		_tw(1280, "opened $taepid~~" & $7v)
    		If $7z Then
    			If $80 Then
    				Local $8c, $8b
    				$7i = _tu($8n, $8c, $8b)
    				If ($7i = 0) Or $7m Then
    					_tw(1286, "~~converting $filepath~~" & $8n & "~~ result $ret~~" & $7i & "~~to $txtpath~~" & $8c & "~~$tamxpath~~" & $8b)
    				EndIf
    				If Not $82 Then
    					$7i = WinActivate($85, "")
    					_tw(1290, " winactivate $ret~~" & $7i & @CRLF)
    					Sleep($7x)
    					Send("{ALTDOWN}")
    					Sleep($7x)
    					Send("f")
    					Sleep($7x)
    					Send("t")
    					Sleep($7x)
    					Send("{ALTUP}")
    					Sleep($7x)
    					$7i = WinActivate("Save as text File", "")
    					_tw(1301, " winactivate $ret~~" & $7i & @CRLF)
    					Sleep($7x)
    					$7i = ControlSetText("Save as text File", "", "WindowsForms10.EDIT.app.0.ea7f4a_r11_ad11", $8c)
    					_tw(1304, " controlsettext $ret~~" & $7i & @CRLF)
    					Sleep($7x)
    					$7i = ControlClick("Save as text file", "", "WindowsForms10.BUTTON.app.0.ea7f4a_r11_ad13")
    					_tw(1307, "controlclick $ret~~" & $7i & @CRLF)
    					Sleep($7x)
    					Local $7w
    					$7w = ProcessExists("notepad.exe")
    					If $7w Then ProcessClose($7w)
    					If @error Then _tw(1312, "notepadclose error~~" & @error)
    				EndIf
    				If ($81) Then
    					$7i = WinActivate($85, "")
    					If $7i = 0 Then
    						_tw(1317, "cannot winactivate")
    						Sleep(5 * $7x)
    						$7i = WinActivate($85, "")
    						If $7i <> 0 Then _tw(1320, "could winactivate try2")
    					EndIf
    					If Not $82 Then
    						ControlClick("Testing Anywhere Client - Test Editor", "", "WindowsForms10.Window.8.app.0.ea7f4a_r11_ad125", "left", 96, 16)
    						Sleep(5 * $7x)
    					EndIf
    					Local $8r = True
    					Local $8s[1]
    					Local $8t = 0
    					Local $8u = 0
    					$7i = WinActivate($85, "")
    					If $7i = 0 Then
    						_tw(1332, "cannot winactivate")
    						Sleep(5 * $7x)
    						$7i = WinActivate($85, "")
    						If $7i <> 0 Then _tw(1335, "could winactivate try2")
    					EndIf
    					While ($8r)
    						$8t = $8t + 1
    						ReDim $8s[$8t + 1]
    						Sleep($7x)
    						Send("{end}")
    						Sleep($7x)
    						Send("{space}")
    						Sleep($7x)
    						Send("{left}")
    						Sleep($7x)
    						Send("+{home}")
    						Sleep($7x)
    						Send("^c")
    						Sleep($7x)
    						Send("{down}")
    						Sleep($7x)
    						Local $8v = ClipGet()
    						Sleep($7x)
    						$8v = StringStripWS($8v, 3)
    						If @error Then
    							_tw(1357, "error:Clipget $astrlines[$i] error~~" & @error)
    						EndIf
    						Sleep($7x)
    						$8s[$8t] = $8v
    						Local $8w, $8x, $8u = 0
    						If Mod($8t, 5) = 0 Then
    							_tw(1363, "$iteration~~" & $8t)
    							If ($8s[$8t] = $8s[$8t - 1]) Then
    								_tw(1365, "At $iteration, EQUAL~~" & $8t & "~~test~~" & $8s[$8t] & "<>?>" & $8s[$8t - 1])
    								If $8s[$8t] = $8s[$8t - 2] Then
    									_tw(1367, "At $iteration, EQUAL~~" & $8t & "~~test~~" & $8s[$8t] & "<>?>" & $8s[$8t - 1])
    									If $8s[$8t] = $8s[$8t - 3] Then
    										_tw(1369, "At $iteration, EQUAL~~" & $8t & "~~test~~" & $8s[$8t] & "<>?>" & $8s[$8t - 1])
    										If $8s[$8t] = $8s[$8t - 4] Then
    											_tw(1371, "At $iteration, EQUAL~~" & $8t & "~~test~~" & $8s[$8t] & "<>?>" & $8s[$8t - 1])
    											If $8s[$8t] = $8s[$8t - 5] Then
    												$8r = False
    												_tw(1374, "$notendoffile" & $8r)
    												$8u = 5
    												_tw(1376, "now:" & $8u)
    												If (UBound($8s) >= 9) Then
    													If $8s[$8t] = $8s[$8t - 6] Then
    														$8u = $8u + 1
    														_tw(1380, "now:" & $8u)
    														If $8s[$8t] = $8s[$8t - 7] Then
    															$8u = $8u + 1
    															_tw(1383, "now:" & $8u)
    															If $8s[$8t] = $8s[$8t - 8] Then
    																$8u = $8u + 1
    																_tw(1386, "now:" & $8u)
    																If $8s[$8t] = $8s[$8t - 9] Then
    																	$8u = $8u + 1
    																	_tw(1389, "now:" & $8u)
    																EndIf
    															EndIf
    														EndIf
    													EndIf
    												EndIf
    											EndIf
    										EndIf
    									EndIf
    								EndIf
    							Else
    								_tw(1400, "At $iteration, UNEQUAL~~" & $8t & "~~test~~" & $8s[$8t] & "<>?>" & $8s[$8t - 1])
    							EndIf
    						EndIf
    						_tw(1403, "$notendoffile before wend~~" & $8r)
    						Sleep($7x)
    					WEnd
    					Local $8x = 1
    					Local $2x = "", $2y = "", $2z = "", $30 = ""
    					Local $8y = _24($8n, $2x, $2y, $2z, $30)
    					If Not (FileExists($2x & "\" & $2y)) Then DirCreate($2x & "\" & $2y)
    					$8z = $2x & $2y & $2z & ".tax"
    					_tw(1411, "$filepathTAX~~" & $8z)
    					Sleep($7x)
    					For $8x = 1 To $8u
    						$8w = _r($8s, UBound($8s) - 1)
    					Next
    					Sleep($7x)
    					$7i = _1y($8z, $8s, 1)
    					If ($7i = 0) Then
    						_tw(1419, "_FileWriteFromArray @error~~" & _1y)
    					EndIf
    					Sleep($7x)
    					$7i = FileWriteLine($7s, $8n)
    					If $7i = 0 Then _tw(1423, "failed writing log~~" & $8n)
    				EndIf
    			EndIf
    		Else
    			Sleep($7x)
    			MsgBox(0, "Not implemented!", "and likely unimplementable! I will now eject you...")
    			Exit
    			$7i = WinActivate($85, "")
    			If $7i = 0 Then
    				$7i = WinActivate($85, "")
    				Sleep($7x)
    				If $7i = 0 Then
    					Send("{!TAB}")
    					Sleep($7x)
    					$7i = WinActivate($85, "")
    					_tw(1438, "@error=" + @error + ". comment: " + ("To activate, had to resort to ALT +TAB." & @CRLF))
    					If $7i = 0 Then
    						_tw(1440, "@error=" + @error + ". comment: " + ("Cannot activate " & $85 & "~~exiting!"))
    						Exit
    					EndIf
    				EndIf
    			EndIf
    			Sleep($7x)
    			If @error Then
    				_tw(1447, "~~@error~~" & @error & "~~Activated~~" & $85)
    			EndIf
    			Send("^a")
    			Sleep($7x)
    			Send("{DEL}")
    			Send("^a")
    			Sleep($7x)
    			Send("{DEL}")
    			Sleep($7x)
    			For $1p = 0 To UBound($8s) - 1
    				ClipPut($8s[$1p])
    				Send("{home}")
    				Sleep($7x)
    				Send("+{end}")
    				Send("^v")
    				Sleep($7x)
    				Send("{enter}")
    				Sleep($7x)
    				If @error Then _tw(1465, "@error=" + @error + ". comment: " + ($7j & "."))
    			Next
    			If Not ($82) Then
    				Send("^H")
    				Send("^S")
    			Else
    				Send("^s")
    			EndIf
    			MsgBox(0, "Not implemented!", "construction site! I will now eject you...")
    			Exit
    		EndIf
    		$7i = ProcessClose($7v)
    		Sleep($7x)
    		_tw(1478, "result closing test editor:" & $7i)
    		If @error Then _tw(1479, "processclose error~~" & @error)
    		Sleep($7x)
    		$7v = ProcessExists($84)
    		Sleep($7x)
    		$7i = ProcessClose($7v)
    		Sleep($7x)
    		_tw(1485, "2nd try: closing test editor:" & $7i)
    		If @error Then _tw(1486, "processclose error~~" & @error)
    	Next
    EndFunc   ;==>_tv
    Func _tw($90 = 1489, $91 = "Error")
    	Local $92
    	Local $93
    	Local $94
    	$94 = @TempDir
    	If $94 == "" Then
    		If Not FileExists($7n) Then DirCreate($7n)
    		$94 = $7n
    	EndIf
    	$92 = $90 & "~" & _rf() & "~" & $91
    	If $7o = "debug" Then
    		Local $95 = WinGetTitle("")
    		MsgBox(0, "debug", $92)
    		WinActivate($95)
    	ElseIf $7o = "debugconsole" Then
    		ConsoleWrite($92 & Chr(13))
    	ElseIf $7o = "run" Then
    		If $94 == "" Then $94 = $7n
    		$93 = _tx($92, $94) & ".jpg"
    		_p6($93)
    		_8($92)
    	ElseIf $7o = "debugconsolescreen" Then
    		ConsoleWrite($92 & Chr(13))
    		$93 = _tx($92, $94) & ".jpg"
    		_p6($93)
    	ElseIf $7o = "releasetextlog" Then
    		If $7l == "" Then $7l = @TempDir & "\" & "autoitlogfile.log"
    		$96 = FileOpen($7l, 1)
    		If $7i = 0 Or @error Then Exit
    		$7i = FileWriteLine($96, $92 & Chr(13))
    		If $7i = 0 Or @error Then Exit
    		$7i = FileClose($96)
    	ElseIf $7o = "releasewordpad" Then
    	Else
    		SetError(1)
    	EndIf
    EndFunc   ;==>_tw
    Func _tx($97, $94)
    	$97 = StringReplace($97, ":", "_")
    	$97 = StringReplace($97, ">", "larger_than")
    	$97 = StringReplace($97, "<", "smaller_than")
    	$97 = StringReplace($97, " ", "_")
    	$97 = StringReplace($97, "/", "&")
    	$97 = StringReplace($97, "/", "+")
    	$97 = StringReplace($97, "&", "+")
    	$97 = StringReplace($97, Chr(9), "_")
    	$97 = StringReplace($97, "?", "questionmark")
    	$97 = StringReplace($97, "!", "exclamationmark")
    	$97 = StringReplace($97, "'", "quotationmark")
    	$97 = StringReplace($97, Chr(34), "doublequotationmark")
    	$97 = StringReplace($97, "__", "_")
    	$97 = StringReplace($97, "__", "_")
    	$97 = StringReplace($97, "__", "_")
    	$97 = StringReplace($97, "__", "_")
    	$97 = $94 & "\" & $97
    	Return $97
    EndFunc   ;==>_tx
    
      

    How to add control of student sound/recording volume, sidetone, restart, and more to a Sanako Study 1200 environment, using the Launch Program feature and AutoIt

    2014/08/22 1 comment
    1. UPDATE: A Windows7 (and Vista) version – which also uses a simplified deployment mechanism – is in the works, check back for a new post here.
    2. In refining our Sanako classroom setup, we improved the control, that the Sanako Study 1200 affords the teacher over the student clients in the computerized classroom,
    3. by extending the built-in Launch Program feature
    4. with custom-made executables (realized in AutoIt V3) that can control the volume (here on Windows XP SP3).
    5. This it how it works: Launch any of the programs (what each does is in its name) to any individual/group of students or the entire class in order to do any of these things on the student computers that the Sanako out of the box does not allow you to control, and that I often wish I could do when teaching language classes in a Sanako (or other computerized classroom management system) environment, like
      1. controlling the volume of what the students
        1. hears
        2. records
      2. turning the student sidetone (= echoing back the student microphone into the student headset) on and off
      3. starting/pausing Windows Media Player
      4. launching/closing quiz files in MS-Word
      5. restarting an entire (misbehaving) student applications
    6. Here is what we have: sanako-launch-programs-autoit1
    7. Here is how using what we have looks like:
    8. sanako-launch-programs-autoit
    9. You can now request the download of these language lab enhancing programs, including source code, here.

    Request to download the digital audio lab classroom audio configuration on the fly, program and source for Windows XP

    UPDATE: A Windows7 (and Vista) version is in the works, check back for a new post here.

    Back to description of reset of classroom audio configuration on the fly program

    Manage some of your teacher computer settings per logged in user

    1. Another day, another hack, and inconsequential, unless of course you are in my situation:
    2. If you need a simple way to change some of your Sanako settings per logged in user
    3. but cannot use the logged-in user system built into Sanako Study 1200:

     

    $path = "C:\ProgramData\Sanako\Study\Tutor\"
    
    
    
    If (@UserName = "PRTOTECTTHEINNOCENT") Then	
    
    ; change the sanako default save to dual track supporting mff
    
    	; prereq: customized settings files in the folder ready to rename 
    
    	FileCopy($path & "mffTutor.Settings", $path & "Tutor.Settings", 1)
    
    ElseIf (@UserName = "tplagwit") Then 
    
    ; change the sanako default save to dual track supporting wma, for testing
    
    	FileCopy($path & "wmaTutor.Settings", $path & "Tutor.Settings", 1)
    
    Else 
    
    ; keep the default mp3, but we may have to reset the tutorsettings on this unfrozen computer
    
    	FileCopy($path & "mp3Tutor.Settings", $path & "Tutor.Settings", 1)
    
    EndIf
    
    ; tutor.exe could be hardcoded to (re)load here
    
    If ProcessExists("Tutor.exe") Then
    
    	; determine: we could kill tutor to reload it, but that could be disruptive of a class
    
    Else
    
    	Run("C:\Program Files (x86)\SANAKO\Study\Tutor\Tutor.exe")
    
    EndIf
    
    Exit

    First steps with the teacher-training-setup for Sanako Study 1200 v7 in a deepfrozen computer lab environment

    1. I remember a time when the vendor travelled onsite to provide faculty induction into the Sanako Lab300, they set up the student PCs with a special version of the tutor software that multiple faculty could gain hands-on experience during a workshop.
    2. I have sorely missed this facility during my own 8 years’ of experience training faculty in using the successor product, Sanako Study 1200. No longer: With Sanako 7, Sanako provides to the digital audio lab manager an installer that sets up a similar environment for faculty in a Sanako Study 1200 lab. Below are some observations how to get this to run what should be a fairly typical HE language lab environment
    3. Install, in frozen state, as admin:
      1. Uninstall Sanako student recorder from appwiz.cpl
      2. Install "S:\COAS\LCS\MYDEPT\LRC\Secure\software\Sanako\7\TeacherTrainingSETUP.EXE" (right-click, run as admin)
      3. Is mostly hands-free, but I’d prefer an MSI with a /quiet install option, then I could automate that.  
        1. One could write AutoIt script compiled to .exe that uninstalls student recorder? Need to know the msicache location ?
      4. Neither Uninstall of student recorder nor install of teacher-training-setup require a restart  -  is suitable for installation on otherwise frozen lab installation
    4. Additional setup required:
      1. I got an error about corrupt student settings file, but it worked.
      2. Loading students from "corridor"
        1. On unfrozen office computer, I got an error about student settings corrupt, but teacher could load students
        2. On frozen lab computer, I get no error, but teacher does not see students, although 5 have been started – Is an original student settings hanging around?
        3. After tutor setup (do not require tutor login) and restart, I get this error on the tutor: image
        4. And this crash of the student: image
        5. But now is see these signs of success :
          1. on student timage
          2. on tutor this : image
          3. And it works: image
      3. We have to unblock tutor in firewall twice:
        1. Initiate a screen sharing , then unblock : image
        2. For audio: initiate a model imitation with collect, then unblock.
      4. Set Collection path:
        1. Initiate a homework collection , set collect path to a suitable folder (here S:\COAS\LCS\LRC\sanako\student).
        2. Not needed for audio collection.
      5. Other observations:
        1. Uses file download, not stream audio, to students: You can see the tutor and the student applications at the same time, monitoring the effects your tutor operations would have in the classroom
          1. Why at first 2 students and then 3? image
        2. Remote control:
          1. Note that screen sharing will switch aero off on your computer
          2. Note that button:"collaborate" does weird things to your mouse, make sure you can even get back to the button:"monitor" to turn it off.
      6. Setup TeacherTrainingSETUP for each workshop participant.
        1. The msi packages contained in teacher training setup as of Fall 2013, in case you ever get around automating the installer using AutoIt that you can deploy it from teacher station instead of having to touch each machine, please share: imageimageimage

      Sanakoaudioconfigonthefly software utilities updated for Vista/Windows7

      1. (Shortcut to download – now fixed) The reason why a colleague’s signature reads: “Worrying about a large institution, especially when it has computers, is like worrying about a large gorilla, especially when it’s on fire" (Bruce Sterling) might just be that a multimedia-capable fully computerized classroom – think 30 PCs and 30 students trying not only to listen to, but record responses to exam audio – is a notoriously difficult beast to control, and all too easily spins out of the same (a classroom humming in an endless audio feedback loop is neither a pleasant nor an unfamiliar sight).
      2. The Sanako Study 1200 is a digital audio lab software that facilitates the use of personal computers in face-to-face class settings. However, while the Sanako Study 1200 features many ways for the teacher to control and manage the student PCs, the students’ audio settings cannot be controlled on the fly.
      3. Enter these little sanakoaudioconfigonthefly utilities (written in AutoIt) for Windows 7 and Vista  (old Windows PX version still available here) that extend the Sanako Study 1200.
      4. We now use  (as it is completely adequate and actually superior to to the seemingly more applicable PC control / Launch programs features which is requires the program executable to reside under the same path on student and tutor computer) Playlist / copy and launch (folder icon) and the Sanako grouping feature to send a program with your choice of action to the student PCs  of your choice. In this example,
        1. click playlist, 01
        2. and in the window that opens, click (1) to send to “all”, then click (2) to select which program to send: image_thumb[3]
      5. Files included in this release (each for 64-bit, and as source code, so that you can compile your own if you are still on MS-Vista/MS-Windows-732-bit platform):
        1. Change student recording levels (microphone sensitivity).
        2. Toggle student sidetone ( in Sanako = “listen” to this device in Windows)
        3. Control student playback level (headphone volume).
      6. Likely these programs can be adapted beyond Sanako Study 1200, but I do not remember (helpful comments appreciated)
        1. whether other digital audio lab platforms (Sony Virtuoso, Robotel SmartClass) allow for changing the student audio config on the fly
        2. and what mechanism (if any – but likely) they (and Sanako Lab300) provide to launch programs on the students’ computers
      7. Prerequisites:
        1. None other than your digital audio lab software and the utilities you can download below. In particular, it is not required to install AutoIt on teacher or student computers.
        2. However, there should be only 1 microphone/speaker per student computer in the digital audio lab. If you have more, you likely have bigger problems to solve first, but you also need to alter the source code (included) to select the microphone you want to work with (should be easy; note however, that I have not tested this scenario, for: “There should be only 1 microphone/speaker per student computer in the digital audio lab” Smile
      8. Request here to download these utilities.

        Request to download the digital audio lab classroom audio configuration on the fly, program and source for Windows 7