Jump to content

Help needed in getting details of a gui in remote machine


Go to solution Solved by jdelaney,

Recommended Posts

I am writing a script to check whether an analysis software is using a particular port (3rd party device port) and release that port in remote computer. The plan is something like below:
1. Check whether the software is running in remote machine. Multiple instances of process can run with different pid.
For all pids returned in step1:
2. Open the software's gui using pid.
3. There is a dropdown in the gui which tell you the port which it is using. The classname of the control is [Class:Button; Instance 23]. Check whether the port name matches to one the local script is searching. If yes, kill the particular process. If not matching, leave the port open. 
4. Repeat steps 2-3 with all pids until a match is found for port or no match is found at all.
 
I have written a method to check pids remotely. The code is below. I am not sure how to proceed. All the methods I am writing is complicating things. Is there any way it can be achieved easily?
 
#Include "Array.au3"
Func fCheckProcess_Remote($processtocheck, $RemoteComputer, $RemoteUsername, $RemotePassword)
dim $process [1]
$colItems = ""
$Output=""
$objSWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
$objWMIService = $objSWbemLocator.ConnectServer($RemoteComputer, "rootCIMV2",$RemoteUsername,$RemotePassword)
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 0x10 + 0x20)
If IsObj($colItems) then
For $objItem In $colItems
$Output &= $objItem.Name
_ArrayAdd($process, $Output)
$Output=""
Next
Else
SetError(1)
Return "No WMI Objects Found for class: " & "Win32_Process"
Endif
;_ArrayDisplay($process)
$result = _ArrayFindAll($process, $processtocheck)
;_ArrayDisplay($result )
Return $result
EndFunc
 
Please help.
Edited by hellovivz
Link to comment
Share on other sites

hello hellovivz, welcome to AutoIt and to the forum!

if possible, query the application directly. it may have the info written in the registry, ini file, etc.

otherwise, the "remote" part is going to give you hell - assuming it's even possible. don't go there. instead, write your script to do it interactively, then launch your script on the remote machines.

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Thanks for the reply. I have written a method to get window handle of the application from pid and kill it as in my requirement. But now I am able to execute it from the machine itself as an exe from command line. But when I execute if remotely, it gives an error than window handle of pid is not found. Is it because it is remote and the windows are not visible remotely ??

Here are the methods which I am using. 

Func fGetWindowHandle_byPID($iPID)
Local $aError[1] = [0], $aWinList, $sReturn
$aWinList = WinList()
;_ArrayDisplay($aWinList)
For $window = 1 To $aWinList[0][0]
;If WinGetProcess($aWinList[$window][1]) = $iPID And BitAND(WinGetState($aWinList[$window][1]), 2)  Then
If WinGetProcess($aWinList[$window][1]) = $iPID  and StringInStr($aWinList[$window][0],'appname - ') <> 0 Then
$hWnd= $aWinList[$window][1]
Return $hWnd
EndIf
Next
SetError(1)
Return "fGetHandle_byPID() No window handle"
EndFunc

Here  the fGetHandle_byPID() No window handle error is thrown even though the pid exist in the machine.

And I am using the below code to execute the exe:

mycommand = <filename.exe> <params>
$objSWbemLocator = ObjCreate("WbemScripting.SWbemLocator")
$objWMIService = $objSWbemLocator.ConnectServer($Streamer_ip,"root\CIMV2",$Streamer_username,$Streamer_password)
$objProcess = $objWMIService.Get("Win32_Process")
$objInParam = $objProcess.Methods_("Create").inParameters.SpawnInstance_()
$objInParam.Properties_.Item("CommandLine") =  $mycommand
$objInParam.Properties_.Item("ProcessId") =  ""
$objOutParams = $objWMIService.ExecMethod("Win32_Process", "Create", $objInParam)
$ReturnValue = $objOutParams.ReturnValue
If $ReturnValue > 0 Then
    SetError(1)
    Return "ERROR: Failed to Check app"
EndIf

Is it because of the way I am calling the autoit exe remotely. Should I execute it differently such that it can get hold of the desktop remotely so that it can get window handle ?

Link to comment
Share on other sites

  • Solution

I'd suggest [PA|PS]execute, to actually run the script locally on the remote station (if you can't find any output file|registry, like mentioned above).  Then, you would interact directly with the gui.

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.
Link to comment
Share on other sites

i advise you do not run it remotely by PsExec (or PaExec) as suggested. yes, it supports interactive mode, but to my experience it is not reliable at handle existing GUI elements.

add a loop to your script that allows it to run in the background, and only do its thing when the condition is met.

then compile your script to exe, deploy it to the target machines, and have it run at startup.

(i'd use registry entry at HKLM'SOFTWAREMicrosoftWindowsCurrentVersionRun so your script runs for all users at logon.)

possibly make your script write its actions to a log file in a central share.

then just forget about the whole thing.

EDIT: since you actually run the script locally, you can utilize some built-in functions:

ProcessList()
_WinAPI_EnumProcessWindows() 
Edited by orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

pray tell, which part of the phrase "do not run it remotely" was not clear enough?  ;)

no scheduler, no service, no remote calls, no PsExec, no nothing. if you can run it locally on your machine, then run it locally on the other machines. how to launch it? i made one suggestion already.

of course it is only a suggestion. but this wall has met my forehead several times in the past, and running locally always proved the best solution.

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

The thing is that the local machine needs to run another application which uses the same port already used by remote machine. So only when the local machine needs the port, it should kill the instance in remote machine and once done it should log back in and restart the application again. So I cannot run the script locally all the time or during startup. The run will be on a need basis and that 'need' is define by local machine, not the remote machine, Sadly. 

Link to comment
Share on other sites

many times, an on-demand action requires an idle agent at standby. use TCPSend() and TCPRecv() to trigger the agents and receive feedback. the help file has a perfect example on this:

TCPSend()
TCPRecv()

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Psexecute solved the issue. When the first time i was trying with session id 1 and it was not working. I found out that it was using a different session id, now I get actual session id by using the below command:

PSExec & ' \\' & $ip & ' -u ' & username & ' -p ' & $password & ' query session'

Using the session id I use PSExec command to run the exe I wanted in the remote machine with -i option for interactive desktop:

PSExec & ' \\' & $ip & ' -u ' & $username & ' -p ' & $password & ' -i ' & $sessionid & ' -w ' & $remote_location & " cmd.exe /c " & $myexec

With these commands I was able to get Window handle, but I had to change the Winwaitactive to Winwait since Winwaitactive was not able to activate the handle of window in remote machine.

$hWnd=fGetWindowHandle_byPID($pid)
If @error Then
    Exit ;Exit with log
Endif
WinSetState($hWnd, "", @SW_SHOW)
$hWnd = WinWait($hWnd, "", 60) ;Winwaitactive didn't work for remote machine
If ($hWnd == 0) Then
    ;Log("Unable to get window")
    ;Return with error code or Exit
EndIf
$ret = ControlCommand($hWnd,"","[CLASS:ComboBox; INSTANCE:1]", "GetCurrentSelection","")
;Rest of code

Now it works with above changes.

Thank you all for the replies and suggestions !!

Edited by hellovivz
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...