Jump to content

Autoit Powershell issues


 Share

Recommended Posts

#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.

Link to comment
Share on other sites

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 by mwpeck
Link to comment
Share on other sites

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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?
Link to comment
Share on other sites

Try this:

#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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Try this:

#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 by mwpeck
Link to comment
Share on other sites

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:

#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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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 by mwpeck
Link to comment
Share on other sites

You can add the autoit error handler for objects to the script to catch errors:

#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 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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

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.

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...