里程碑 XProtect 自动化

Milestone XProtect Automation

我正在尝试为摄像头监控软件 Milestone XProtect 创建一些自动化代码,我需要一些帮助。我最初使用批处理脚本和 VBScript 来尝试实现我的目标,但它似乎对我不起作用

    #include <MsgBoxConstants.au3>                          ;Import Message Box

Local Const $milestone = "C:\Program Files\Milestone\XProtect Smart Client\Client.exe"  ;Local Variable $milestone set to file path

Local $iFileExists = FileExists($milestone)                     ;Variable that sees if file exists($milestone)

If $iFileExists Then
    Run($milestone)
>   ;[Unknown Variables]                                ;***Figure out the "Window Title", Class, and Instance***
    Send("{TAB}")
    Send("{TAB}")
    Send("[Insert Camera IP Address Here]")                     ;Between [] different for each .exe I'll create
    Send("{ENTER}")
>   ;[Unknown Variables]                    ;***Figure out items in camera window to see when its fully loaded***
Else
    MsgBox($MB_SYSTEMMODAL, "", "Milestone XProtect wasn't found on this computer" & @CRLF)     ;Error Message "File not Found"
EndIf

截至目前,我的代码在计算机上设置了 Milestone 路径的变量,并且 if 语句检查文件是否存在。如果它存在,那么它将 运行 程序。下一行代码应该等到程序完全加载后再发送两个 tab 键,将 ip 地址发送到摄像头服务器,然后输入密钥。 if 语句中的最后一行代码应该在程序结束前检查相机是否已完全加载。

我需要帮助的是代码中标记为 [未知变量] 的两个部分:

  1. 我需要知道程序何时加载到服务器选择屏幕
  2. 在结束程序之前我需要知道摄像头服务器何时完全加载

有人能帮忙吗?

解决方案

为了在保持简单性的同时完成此任务,我已经整理了一些您需要的缺失元素,并添加了注释以帮助描述每一行。

有几种方法可以继续自动化过程,例如提供不同 IP 地址的下拉列表或输入框而不是对地址进行硬编码。随着时间的推移,您只需不断改进脚本,一次添加一个元素。

AutoIt 脚本

#include <MsgBoxConstants.au3>

Local Const $milestone = "C:\Program Files\Milestone\XProtect Smart Client\Client.exe" ;Path to software

Local $iFileExists = FileExists($milestone)                                 ;Check if the file exists, returns a 1 or 0

If $iFileExists Then                                                        ;If FileExists = 1 (exists)
    ;$inputbox = InputBox("Title", "Enter the IP Address of the camera.", "127.0.0.1")  ;Uncomment out if you would like to prompt for input for the IP Address. Used on line 19.
    ;If @error Then Exit                                                    ;@Error can mean Cancel button was pushed, so exit if canceled.
    $iPID = Run($milestone)                                                 ;Runs the software and returns the Process ID
    Sleep(1000)                                                             ;sleep for 1 second
    If @error Then MsgBox(0, "Title", "The program could not launch.")      ;If Run returns a 0 or error, there was a problem
    $handle = _GetHandleFromPID($iPID)                                      ;Retrieve the handle of the program ran, jump to the function below
    If $handle = 0 Then MsgBox(0, "Title", "The handle could not be found.");If the Handle returned is 0, there was no match
    WinWaitActive($handle)                                                  ;Wait for the program to be activated
    Send("{TAB}")                                                           ;send keystrokes to active window
    Send("{TAB}")
    Send("[Insert Camera IP Address Here]")                                 ;Hardcoded IP Address
    ;Send($inputbox)                                                            ;Uncomment out this line and comment out the above line to utilize the input box method instead of hardcoding IP Addresses.
    Send("{ENTER}")
   ;[Unknown Variables]                                                     ;***Figure out items in camera window to see when its fully loaded***
Else
    MsgBox($MB_SYSTEMMODAL, "", "Milestone XProtect wasn't found on this computer" & @CRLF)
EndIf

func _GetHandleFromPID($PID)                                                ;Call function with the PID returned from Run function
    $WinList = WinList()                                                    ;Assign WinList to a variable
    for $i = 1 to $WinList[0][0]                                            ;Run through each Window in WinList, 2D array [titles][handles]
        If WinGetProcess($WinList[$i][1]) = $PID then                       ;Look for a Window with the correct PID
            Return $WinList[$i][1]                                          ;Assign the matching Windows handle to the variable
        EndIf
    Next
    Return 0                                                                ;Return 0 if no matches were found
EndFunc

Window句柄

检索 window 句柄很重要,因为它确保击键被发送到 Milestone 软件的最后一个 运行 实例,如果有几个是 运行.

关于重试的想法

关于第二个问题,有很多方法可以实现检查连接超时重试。然而,它主要取决于通过 AutoIt 可用的交互。一个好的起点是 AutoIt Window 信息工具。您可以将十字准线拖放到 window 的元素以识别控件。下图显示了聚焦 Windows 计算器时的工具。

例子

如果在服务器无法连接时显示弹出窗口 window,您可以拦截它以发出重试信号。如果您需要离开的只是一个空白的视频监视器,则可以选择在屏幕上搜索图像或像素。或者一个良好的服务器连接可能会提供某种类型的警报,AuoIt 可以捕获并在满意时成功关闭,如果不满意,则在 X 秒后重试。

更新

这是带有 GUI 和组合框选项的程序,它使用二维数组。

#include <MsgBoxConstants.au3>
#include <Array.au3>
#include <ComboConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local Const $milestone = "C:\Program Files\Milestone\XProtect Smart Client\Client.exe" ;Path to software

Local $iFileExists = FileExists($milestone)                                     ;Check if the file exists, returns a 1 or 0
Global $list = [["Austin, TX","192.168.0.0"], ["Memphis, TN","192.168.0.1"]]    ;Enter all your selections, this builds a 2D Array [X][0] is the name [X][1] is the IP

If $iFileExists Then                                                            ;If FileExists = 1 (exists) then
    Local $GUI = GUICreate("TITLE", 267, 115)                                   ;Create the GUI
    $button = GUICtrlCreateButton("Start", 96, 56, 65, 25)                      ;Create a button
    $server = GUICtrlCreateCombo("Select Server", 8, 8, 249, 25, $CBS_DROPDOWN) ;Create the combo box
    For $i = 0 To UBound($list) - 1                                             ;Populate combo box with first value (name) from array
        If $list[$i][0] <> "" Then $var = GUICtrlSetData($server, $list[$i][0]) ;Ensure array is not empty
    Next

    GUISetState(@SW_SHOW)

    While 1                                                                     ;Enter loop until user closes or presses button
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE                                               ;Exit when closed
                Exit
            Case $button                                                        ;Store selection into variable, delete the GUI, and run the start function
                $selection = GUICtrlRead($server)
                GUIDelete()
                start()
        EndSwitch
    WEnd
Else                                                                            ;otherwise, message
    MsgBox($MB_SYSTEMMODAL, "", "Milestone XProtect wasn't found on this computer" & @CRLF)
EndIf

Func start()
    $iPID = Run($milestone)                                                     ;Runs the software and returns the Process ID
    Sleep(1000)                                                                 ;sleep for 1 second
    If @error Then MsgBox(0, "Title", "The program could not launch.")          ;If Run returns a 0 or error, there was a problem
    $handle = _GetHandleFromPID($iPID)                                          ;Retrieve the handle of the program ran, jump to the function below
    If $handle = 0 Then MsgBox(0, "Title", "The handle could not be found.")    ;If the Handle returned is 0, there was no match
    WinWaitActive($handle)                                                      ;Wait for the program to be activated
    Send("{TAB}")                                                               ;send keystrokes to active window
    Send("{TAB}")
    For $i = 0 to UBound($list) - 1                                             ;Find the IP address that matches the selection and send it
        If $list[$i][0] = $selection Then Send($list[$i][1])
    Next
    Send("{ENTER}")
    Exit                                                                        ;Exit for now until you can capture a succesful run
   ;[Unknown Variables]                                                         ;***Figure out items in camera window to see when its fully loaded***
EndFunc

func _GetHandleFromPID($PID)                                                    ;Call function with the PID returned from Run function
    $WinList = WinList()                                                        ;Assign WinList to a variable
    for $i = 1 to $WinList[0][0]                                                ;Run through each Window in WinList, 2D array [titles][handles]
        If WinGetProcess($WinList[$i][1]) = $PID then                           ;Look for a Window with the correct PID
            Return $WinList[$i][1]                                              ;Assign the matching Windows handle to the variable
        EndIf
    Next
    Return 0                                                                    ;Return 0 if no matches were found
EndFunc

更新#2

  1. 我添加了一种将新服务器添加到列表并将其存储在本地的方法。
  2. 我制作了一个隐藏的热键,以便在需要更改时打开该文件 创建或删除服务器,您可以按 F1 进入该文件 键盘上的键。我会让你弄清楚如何进一步 自定义这个。
  3. 如果没有选择服务器,则不会发生任何事情,否则 启动程序。
  4. 目前这将启动程序 聚焦并等待它再次聚焦以输入击键(在 如果有人想在点击前等待 1 秒或 100 秒 回到程序中)。
  5. 如果这还不够,或者 window 默认情况下在启动画面后进行控制,然后更改 睡眠定时器从 1000(1 秒)到任何你想要的。
  6. 注意脚本中的第一个区域,它需要一些自定义。设置程序的路径、THIS 程序的标题和一个图标文件。
  7. 要编译它,只需使用 AutoIt 编译器,这将使图标正常工作。

#include <MsgBoxConstants.au3>
#include <Array.au3>
#include <ComboConstants.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBox.au3>

#Region EDIT THE BELOW INFORMATION-------------------------------------------------------------------------------------------------------------------------------------------
Local Const $milestone = "C:\Program Files\Milestone\XProtect Smart Client\Client.exe"  ;Path to software
Local $Title = "Program Title"                                                          ;Give me a name
Local $icon = "Full\Path\To\Icon.ico"
#EndRegion-------------------------------------------------------------------------------------------------------------------------------------------------------------------

#Region Script---------------------------------------------------------------------------------------------------------------------------------------------------------------
Local $iFileExists = FileExists($milestone)                                     ;Check if the file exists, returns a 1 or 0
Global $list = IniReadSection(@TempDir & "\" & $Title & "\config.ini","Server") ;Read the ini file, this builds a 2D Array [X][0] is the key [X][1] is the value
HotKeySet("{F1}", "help")

If $iFileExists Then                                                            ;If FileExists = 1 (exists) then
    If Not FileExists(@TempDir & "\" & $Title) Then                             ;If config directory does not exists then
        Do
        DirCreate(@TempDir & "\" & $Title)                                      ;Create a directory in TempDir for the config.ini file to be stored locally
        Until FileExists(@TempDir & "\" & $Title)
        IniWrite(@TempDir & "\" & $Title & "\config.ini", "Server", "", "")
    EndIf
    Local $GUI = GUICreate($Title, 267, 115)                                    ;Create the GUI
    GUISetIcon($icon, -1)                                                       ;Create icon
    $start = GUICtrlCreateButton("Start", 40, 72, 65, 25)                       ;Create a button
    $create = GUICtrlCreateButton("Add Server", 160, 72, 65, 25)
    $server = GUICtrlCreateCombo("Select Server", 8, 8, 249, 25, $CBS_DROPDOWN) ;Create the combo box
    For $i = 1 To UBound($list) - 1                                             ;Populate combo box with first value (name) from array
        If $list[$i][0] <> "" Then GUICtrlSetData($server, $list[$i][0])        ;Ensure array is not empty and fill combox with KEYS
    Next
    $servername = GUICtrlCreateInput("Server Name", 8, 40, 121, 21)
    GUICtrlSetState(-1, $GUI_HIDE)
    $serverip = GUICtrlCreateInput("IP Address", 136, 40, 121, 21)
    GUICtrlSetState(-1, $GUI_HIDE)

    GUISetState(@SW_SHOW)

    While 1                                                                     ;Enter loop until user closes or presses button
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE                                               ;Exit when closed
                Exit
            Case $start                                                         ;Store selection into variable, delete the GUI, and run the start function
                $selection = GUICtrlRead($server)
                If $selection <> "Select Server" Then
                    GUIDelete()
                    start()
                EndIf
            Case $create
                If GUICtrlRead($create) = "Add Server" Then
                    GUICtrlSetState($servername, $GUI_SHOW)
                    GUICtrlSetState($serverip, $GUI_SHOW)
                    GUICtrlSetData($create, "Create")
                Else
                    If (GUICtrlRead($servername) <> "" And GUICtrlRead($servername) <> "Server Name" And GUICtrlRead($serverip) <> "" And GUICtrlRead($serverip) <> "IP Address") Then
                        IniWrite(@TempDir & "\" & $Title & "\config.ini", "Server", GUICtrlRead($servername), GUICtrlRead($serverip))
                        GUICtrlSetState($servername, $GUI_HIDE)
                        GUICtrlSetState($serverip, $GUI_HIDE)
                        GUICtrlSetData($create, "Add Server")
                    Else
                        MsgBox($MB_ICONINFORMATION, $Title, "Invalid Server Name and IP Address.")
                    EndIf
                    For $i = UBound($list) - 1 To 0 Step -1
                        _GUICtrlComboBox_DeleteString($server, $i)
                    Next
                    Local $list = IniReadSection(@TempDir & "\" & $Title & "\config.ini","Server")
                    For $i = 1 To UBound($list) - 1
                        If $list[$i][0] <> "" Then GUICtrlSetData($server, $list[$i][0])
                    Next
                EndIf
        EndSwitch
    WEnd
Else                                                                            ;otherwise, message
    MsgBox($MB_SYSTEMMODAL, "", "Milestone XProtect wasn't found on this computer" & @CRLF)
EndIf

Func start()
    $iPID = Run($milestone,"", @SW_SHOWNOACTIVATE)                              ;Runs the software and returns the Process ID
    Sleep(1000)                                                                 ;sleep for 1 second
    If @error Then MsgBox(0, $Title, "The program could not launch.")           ;If Run returns a 0 or error, there was a problem
    $handle = _GetHandleFromPID($iPID)                                          ;Retrieve the handle of the program ran, jump to the function below
    If $handle = 0 Then MsgBox(0, $Title, "The handle could not be found.")     ;If the Handle returned is 0, there was no match
    Sleep(1000)
    WinWaitActive($handle)                                                      ;Wait for the program to be activated
    Send("{TAB}")                                                               ;send keystrokes to active window
    Send("{TAB}")
    For $i = 0 to UBound($list) - 1                                             ;Find the IP address that matches the selection and send it
        If $list[$i][0] = $selection Then Send($list[$i][1])
    Next
    Send("{ENTER}")
    Exit                                                                        ;Exit for now until you can capture a succesful run
EndFunc

func _GetHandleFromPID($PID)                                                    ;Call function with the PID returned from Run function
    $WinList = WinList()                                                        ;Assign WinList to a variable
    for $i = 1 to $WinList[0][0]                                                ;Run through each Window in WinList, 2D array [titles][handles]
        If WinGetProcess($WinList[$i][1]) = $PID then                           ;Look for a Window with the correct PID
            Return $WinList[$i][1]                                              ;Assign the matching Windows handle to the variable
        EndIf
    Next
    Return 0                                                                    ;Return 0 if no matches were found
EndFunc

Func help()
    ShellExecute(@TempDir & "\" & $Title & "\config.ini")
EndFunc
#EndRegion--------------------------------------------------------------------------------------------------------------------------------------------------------------------