Jump to content

hWnd and error: Subscript used on non-accessible variable


Recommended Posts

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?
 


 

#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()

 

Link to comment
Share on other sites

Can't really test it for you but how is this?

#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 by Bilgus
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...