Subversion Repositories Moxba-Metrex.metrex

Rev

Blame | Last modification | View Log | Download

;==============================================================================
;
; Script version: 3.0
; Script date:    12-06-2019
; AutoIt Version: 3.0
; Language:       English
; Platform:       WinXP/2003/Vista/Win7/Win10
; Author:         Marcel Jordaan (mjordaan@rldautomation.eu)
;
; Script Function:
;  Starts the FactoryLink webclient using graph.exe, and accepts the the same
;  commandline parameters as graph.exe.
;  This script will start the weblcient and close all popup messageboxes re-
;  porting errors, normally webclient will close after accepting popup
;  messages!
;
;  Settings for this script are located in flweb.ini (same directory as
;  flweb.exe)
;
;   Note: the path variable should be set to the bin-directory where webclient
;   is installed
;
; Usage:
;   Calling this script in cmd or batch file makes it possible to auto-close
;   webclientafter an error, and restart the same or an alternative weblcient
;   connection.
;==============================================================================


;=======================================================================================
; GLOBAL Options definitions
;=======================================================================================

; default is progam icon hidden, with option HIDE_ICON in flweb.ini the program
; icon can beshown or hidden
#NoTrayIcon


;=======================================================================================
; INCLUDE Files
;=======================================================================================

; include files
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <IE.au3>
#Include <WinAPI.au3>
#Include <Constants.au3>
#include <Array.au3>
#include <Process.au3>
#include <_IsUACAdmin.au3>


;=======================================================================================
; OPTIONS for script
;=======================================================================================

; Set the different ptogam options
Opt("TrayAutoPause", 0)   ; Script pauses when click on tray icon
Opt("TrayMenuMode", 1)    ; Extend the behaviour of the script tray icon/menu
                          ; 1 = no default menu
Opt("TrayOnEventMode", 1) ; Enable/disable OnEvent functions notifications for the tray


;==============================================================================
; Main flweb
;==============================================================================

; main variables
$startup = -1
$webclient = -1
$GraphhWnd = 0
$server = 0
$single = 0 ;use all available servers

;Create tray icon menu, only Exit
$ExitId = TrayCreateItem("Exit")
TrayItemSetState( $ExitId, $TRAY_UNCHECKED)
TrayItemSetOnEvent( $ExitId, "WcExit")

;define and register exit function
OnAutoItExitRegister( "MyexitFunction")

;initialize the command line parameter string
$params = ""
$inifile = @ScriptDir & "/flweb.ini"

;Get the commandline and build the parameter list for webclient
For $i = 1 to $CmdLine[0] step 1

  $params = $params & " " & $CmdLine[$i]
Next

;if only one instance per user is allowed; check if we are already running
$oneinst = Int( IniRead( $inifile, "WEBCLIENT", "ONE_INSTANCE" , "1"))

;show popup we are already running and Exit
if $oneinst <> 0 then

  ; current user's SessionId
  $sid = _WTSQuerySessionInformation(-1, 4)
  ;dbg( "Webclient: SessionId=" & $sid)

  ; get our process name and id
  $name = _ProcessGetName( @AutoItPID)
  ;dbg( "Webclient: scriptname=" & $name)

  ;If Not Ping(@ComputerName,200) Then SetError(1)
  $objWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & @ComputerName & "\root\CIMV2")
  ;If Not IsObj($objWMI) Then SetError(2)
  $query = "SELECT * FROM Win32_Process WHERE SessionId = " & $sid & "and Name Like '" & $name & "%'"
  ;dbg( "Webclient: WMI query=" & $query)

  $colItems = $objWMI.ExecQuery ($query)
    ;Dim $arrResults[1][3] = [["Processname","ProcessID","SessionID"]]
    ;For $objItem In $colItems
    ;    ReDim $arrResults[UBound($arrResults)+1][3]
    ;    $arrResults[UBound($arrResults)-1][0] = $objItem.Name
    ;    $arrResults[UBound($arrResults)-1][1] = $objItem.ProcessId
    ;    $arrResults[UBound($arrResults)-1][2] = $objItem.SessionId
    ;Next
  ;dbg( "Webclient: nr instances running=" & $colItems.Count)

  ;current script is nr 1, if there is already a script running it is the second one
  if $colItems.Count > 1 then

    SplashTextOn("FactoryLink Webclient", "Only one instance allowed, exiting", -1, 70, -1, -1, 18)
    Sleep( 3500)
    SplashOff()
    exit
  endif
endif

$UACadmin = _IsUACAdmin()
;look for registry settings for graph
;check if webclient.reg exists

if $UACadmin Then
   $test = StringCompare(@OSArch, "X86")
;msgbox(1, "UAC", "@OSarch = "& @OSArch & "test=" & $test)
  Switch $test
    Case 0
     $reg_stdfile = @ScriptDir & "\webclient3_x86.reg"
    Case Else
      $reg_stdfile = @ScriptDir & "\webclient3.reg"
  EndSwitch

  $reg_file = IniRead( $inifile, "WEBCLIENT", "GRAPH_REGFILE" , $reg_stdfile)

  if FileExists($reg_file) Then
    ;add registry values, or overwrite
    ;RunWait( "regedit /s " & $reg_file)
  IniWrite($inifile, "WEBCLIENT", "WEBCLIENT_SET", "1")
  Exit
  EndIf
EndIf

;check for the use of one server only: server_1
if  (StringCompare( StringStripWS($params, 3), "-s1") == 0) then
  $single = 1
  $params = ""
EndIf

;check for the use of one server only: server_2
if  (StringCompare( StringStripWS($params, 3), "-s2") == 0) then
  $single = 2
  $params = ""
EndIf

;array for two servers
local $serverx[2]
;Server definitions are default empty
$serverx[0] = ""
$serverx[1] = ""

;dbg( "Webclient: $params = " & $params)
;dbg( "Webclient: $single = " & $single)

;Show splash screen
$splash = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN" , "0"))
$splash_width = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN_WIDTH" , "600"))
$splash_height = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN_HEIGHT" , "375"))
$splash_x = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN_X" , "-1"))
$splash_y = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN_Y" , "-1"))
$splash_option = Int( IniRead( $inifile, "WEBCLIENT", "SPLASH_SCREEN_OPTION" , "18"))

if $splash <> 0 then
  SplashImageOn("FactoryLink Webclient", "web_splash.jpg", $splash_width, $splash_height, $splash_x, $splash_y, $splash_option)
endif

while (($webclient <> 0) or ($startup <> 0))

  ;dbg( "Webclient: $webclient=" & $webclient & "; $startup=" & $startup)

  if ($startup <> 0) then

    ;if there is a command line, ignore settings in the ini-file
    ;settings ignored are arguments and server definitions, mark
    ;that from the comand line only one server can be defined!
    if ($params == "") then

      ;read arguments and server definitions
      $params = IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_ARGUMENTS" , "")
      $serverx[0] = "-h" & IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_SERVER1" , "")
      $serverx[1] = "-h" & IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_SERVER2" , "")

      ;dbg( "Webclient: $single = " & $single)
      ;dbg( "Webclient: $server = " & $server)
      ;dbg( "Webclient: $params = " & $params)
      ;dbg( "Webclient: $serverx[0] = " & $serverx[0])
      ;dbg( "Webclient: $serverx[1] = " & $serverx[1])

      ;active server is server1
    if ($single == 0) then
        $server = 0
    else
    $server = $single - 1
      endif

      if ($params <> "") then
        $params = $params & ","
      else
        $params = " "
      endif
    endif

    ;Read settings from flweb.ini file in current working directory
    $WebCLientDir = IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_DIR" , "C:\Program Files\Siemens\FactoryLink\Client\WebClient\Bin")
  $GraphSET = Int( IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_SET" , "1"))
    if $GraphSET then
      RunWait( $WebCLientDir & "/graphset.exe")
      IniWrite($inifile, "WEBCLIENT", "WEBCLIENT_SET", "0")
    EndIf
    $WebCLientClass = IniRead( $inifile, "WEBCLIENT", "WINCLASS" , "dispclass")
    $WebCLientWin = IniRead( $inifile, "WEBCLIENT", "MAINWIN_NAME" , "APPLICATION")
    $WebCLientStyle = IniRead( $inifile, "WEBCLIENT", "MAINWIN_STYLE" , "0x94000000")
    $WebCLientWinChange = Int( IniRead( $inifile, "WEBCLIENT", "MAINWIN_CHANGE" , "0"))
    $FullScreenChange = Int( IniRead( $inifile, "WEBCLIENT", "FULLSCREEN_CHANGE" , "0x94000000"))
    $FullScreenStyle = IniRead( $inifile, "WEBCLIENT", "FULLSCREEN_STYLE" , "0x94000000")

    $WebCLientAlwaysActive = Int( IniRead( $inifile, "WEBCLIENT", "WEBCLIENT_ALWAYS_ACTIVE" , "0"))

    $MainWin_X = Int( IniRead( $inifile, "WEBCLIENT", "MAINWIN_X" , "0"))
    $MainWin_Y = Int( IniRead( $inifile, "WEBCLIENT", "MAINWIN_Y" , "0"))
    $MainWin_Width = Int( IniRead( $inifile, "WEBCLIENT", "MAINWIN_WIDTH" , "0"))
    $MainWin_Height = Int( IniRead( $inifile, "WEBCLIENT", "MAINWIN_HEIGHT" , "0"))

  $ShowMyIcon = Int( IniRead( $inifile, "PROGRAM", "HIDE_ICON" , "1"))
  AutoItSetOption( "TrayIconHide", $ShowMyIcon)

    ;debug info for ini file parameters
    ;dbg( "Webclient: INI file:  WEBCLIENT_DIR = " & $WebCLientDir)
    ;dbg( "Webclient: INI file:  MAINWIN_CHANGE = " & $WebCLientWinChange)
    ;dbg( "Webclient: INI file: WINCLASS = " & $WebCLientClass)
    ;dbg( "Webclient: INI file: MAINWIN_NAME = " & $WebCLientWin)
    ;dbg( "Webclient: INI file: MAINWIN_STYLE = " & $WebCLientStyle)
    ;dbg( "Webclient: INI file:  FULLSCREEN_CHANGE = " & $FullScreenChange)
    ;dbg( "Webclient: INI file: FULLSCREEN_STYLE = " & $FullScreenStyle)

    ;read and set the hot keys
    $HotKeyMaximize = IniRead( $inifile, "HOTKEYS", "MAXIMIZE_KEY" , "")
    ;dbg( "Webclient: HotKey Maximize = " & $HotKeyMaximize)
  $idx = 0
    If StringLen( $HotKeyMaximize) > 0 Then
      HotKeySet( $HotKeyMaximize, "Maximize")
    EndIf

    $HotKeyExit = IniRead( $inifile, "HOTKEYS", "WCEXIT_KEY" , "")
    ;dbg( "Webclient: HotKey Exit = " & $HotKeyExit)
    If StringLen( $HotKeyExit) > 0 Then
      HotKeySet( $HotKeyExit, "WcExit")
      ;dbg( "Webclient: Hotkey for exit set")
    EndIf

    ;start webclient with parameters
  ;dbg( "Webclient: " & $params & $serverx[$server])
    $GraphPID = Run( $WebCLientDir & "/graph.exe" & " " & $params & $serverx[$server])

    ;only switch server if single server is not set
  if ($single == 0) then

      if ($server == 0) then

        if ( $serverx[1] <> "-h") > 0 then
        $server = 1
      endIf
      else
      $server = 0
      endif
    endif

    ;get the PID for the webclient task
    $webclient = $GraphPID ;ProcessWait( "graph.exe", 20)

    If $webclient == 0 Then

      ;only report with message box if defined in ini file
      $ReportExit = IniRead( $inifile, "WEBCLIENT", "ERROREXIT" , 0)

      If $ReportExit Then
        MsgBox(0, "FactoryLink webclient", "'Graph' did not start. Bye!")

        if $splash <> 0 then
          SplashOff()
        endif
        ;Exit the script
        Exit
      EndIf
    EndIf

    $startup = 0
  EndIf

  ;do have to change the appearance of the main window?
  if ($WebCLientWinChange <> 0) or ($FullScreenChange <> 0) Then

    ;dbg( "Webclient: Upfdating style for main window webclient")

    ;find the handle with the main window name and class
  $GraphhWnd = _GetHwndFromPID( $GraphPID)
  ;dbg( "Webclient: _GetHwndFromPID, window handle = " & $GraphhWnd)
  $GraphState = WinGetState( $GraphhWnd)
  ;dbg( "Webclient: WinGetState, window state = " & $GraphState)

    if ($GraphState >= 7) then

      if ($WebCLientWinChange <> 0) then

        ;dbg( "Webclient: wHnd graph = " & $GraphhWnd)

        ;change the window style accoriding to ini file settings
        SetWindow( $WebCLientStyle, $GraphhWnd)

        ;we have changed the appeareance, do this only once
        $WebCLientWinChange = 0
        $FullScreenChange = 0
      else

        ;change the window style accoriding to ini file settings
        SetWindow( $FullScreenStyle, $GraphhWnd)

        ;we have changed the appeareance, do this only once
        $WebCLientWinChange = 0
        $FullScreenChange = 0
      endif
    endif
  EndIf

  ;webclient uses standard messageboxes to report errors, other programs use the same
  ;class names for the standard messageboxes.
  ;if we find a standard message box, check if it is owned by webclient
  $var = WinList("[CLASS:#32770]")
  ;$array[0][0] = Number of windows returned
  ;$array[1][0] = 1st window title
  ;$array[1][1] = 1st window handle (HWND)
  ;$array[2][0] = 2nd window title
  ;$array[2][1] = 2nd window handle (HWND)
  $keepgoing = 0

  ;loop through all the standard messageboxes
  For $i = 1 to $var[0][0] step 1

  ;check if the messagebox is owned by webclient, if not just ignore
  $PidMsgBox = WinGetProcess($var[$i][1])

    If $webclient == $PidMsgBox Then

      ;dbg( "Webclient: Number of matches = " & $var[0][0] & "; counter = " & $i)
      ;dbg( "Webclient: PID graph.exe: " & $webclient)
      ;dbg( "Webclient: PID message box: " & $PidMsgBox)
      ;dbg( "Webclient: Handle message box: " & $var[$i][1])
    ;dbg( "Webclient: title message box: " & $var[$i][0])

      ;messagebox is owned by webclient, give user 2.5 seconds to read....
      Sleep( 2500)

      ;close the message box
      WinClose($var[$i][1])
      ;dbg( "Webclient: Closed error message box from graph.exe: " & $var[$i][0])
    EndIf
  Next

  ;do not use 100% CPU power, just go to sleep for tenth a second
  Sleep( 100)

  ;we are finished if webclient is shutdown or has ended after error
  $webclient = ProcessExists( $GraphPID)
  if ($webclient == 0) and ($WebCLientAlwaysActive <> 0) then
    $startup = -1
  endif
WEnd
; Finished!

;Leave the script
WcExit()
Exit


;=======================================================================================
; FUNCTION definitions
;=======================================================================================

;=======================================================================================
; FUNCTION dbg($msg)
;
; debug function for use with Sysinternals DebugViewer (dbgview.exe)
;=======================================================================================
Func dbg($msg)
  DllCall("kernel32.dll", "none", "OutputDebugString", "str", $msg)
EndFunc ;==>dbg


;=======================================================================================
; FUNCTION Maximize()
;=======================================================================================
Func Maximize()
  Local Const $SC_MAXIMIZE = 0xF030, $SC_RESTORE = 0xF120
  Local $sState

  $GraphhWnd = _GetHwndFromPID( $GraphPID)
  dbg( "Webclient: _GetHwndFromPID, window handle = " & $GraphhWnd)

  if ($GraphhWnd == 0) Then
    Return
  EndIf

  If BitAND(WinGetState($GraphhWnd), 32) = 0 Then ; Not Maximised
    $sState = $SC_MAXIMIZE
    SetWindow( 0, $GraphhWnd)
  Else
    $sState = $SC_RESTORE
    SetWindow( $WebCLientStyle, $GraphhWnd)
  EndIf

  Return _SendMessage($GraphhWnd, $WM_SYSCOMMAND, $sState)
EndFunc   ;==>Maximize


;=======================================================================================
; FUNCTION WcExit()
;=======================================================================================
Func WcExit()
  ;dbg( "Webclient: Hotkey for exit script")
  if $splash <> 0 then
    SplashOff()
  endif

  if ($webclient > 0) then ProcessClose( $webclient)
  Exit
EndFunc ;==>WcExit

;=======================================================================================
; FUNCTION SetWindow( $WindowStyle, $hWnd)
;=======================================================================================
Func SetWindow( $WindowStyle, $hWnd)

  $GraphhWnd = _GetHwndFromPID( $GraphPID)
  dbg( "Webclient: _GetHwndFromPID, window handle = " & $GraphhWnd)

  $wpLong = _WinAPI_SetWindowLong($GraphhWnd, $GWL_STYLE, $WindowStyle)
  dbg( "Webclient: _WinAPI_SetWindowLong returned = " & $wpLong)
  if ($hWnd > 0) Then

    if ($MainWin_X == 0) and ($MainWin_Y == 0) and ($MainWin_Width == 0) and ($MainWin_Height == 0) then
      _WinAPI_SetWindowPos($hWnd,0,0,0,0,0,$SWP_FRAMECHANGED+$SWP_NOMOVE+$SWP_NOSIZE)
    else
      _WinAPI_SetWindowPos($hWnd,0,$MainWin_X,$MainWin_Y,$MainWin_Width,$MainWin_Height,$SWP_FRAMECHANGED)
    endif

    ;redraw frame and client area
    _WinAPI_RedrawWindow($hWnd)
  EndIf
EndFunc

;==============================================================================
; FUNCTION _GetHwndFromPID($PID)
;
; _GetHwndFromPID : function to find window handle from process id
;==============================================================================
Func _GetHwndFromPID($PID)

  $hWnd = 0
  $stPID = DllStructCreate("int")

  Do
    $winlist2 = WinList()

    For $i = 1 To $winlist2[0][0]

      If $winlist2[$i][0] <> "" Then

        DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", $winlist2[$i][1], "ptr", DllStructGetPtr($stPID))

        If DllStructGetData($stPID, 1) = $PID Then
          $hWnd = $winlist2[$i][1]
          ExitLoop
        EndIf
      EndIf
    Next

    Sleep(10)

  Until $hWnd <> 0

  Return $hWnd
EndFunc ;==>_GetHwndFromPID

;==============================================================================
; MyExitfunction
;==============================================================================
Func MyExitFunction()

  ;Leaving the main program, close our open graph.exe (if any)
  if ($webclient > 0) then ProcessClose( $webclient)

EndFunc


;==============================================================================
; FUNCTION : _WTSQuerySessionInformation($SessionId, $WTSInfoClass = 10,
;                                        $iReturnAsIs = 0)
;
; mod. of https://www.autoitscript.com/forum/topic/
; 134679-get-hostname-of-the-client-connected-to-the-terminalserver-session/
;
; WMI Query function
;==============================================================================
Func _WTSQuerySessionInformation($SessionId, $WTSInfoClass = 10, $iReturnAsIs = 0)
    Local $aResult = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "Ptr", 0, "int", $SessionId, "int", $WTSInfoClass, "ptr*", 0, "dword*", 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "")
    Local $ip = DllStructGetData(DllStructCreate("byte[" & $aResult[5] & "]", $aResult[4]), 1)
    DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $aResult[4])
    If $iReturnAsIs Then Return $ip
    Switch $WTSInfoClass ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ns-wtsapi32-_wts_client_address
        Case 4 ; WTSSessionId
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 14 ; WTSClientAddress
            If Not (Int(StringLeft($ip, 4)) = 2) Then ; IPv4
                $ip = ""
            Else
                $ip = Dec(StringMid($ip, 15, 2)) & '.' & Dec(StringMid($ip, 17, 2)) & '.' & Dec(StringMid($ip, 19, 2)) & '.' & Dec(StringMid($ip, 21, 2))
            EndIf

    EndSwitch
    Return StringReplace(BinaryToString($ip), Chr(0), "")
EndFunc   ;==>_GetWTSClientName