mwpeck Posted August 25, 2011 Posted August 25, 2011 #include <constants.au3> $cmd = 'gwmi win32_process -credential lap -Filter "Name = ''explorer.exe''" -cn 192.168.0.16 | %{$_.GetOwner()} |select user' $1 = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ' & _ '-command . ''' & @ScriptDir & "\" & 'test.ps1''' $powerShell = Run($1, '', @SW_SHOW, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD) $output = "" While 1 $output &= StdoutRead($powerShell) If @error Then ExitLoop WEnd MsgBox(0, "", $output) In short, the above script will "work fine", in that the message box will show the expected output from powershell (test.ps1 contains the following command: gwmi win32_process -credential lap -Filter "Name = 'explorer.exe'" -cn 192.168.0.16 | %{$_.GetOwner()} |select user ), however, if I change the -command part to: ( '-command . ''' & $cmd & '''' ), without the parenthesis obviously, it does not work correctly......yet the commands should be identical (and if I actually use a messagebox to view the contents of $cmd, they are identical to what I have in test.ps1). I am obviously doing something wrong, but after playing with quote positioning and numbers for the past half hour I can't figure out why it won't work right.
mwpeck Posted August 26, 2011 Author Posted August 26, 2011 (edited) Anyone have any ideas? Makes no sense that I can read the file into (different code than shown) autoit and display both it and the code in the $cmd variable, and get identical text, yet one works and the other doesn't. Edited August 26, 2011 by mwpeck
mwpeck Posted August 27, 2011 Author Posted August 27, 2011 Bump, Nobody? I just can't figure this out, I've even tried reading the .ps1 file into $cmd and it still doesn't work when passing $cmd to the -command part of the text.
trancexx Posted August 27, 2011 Posted August 27, 2011 Bump, Nobody?It's very hard to understand what you are asking. You are likely ignored because of the way your question is written.Rephrase. ♡♡♡ . eMyvnE
UEZ Posted August 27, 2011 Posted August 27, 2011 E.g. when I start the PowerShell command gwmi win32_process -Filter "Name='explorer.exe'" from CMD whereas the command is saved to Test1.ps1 it gives information back. But when I start in CMD directly: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "gwmi win32_process -Filter "Name='explorer.exe'"" it is not working. I tested several quotes but it is not working, too. C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "gwmi win32_process" give a lot of information back. Thus problem is probably the parameters for powershell.exe in CMD directly. Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
mwpeck Posted August 27, 2011 Author Posted August 27, 2011 It's very hard to understand what you are asking. You are likely ignored because of the way your question is written. Rephrase. Okay then, basically I need to check if a user is logged in to a system (I don't really care about who the user is, just whether or not somebody is logged in): #include <constants.au3> $1 = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ' & _ '-command . ''' & @ScriptDir & "\" & 'test.ps1''' $powerShell = Run($1, '', @SW_SHOW, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD) $output = "" While 1 $output &= StdoutRead($powerShell) If @error Then ExitLoop WEnd MsgBox(0, "", $output) test.ps1 contains only: gwmi win32_process -credential lap -Filter "Name = 'explorer.exe'" -cn 192.168.0.16 | %{$_.GetOwner()} |select user With the above code and a user called "lap" logged into 192.168.0.16, MsgBox contains: User ---- lap That works fine, how I would expect it.....but the following doesn't return anything: #include <constants.au3> $cmd = 'gwmi win32_process -credential lap -Filter "Name = ''explorer.exe''" -cn 192.168.0.16 | %{$_.GetOwner()} |select user' $1 = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ' & _ '-command . ''' & $cmd & '''' $powerShell = Run($1, '', @SW_SHOW, $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD) $output = "" While 1 $output &= StdoutRead($powerShell) If @error Then ExitLoop WEnd MsgBox(0, "", $output) This simply doesn't return anything, but I would expect it to return the same as above. Basically, I want to embed the command in test.ps1, into a variable in AutoIt so I can dynamically change the command before I run it and without having to create a temporary .ps1 (if possible). So is there a way to embed the above command (the command after test.ps1 above) into autoit? Or is there some other way I can more easily check if a user is logged into a system? E.g. when I start the PowerShell command gwmi win32_process -Filter "Name='explorer.exe'" from CMD whereas the command is saved to Test1.ps1 it gives information back. But when I start in CMD directly: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "gwmi win32_process -Filter "Name='explorer.exe'"" it is not working. I tested several quotes but it is not working, too. C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "gwmi win32_process" give a lot of information back. Thus problem is probably the parameters for powershell.exe in CMD directly. Br, UEZ It is probably due to the quotes in the first line due to passing the command to powershell with the quotes (in the command line), as soon as the quotes wrapping the Name='explorer.exe' are read, the command line is stopping and erroring out.....is there any other way I could check a remote host to find if a user is logged in?
UEZ Posted August 27, 2011 Posted August 27, 2011 (edited) Try this: expandcollapse popup#include <Array.au3> Global $oErrorHandler = ObjEvent("AutoIt.Error", "ObjErrorHandler") $host = "localhost" $aList = WMI_GetLoggedInUser($host) _ArrayDisplay($aList, "Logged in Users on " & $host) $aList = WMI_GetLoggedInUser2($host) _ArrayDisplay($aList, "Logged in Users on " & $host) Func WMI_GetLoggedInUser($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $ping = Ping($host, 1000) If @error Then SetError(1, 0, -1) Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") If @error Then Return SetError(2, 0, 0) Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") If @error Then Return SetError(3, 0, 0) ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = StringRegExpReplace($objItem.Antecedent, '(?i).*name="(.*)"', "$1") $aResult[$i][1] = StringRegExpReplace($objItem.Antecedent, '(?i).*\.domain="(.*)",.*', "$1") $aResult[$i][2] = StringRegExpReplace($objItem.Dependent, '(?i).*LogonId="(.*)"', "$1") $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(4, 0, 0) EndFunc Func WMI_GetLoggedInUser2($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $ping = Ping($host, 1000) If @error Then SetError(1, 0, -1) Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") If @error Then Return SetError(2, 0, 0) Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") If @error Then Return SetError(3, 0, 0) ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT UserName, Domain, PrimaryOwnerName FROM Win32_ComputerSystem", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = $objItem.UserName $aResult[$i][1] = $objItem.Domain $aResult[$i][2] = $objItem.PrimaryOwnerName $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(4, 0, 0) EndFunc Func ObjErrorHandler() ConsoleWrite( "A COM Error has occured!" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oErrorHandler.description & @CRLF & _ "err.windescription:" & @TAB & $oErrorHandler & @CRLF & _ "err.number is: " & @TAB & Hex($oErrorHandler.number, 8) & @CRLF & _ "err.lastdllerror is: " & @TAB & $oErrorHandler.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oErrorHandler.scriptline & @CRLF & _ "err.source is: " & @TAB & $oErrorHandler.source & @CRLF & _ "err.helpfile is: " & @TAB & $oErrorHandler.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oErrorHandler.helpcontext & @CRLF _ ) EndFunc The result is an array with the users logged in on the system. Br, UEZ Edited September 8, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
mwpeck Posted August 27, 2011 Author Posted August 27, 2011 (edited) Try this: expandcollapse popup#include <Array.au3> $host = "localhost" $aList = WMI_GetLoggedInUser($host) _ArrayDisplay($aList, "Logged in Users on " & $host) $aList = WMI_GetLoggedInUser2($host) _ArrayDisplay($aList, "Logged in Users on " & $host) Func WMI_GetLoggedInUser($host) ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = StringRegExpReplace($objItem.Antecedent, '(?i).*name="(.*)"', "$1") $aResult[$i][1] = StringRegExpReplace($objItem.Antecedent, '(?i).*\.domain="(.*)",.*', "$1") $aResult[$i][2] = StringRegExpReplace($objItem.Dependent, '(?i).*LogonId="(.*)"', "$1") $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc Func WMI_GetLoggedInUser2($host) ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT UserName, Domain, PrimaryOwnerName FROM Win32_ComputerSystem", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = $objItem.UserName $aResult[$i][1] = $objItem.Domain $aResult[$i][2] = $objItem.PrimaryOwnerName $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc The result is an array with the users logged in on the system. Br, UEZ Any way to get that to tap remote hosts? If I replace "localhost" with "192.168.0.16" or "Lap-PC" it says: \GUITest.au3 (13) : ==> Variable must be of type "Object".: Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", 0x30) Local $colItems = $objWMIService^ ERROR EDIT: Also, while I do have the admin account name and pass for the remote host (assuming thats required), but they are NOT the same account or pass as my localhost. Edited August 27, 2011 by mwpeck
UEZ Posted August 27, 2011 Posted August 27, 2011 (edited) With this method WMI tries to login to remote system with the current credentials you are logged in on your pc. Either your are using same account which should have admin rights on remote system or try this and pass user id and password for the account on remote system which has admin rights: expandcollapse popup#include <Array.au3> $host = "localhost" $aList = WMI_GetLoggedInUser($host) _ArrayDisplay($aList, "Logged in Users on " & $host) $aList = WMI_GetLoggedInUser2($host) _ArrayDisplay($aList, "Logged in Users on " & $host) Func WMI_GetLoggedInUser($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = StringRegExpReplace($objItem.Antecedent, '(?i).*name="(.*)"', "$1") $aResult[$i][1] = StringRegExpReplace($objItem.Antecedent, '(?i).*\.domain="(.*)",.*', "$1") $aResult[$i][2] = StringRegExpReplace($objItem.Dependent, '(?i).*LogonId="(.*)"', "$1") $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc Func WMI_GetLoggedInUser2($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT UserName, Domain, PrimaryOwnerName FROM Win32_ComputerSystem", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = $objItem.UserName $aResult[$i][1] = $objItem.Domain $aResult[$i][2] = $objItem.PrimaryOwnerName $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc Br, UEZ Edited August 27, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
mwpeck Posted August 27, 2011 Author Posted August 27, 2011 (edited) Thanks, got it working. Sorry for the confusion early on....I was just frustrated after working on trying to get my original script to work after a few hours and understood what I was trying to do better than I was able to explain it at the time. That being said, this will work on pretty much anything XP or newer, right? EDIT: One more quick thing, what can I do to verify that $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") connected to an actual host? With the powershell script I could do a timeout function so after a few seconds of no output from powershell, it assumed there was no connection and continued on with my script, WMI seems 10x faster and if there is no connection made in the above line (the .connectserver), the script errors and autoit returns: \GUITest.au3 (35) : ==> The requested action with this object has failed.: Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80")^ ERROR I am not that advanced in error handling, and know next to nothing about WMI, so how would I catch that and set a variable so my script can act appropriately? Edited August 27, 2011 by mwpeck
UEZ Posted August 27, 2011 Posted August 27, 2011 (edited) You can add the autoit error handler for objects to the script to catch errors: expandcollapse popup#include <Array.au3> Global $oErrorHandler = ObjEvent("AutoIt.Error", "ObjErrorHandler") $host = "localhost" $aList = WMI_GetLoggedInUser($host) _ArrayDisplay($aList, "Logged in Users on " & $host) $aList = WMI_GetLoggedInUser2($host) _ArrayDisplay($aList, "Logged in Users on " & $host) Func WMI_GetLoggedInUser($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = StringRegExpReplace($objItem.Antecedent, '(?i).*name="(.*)"', "$1") $aResult[$i][1] = StringRegExpReplace($objItem.Antecedent, '(?i).*\.domain="(.*)",.*', "$1") $aResult[$i][2] = StringRegExpReplace($objItem.Dependent, '(?i).*LogonId="(.*)"', "$1") $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc Func WMI_GetLoggedInUser2($host, $usr = "", $pass = "") ;coded by UEZ 2011 Local $aResult[1000][3], $i = 1 Local $objWMILocator = ObjCreate("WbemScripting.SWbemLocator") Local $objWMIService = $objWMILocator.ConnectServer($host, "\root\cimv2", $usr, $pass, "", "", "&H80") ;~ Local $objWMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & $host & "\root\cimv2") Local $colItems = $objWMIService.ExecQuery("SELECT UserName, Domain, PrimaryOwnerName FROM Win32_ComputerSystem", "WQL", 0x30) If IsObj($colItems) Then For $objItem In $colItems $aResult[$i][0] = $objItem.UserName $aResult[$i][1] = $objItem.Domain $aResult[$i][2] = $objItem.PrimaryOwnerName $i +=1 If $i = UBound($aResult) Then ExitLoop Next ReDim $aResult[$i][3] $aResult[0][0] = $i - 1 Return $aResult EndIf Return SetError(1, 0, 0) EndFunc Func ObjErrorHandler() ConsoleWrite( "A COM Error has occured!" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oErrorHandler.description & @CRLF & _ "err.windescription:" & @TAB & $oErrorHandler & @CRLF & _ "err.number is: " & @TAB & Hex($oErrorHandler.number, 8) & @CRLF & _ "err.lastdllerror is: " & @TAB & $oErrorHandler.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oErrorHandler.scriptline & @CRLF & _ "err.source is: " & @TAB & $oErrorHandler.source & @CRLF & _ "err.helpfile is: " & @TAB & $oErrorHandler.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oErrorHandler.helpcontext & @CRLF _ ) EndFunc It should work also for WinXP but it didn't test it. Br, UEZ Edited August 27, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
mwpeck Posted August 27, 2011 Author Posted August 27, 2011 Thanks a ton UEZ.....had the error handler set a global error variable based on the error description, then at various points in the WMI_GetLoggedInUser I have it check the error variable and if it does error it skips the rest of the code for that block, that way I can have my GUI continue running and working after an error, and just skip what I would have done if it hadn't errored. You were a major help UEZ, your script not only worked how I wanted my original script to work but it also got me around having to use powershell (which couldn't accept credential details other than account name in the actual command, so it presented a popup for the password that my script had to then type the password in for) which is much cleaner and more efficient.
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