SkaziChris Posted March 16, 2019 Posted March 16, 2019 Hello, Situation: I have 4-screen setup. I work via citrix session that is stretched across 2 monitors, but inside the session, it acts like a one single big monitor. So, whenever you press Maximize button in any app, it maximizes across 2 monitors ;/ So, I wrote a little UDF that identifies active windows that have size bigger than the screen VRES of 1 display, and then, it places the window on proper monitor (F9 -> left, F10 -> right). However, the script works fine for 5-10 minutes, and then fails with: Line 4086 (File <exe path>): Error: Subscript used on non-accessible variable. I have added IsHwnd checks, but this didn't help. Would you be so kind and help me pinpoint the issue? expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=add_tab_ol_512_swy_icon.ico #AutoIt3Wrapper_Outfile=Citrix_MaintainWindows_v1_x86.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <EditConstants.au3> ; *** End added by AutoIt3Wrapper *** #include <ImageSearch.au3> #include <MsgBoxConstants.au3> #include <GUIConstantsEx.au3> #Include <GUIEdit.au3> #include <WinAPI.au3> GUISetIcon("add_tab_ol_512_swy_icon.ico") TraySetIcon("add_tab_ol_512_swy_icon.ico") Global $y = 0, $x = 0 Global $temp_x = 0, $temp_y = 0 Global $_hWnd = "null" Global $try = 0 Global $error = "false" Global $msgx = "null" Global $Paused Global $EditBox1, $EditBox2 Global $monitor1resX=1680 Global $monitor1resY=990 Global $monitor2resX=1280 Global $monitor2resY=990 Global $currWindowPosX=0 Global $currWindowPosY=0 Global $msgtxt HotKeySet("{PAUSE}", "TogglePause") Func TogglePause() $Paused = NOT $Paused While $Paused sleep(100) ToolTip('Script is "Paused = SCRIPT IS NOT RUNNING = you wont get another message if you dont unpause it"',0,0) WEnd ToolTip("") EndFunc Func Terminate() Exit 0 EndFunc Func MoveLeft() Send("{F9}") ;This will move the app to the left screen by an external app (with F9 kb shortcut) Sleep(1000) EndFunc Func MoveRight() Send("{F10}") ;This will move the app to the left screen by an external app (with F10 kb shortcut) Sleep(1000) EndFunc Func MaintainWindowSize() ; windows that should be put on the LEFT side: $lewe = "Notepad;Word;Excel;Outlook;Explorer;Chrome;DBInventory;Message ;null" $array_left=StringSplit($lewe, ";") ; windows that should be put on the RIGHT side: $prawe = "SQL*Security;Oracle Centralized Security;Putty;Oracle SQL Developer" $array_right=StringSplit($prawe, ";") ; windows classes that should be put on the RIGHT side: $praweCl = "TMobaXtermForm;null" $array_rightCl=StringSplit($praweCl, ";") ; windows classes that should be put on the LEFT side: $leweCl = "ExploreWClass;CabinetWClass;null" $array_leftCl=StringSplit($leweCl, ";") $hw = WinActive("","") if IsHWnd($hw) Then WinActivate($hw) $wT=WinGetTitle( "[ACTIVE]" ) $aWindowSize = WinGetClientSize($hw) $width=$aWindowSize[0] else break EndIf ;resolution of the citrix session: 3340x1010 ;each monitor has res 1680x1050 ;so, if the app window has Vsize bigger than 2000, this means it is stretched to more than 1 monitor. ;therefore, position that window to the right monitor... if $width > 2000 Then ; wT=window titile if IsHWnd($hw) Then WinSetState($hw,"",@SW_RESTORE) $wT=WinGetTitle( "[ACTIVE]" ) $wC=_WinAPI_GetClassName($hw) else break EndIf ;MsgBox($MB_SYSTEMMODAL, "", $wC) For $i = 1 to $array_left[0] If stringinstr($wT , $array_left[$i]) Then MoveLeft() EndIf Next For $j = 1 to $array_right[0] If stringinstr($wT , $array_right[$j]) Then MoveRight() EndIf Next For $k = 1 to $array_rightCl[0] If stringinstr($wC , $array_rightCl[$k]) Then MoveRight() EndIf Next For $l = 1 to $array_leftCl[0] If stringinstr($wC , $array_leftCl[$l]) Then MoveLeft() EndIf Next EndIf EndFunc Func Main() While Not @error; Try MaintainWindowSize() Sleep(100) WEnd If @error Then; Catch MaintainWindowSize() EndIf EndFunc ;==>Main Main()
Bilgus Posted March 17, 2019 Posted March 17, 2019 (edited) Can't really test it for you but how is this? expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=add_tab_ol_512_swy_icon.ico #AutoIt3Wrapper_Outfile=Citrix_MaintainWindows_v1_x86.exe #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <EditConstants.au3> ; *** End added by AutoIt3Wrapper *** ;#include <ImageSearch.au3> #include <MsgBoxConstants.au3> #include <GUIConstantsEx.au3> #include <GUIEdit.au3> #include <WinAPI.au3> GUISetIcon("add_tab_ol_512_swy_icon.ico") TraySetIcon("add_tab_ol_512_swy_icon.ico") Global $y = 0, $x = 0 Global $temp_x = 0, $temp_y = 0 Global $_hWnd = "null" Global $try = 0 Global $error = "false" Global $msgx = "null" Global $bPaused Global $EditBox1, $EditBox2 Global $monitor1resX = 1680 Global $monitor1resY = 990 Global $monitor2resX = 1280 Global $monitor2resY = 990 Global $currWindowPosX = 0 Global $currWindowPosY = 0 Global $msgtxt HotKeySet("{PAUSE}", "TogglePause") Func TogglePause() $bPaused = Not $bPaused While $bPaused Sleep(100) ToolTip('Script is "Paused = SCRIPT IS NOT RUNNING = you wont get another message if you dont unpause it"', 0, 0) WEnd ToolTip("") EndFunc ;==>TogglePause Func Terminate() Exit 0 EndFunc ;==>Terminate Func MoveLeft() Send("{F9}") ;This will move the app to the left screen by an external app (with F9 kb shortcut) ConsoleWrite("Move Left" & @CRLF) Sleep(1000) EndFunc ;==>MoveLeft Func MoveRight() Send("{F10}") ;This will move the app to the left screen by an external app (with F10 kb shortcut) ConsoleWrite("Move Right" & @CRLF) Sleep(1000) EndFunc ;==>MoveRight Func MaintainWindowSize() ; windows that should be put on the LEFT side: ;I'd probably move these global and only update them in another function making them static for now.... Static Local $sLeftWinTitles = "Notepad;Word;Excel;Outlook;Explorer;Chrome;DBInventory;Message ;null" Static Local $aLeft = StringSplit($sLeftWinTitles, ";") ; windows that should be put on the RIGHT side: Static Local $sRightWinTitles = "SQL*Security;Oracle Centralized Security;Putty;Oracle SQL Developer" Static Local $aRight = StringSplit($sRightWinTitles, ";") ; windows classes that should be put on the RIGHT side: Static Local $sRightWinClasses = "TMobaXtermForm;null" Static Local $aRightCL = StringSplit($sRightWinClasses, ";") ; windows classes that should be put on the LEFT side: Static Local $sLeftWinClasses = "ExploreWClass;CabinetWClass;null" Static Local $aLeftCL = StringSplit($sLeftWinClasses, ";") ;;; Static Local $hWnd_Last = 0 ;Save last active Window so we don't check endlessly Local $sTitle, $aWindowSize, $iWidth, $sClass Local $hWnd = WinGetHandle("[ACTIVE]", "") If IsHWnd($hWnd) And $hWnd <> $hWnd_Last Then $hWnd_Last = $hWnd ;WinActivate($hWnd);Probably Not Needed?? $sTitle = WinGetTitle($hWnd) $aWindowSize = WinGetClientSize($hWnd) If @error Or Not IsArray($aWindowSize) Then Return SetError(1, 0, "") $iWidth = $aWindowSize[0] Else Return ;break EndIf ;resolution of the citrix session: 3340x1010 ;each monitor has res 1680x1050 ;so, if the app window has Vsize bigger than 2000, this means it is stretched to more than 1 monitor. ;therefore, position that window to the right monitor... If $iWidth > 2000 Then If IsHWnd($hWnd) Then WinSetState($hWnd, "", @SW_RESTORE) ;$sTitle = WinGetTitle($hWnd);Already have the title $sClass = _WinAPI_GetClassName($hWnd) Else Return ;break EndIf ;MsgBox($MB_SYSTEMMODAL, "", $sClass) If IsArray($aLeft) Then For $i = 1 To $aLeft[0] If StringInStr($sTitle, $aLeft[$i]) Then MoveLeft() EndIf Next Else Return SetError(2, 0, "") EndIf If IsArray($aRight) Then For $j = 1 To $aRight[0] If StringInStr($sTitle, $aRight[$j]) Then MoveRight() EndIf Next Else Return SetError(3, 0, "") EndIf If IsArray($aRightCL) Then For $k = 1 To $aRightCL[0] If StringInStr($sClass, $aRightCL[$k]) Then MoveRight() EndIf Next Else Return SetError(4, 0, "") EndIf If IsArray($aLeftCL) Then For $l = 1 To $aLeftCL[0] If StringInStr($sClass, $aLeftCL[$l]) Then MoveLeft() EndIf Next Else Return SetError(5, 0, "") EndIf EndIf EndFunc ;==>MaintainWindowSize Func Main() Local $iError = 0 While Not $iError ; Try MaintainWindowSize() $iError = @error Sleep(100) WEnd If $iError Then ; Catch MsgBox(0, "Error", $iError) ;MaintainWindowSize() EndIf EndFunc ;==>Main Main() Edited March 17, 2019 by Bilgus SkaziChris 1
SkaziChris Posted March 17, 2019 Author Posted March 17, 2019 Thanks so much Bilgus!!! Following part: If IsHWnd($hWnd) And $hWnd <> $hWnd_Last Then + corrected error handling fixed it!!!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now