Jump to content
Sign in to follow this  

AutoIT meeting Powershell

Recommended Posts


AutoIT meeting Powershell

Wether you like it or not, but we can't ignore Powershell these days. Since Powershell is built on top of .NET this enables a lot of potential for all scripters around.

Jon made his first steps releasing 2 .NET Assemblies in prior Beta versions. Which is a very good step toward the .NET integration.

In fact there are 2 Assemblies available in the Beta release, a .NET Assembly and a Powershell Assembly.

As it seems the .Net Assembly is derived from the COM AutoItX3.dll.

While the PS Assembly derived from the .NET Assembly, which speaks for itself.

But of course the Method and Properties exposed are limited to the ones in the AutoITX3 COM Object.

Therefore we add this handshake in the meantime awaiting that Jon adds full .NET support in AU3 or AU4, just like other Scripting languages have done ?

The approach is simple.

We use the AU3 commandline interface to run AU3 commands or Script Files. And Powershell picks it up to process them as PS Objects.

This PS function reads out the -> PS Code below.

function Au3_cmd ($sEnv = "env:programfiles(x86)", $sArch = "\AutoIt3\AutoIt3_x64.exe ", $sType = " /AutoIt3ExecuteLine ", $sCmd = "" ) 
$sPath = get-content $sEnv
$sPath = $sPath + $sArch
$oObj = New-Object -ComObject Scripting.FileSystemObject
$sf = $oObj.GetFile($sPath)
Return $sPath, $sf.ShortPath, $sType, $sCmd
$sCmd1 = Au3_cmd -sCmd "InputBox('Question', 'Where were you born?', 'Planet Earth 1', '', -1, -1, 0, 0)" 
$sCmd1 = Au3_cmd -sCmd "InputBox('Question', 'Where were you born?', 'Planet Earth 1', '', -1, -1, 0, 0)" 
$sCmd2 = Au3_cmd -sCmd "MsgBox(0,'Au3 ->PS Test','Hello World 2')"
$sCmd3 = Au3_cmd -sCmd "ConsoleWrite(@CRLF & 'Hello World 3' & @CRLF)"
$sCmd4 = Au3_cmd -sCmd "ConsoleWrite(@CRLF & 'Hello World 4' & ' - ' & @IPAddress1 & @CRLF)"
invoke-expression ($sCmd1[1] + $sCmd1[2] + [CHAR]34 + $sCmd1[3] + [CHAR]34) | % { "processing Au3 Output 4 : $_ " } 
invoke-expression ($sCmd2[1] + $sCmd2[2] + [CHAR]34 + $sCmd2[3] + [CHAR]34) 
$Ret3 = ($sCmd3[1] + $sCmd3[2] + [CHAR]34 + $sCmd3[3] + [CHAR]34) 
invoke-expression "$Ret3 | Write-Host" 
$Ret4 = ($sCmd4[1] + $sCmd4[2] + [CHAR]34 + $sCmd4[3] + [CHAR]34) 
invoke-expression "$Ret4 | tee-object -variable return" | % { "processing Au3 Output 4 : $_ " }
echo "Number of Objects $($Return.Count)" 
# -----------------------------------------------
$sCmd5 = Au3_cmd -sType " /AutoIt3ExecuteScript " -sCmd "C:\temp\test.au3"
$Ret5 = ($sCmd5[1] + $sCmd5[2] + [CHAR]34 + $sCmd5[3] + $sCmd5[4] + [CHAR]34)
Echo ' --- ' # All object as output
invoke-expression "$Ret5 | Write-Host" 
Echo ' --- ' # All objects passed on to PS for further treatment.
invoke-expression "$Ret5 | tee-object -variable script" | % { "processing Au3 Output 5 : $_ " } | Where-object {$_ -notlike '*Idle*'}
rv sCmd1
rv sCmd2
rv sCmd3
rv sCmd4
rv sCmd5
rv ret3
rv ret4
rv ret5
rv script


Just some WinAPI Test script

ConsoleWrite(test() & @CRLF)
Func test()
 $sRet = StringLeft("I am a string", 3)
 Return $sRet
; ------------------------------------------
ConsoleWrite("Idle since " &_IdleTicks() & " MSecs"& @CRLF)
Func _IdleTicks()
    Local $aTSB, $ticksSinceBoot, $struct, $ticksSinceIdle
    $aTSB = DllCall ("kernel32.dll", "long", "GetTickCount")
    $ticksSinceBoot = $aTSB[0]
    $struct = DllStructCreate("uint;dword");
    DllStructSetData($struct, 1, DllStructGetSize($struct));
    DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($struct))
    $ticksSinceIdle = DllStructGetData($struct, 2)
    return $ticksSinceBoot - $ticksSinceIdle
; ------------------------------------------
Dim $idays
Dim $ihours
Dim $imins
Dim $isecs
MsgBox(0,"Uptime","Days: " & $idays & " - Hours: " & $ihours & " - mins: " & $imins & " - secs: " & $isecs)
ConsoleWrite("Days: " & $idays & " - Hours: " & $ihours & " - mins: " & $imins & " - secs: " & $isecs & @CRLF)
Func _uptime(ByRef $iDays, ByRef $iHours, ByRef $iMins, ByRef $iSecs)
    $iTicks = DllCall("kernel32.dll", "long", "GetTickCount")
    $iTicks = $iTicks[0]
    If Number($iTicks) > 0 Then
        $iTicks = Round($iTicks / 1000)
        $iDays  = Int($iTicks / 86400)
        $iHours = Int($iTicks / 3600)
        $iTicks = Mod($iTicks, 3600)
        $iMins = Int($iTicks / 60)
        $iSecs = Round(Mod($iTicks, 60))
        Return 1
    ElseIf Number($iTicks) = 0 Then
        $iDays = 0
        $iHours = 0
        $iTicks = 0
        $iMins = 0
        $iSecs = 0
        Return 1
        Return 0
EndFunc   ;==>_uptime


Since both languages have the strenght and weaknesses. AU3 is realy good in WinAPI's / WinGUI's, whick PS is good in accessing .NET Assemblies.

Seems to be a good mariage. :)

Enjoy !


  • Like 1

Share this post

Link to post
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
Sign in to follow this  

  • Similar Content

    • hemichallenger
      By hemichallenger
      Not sure if this is possible or if someone has already tackled this. Is it possible to embed PowerShell into a GUI? Autoit is great for quick function but sometime I need to run a command thru PowerShell. It be great to have PowerShell console embedded into the gui.
    • BigDaddyO
      By BigDaddyO
      After much searching I finally found a method to get eMails from an Exchange eMail account inbox.  I was hoping for AutoIT or vbscript but I couldn't find any that would read the inbox messages without using Outlook.
      I needed this because I'm testing a web-form that generates an eMail sent to a shared mailbox "not what my current outlook is configured for".  so, I needed to connect to a different account, then get the inbox messages, and see if the auto-generated eMail message body contains what I submitted in the form.
      I found a PowerShell script that was close and modified it to do just what I want, but I'd still like it to run in AutoIT but I'm not sure how to use the Microsoft.Exchange.WebServices.dll
      Anybody have some ideas? 
      #To Launch! # C:\Windows\System32> powershell -ExecutionPolicy ByPass #This launches PowerShell and allows execution of .ps1 files # PS C:\Windows\System32> . "C:\Temp\eMail\getInbox.ps1" #The period . in front of the .ps1 file forces PS to display results on-screen # Where is the EWS .DLL file that you are using # Get the installer from https://www.microsoft.com/en-us/download/details.aspx?id=42022 # We only need 2 dll's from the install and they can be stored anywhere: "Microsoft.Exchange.WebServices.Auth.dll" & "Microsoft.Exchange.WebServices.dll" $EWSdll = "C:\Temp\eMail\Microsoft.Exchange.WebServices.dll" # Where do you want the output text file to be saved $Output = "C:\Temp\eMails.txt" # replace with your email address $email = "MyemailAddress@work.net" # only need to populate these if you're impersonating... $username = "myemail" $password = "Sup3rS3cre+" $domain = "ad.work.net" # load the assembly : point to the dll in the location you have the .dll file [void] [Reflection.Assembly]::LoadFile($EWSdll) # set ref to exchange, first references 2007, 2nd is 2010 (default) #$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1) $s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService # use first option if you want to impersonate, otherwise, grab your own credentials with the 3rd one. not sure what the 2nd one is for $s.Credentials = New-Object Net.NetworkCredential($username, $password, $domain) ##$s.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials #$s.UseDefaultCredentials = $true # discover the url from your email address $s.AutodiscoverUrl($email) # get a handle to the inbox $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox) #create a property set (to let us access the body & other details not available from the FindItems call) $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text; # If you have a set number of items you want to get, use this and insert the # in the () # $items = $inbox.FindItems(5) # If you want to retrieve all items (Server limit is usually at 1000) then use this line # Details on the max returned by server: https://blogs.msdn.microsoft.com/exchangedev/2010/03/12/throttling-policies-and-the-ewsfindcountlimit/ $items = $inbox.FindItems($inbox.TotalCount) # Put some counts at the top of the output Write-host "Total Inbox count: $($inbox.TotalCount)" Write-host "Unread count: $($inbox.UnreadCount)" #These two lines, write the output to the specified text file Add-Content $Output "Total Inbox count: $($inbox.TotalCount)" Add-Content $Output "Unread count: $($inbox.UnreadCount)" foreach ($item in $items.Items) { # load the property set to allow us to get to the body $item.load($psPropertySet) # Get the Body text as-is $bod = $item.Body.Text #if you only want a short summary of the Body, then comment the above line and un-comment these 4 lines # $bod = $item.Body.Text -replace '\s+', ' ' # $bodCutOff = (100,$bod.Length | Measure-Object -Minimum).Minimum # $bod = $bod.Substring(0,$bodCutOff) # $bod = "$bod..." # output the results - first of all the From, Subject, References and Message ID write-host "====================================================================" Write-host "From: $($item.From.Name)" Write-host "Subject: $($item.Subject)" Write-host "Body: $($bod)" write-host "====================================================================" "" # Output the results to the specified Text file Add-Content $Output "" Add-Content $Output "====================================================================" Add-Content $Output "From: $($item.From.Name)" Add-Content $Output "Subject: $($item.Subject)" Add-Content $Output "Body:",$($bod) Add-Content $Output "====================================================================" Add-Content $Output "" } #see these URLs for more info # EWS Stuff # folder members: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.folder_members%28v=exchg.80%29.aspx # exporting headers: https://www.allabout365.com/2010/10/export-email-headers-exchange-powershell/ # read emails with EWS: https://social.technet.microsoft.com/Forums/en-US/3fbf8348-2945-43aa-a0bc-f3b1d34da27c/read-emails-with-ews?forum=exchangesvrdevelopment  
    • Jibberish
      By Jibberish
      Hi all,
      I need to read a log file into an array, but the log file is encoded as $FO_UTF16_BE_NOBOM (2048) = Use Unicode UTF16 Big Endian (without BOM) per FileGetEncoding (it returns 2048).
      I have searched how to convert these log files to UTF-8 and finally found a Powershell command. Since then I have been racking my brain trying to get the function to work. The command itself works from a Powerscript prompt:
      C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command Get-Content C:\Logs\Myplayer_10-10-17-02-31.log | Set-Content -Encoding utf8 C:\Logs\Myplayer1.log This is my sandbox;
      #include <array.au3> #include <File.au3> Local $aArrayLogFile Local $sLogDir = "C:\Logs\" Local $sLogFile = "Myplayer_10-10-17-02-31.log" Local $sConvertedLog = "ConvertedLog.log" Local $sLogDirFile = $sLogDir&$sLogFile RunWait("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command Get-Content "&$sLogDirFile&" | Set-Content -Encoding utf8 "&$sConvertedLog,$sLogDir) _FileReadToArray($sLogDirFile, $aArrayLogFile) _ArrayDisplay($aArrayLogFile) Also tried
      RunWait("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command Get-Content "&$sLogDirFile&" | Set-Content -Encoding utf8 "&$sConvertedLog,$sLogDir) and
      ShellExecuteWait("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"," -Command Get-Content "&$sLogDirFile&" | Set-Content -Encoding utf8 "&$sConvertedLog,$sLogDir) Tried without -Command and a bunch of other parameters that were sprinkled throughout the internet from people trying to get this to work.
    • ur
      By ur
      I am maintaining all the reusable code in a separate file as library.au3.
      In that file I have referenced some dependent files using fileinstall, so that they will be extracted when necessary.
      Problem is, if I use a function in the library.au3 in another script which doesn't require this dependent file, as I am including the whole file using include tag, it is embedding that file also.
      Is there any way to exclude that.
    • david1337
      By david1337
      Hi guys,
      I need a little help here
      I have this simple Powershell script, that is able to set "sig.htm" as signature in OWA for the mail account specified.
      First part of the script just loads the Exchange snapin, since this is needed for the Get-Mailbox command.
      #Add Exchange 2010/2013 snapin if not already loaded in the PowerShell session if (!(Get-PSSnapin | where {$_.Name -eq "Microsoft.Exchange.Management.PowerShell.E2010"})) { try { Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction STOP } catch { #Snapin was not loaded Write-Warning $_.Exception.Message EXIT } . $env:ExchangeInstallPath\bin\RemoteExchange.ps1 Connect-ExchangeServer -auto -AllowClobber } $mailboxes = Get-Mailbox -Identity user@domain.com $mailboxes| foreach {$file= "sig.htm"; Set-MailboxMessageConfiguration -identity $_.alias -SignatureHtml "$(Get-Content -Path $file -ReadCount 0)"} What I want is for AutoIt to use Powershell.exe to run the script somehow. This way I would be able to use AutoIt variables and arrays together with the PS script.
       I guess the solution would be to run Powershell.exe with command line arguments?
      If that is not possible, maybe have the script stored as a "ps1" file, and interact with it that way? (not preferred)