Sign in to follow this  
Followers 0
simy8891

Translate PowerShell script to AutoIT

12 posts in this topic

Hi guys,

I know what I'm asking it's a bit of a pain, but is anybody out there able to translate the following PS script to AutoIT?

I don't really understand a few parts of it and I'm not quite sure is even possible to keep (more or less) the same syntax.

This script gets all AD's in the domain and then gets the last logon details from each one of them for each single Computer Object in order to get a real last logon date.

This cannot  be done with either Get-ADComputers in powershell or with the AD UDF function for a simple reason: It takes about 100 hours against the 20 minutes of the below (About 6100 machines).

If anybody's interested, the below already works, and you can just replace the Write-Host with an export to csv (which I'm not able to do at the moment due my limited PS knowledge).

The reason I'm asking this is because I've got a huge AutoIT script behind the scene already working with the data this script should get:

#Get DirectorySearchers for each DC
$dcSearchers = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers | ? { Test-Connection $_.IPAddress -Count 1 -Quiet } | % { $_.GetDirectorySearcher() }
foreach ($dcSearcher in $dcSearchers)
{
    $dcSearcher.Filter = '(objectClass=computer)'
    $dcSearcher.PageSize = 1000
    $dcSearcher.SizeLimit = [Int32]::MaxValue
    [Void]$dcSearcher.PropertiesToLoad.AddRange(@('lastLogon','name','userAccountControl','description','distinguishedName'))
}

#Build LastLogon Array
$arrayComputers = New-Object System.Collections.ArrayList
$arrayComputerInfo = New-Object System.Collections.ArrayList
foreach ($dcSearcher in $dcSearchers)
{
    $dcSearcher.FindAll() | ForEach-Object `
    {
        $computerName = $_.Properties.Item('distinguishedname')[0]
        $index = $arrayComputers.BinarySearch($computerName)
        if ($index -lt 0)
        {
            $arrayComputers.Insert((-bnot $index),$computerName)
            $computerInfo = @{
                'name' = [string]($_.Properties.Item('name')[0])
                'enabled' = -not (2 -band $_.Properties.Item('useraccountcontrol')[0])
            }
            if ($_.Properties.PropertyNames -icontains 'lastLogon')
            {
                $computerInfo.Add('lastlogon',$_.Properties.Item('lastlogon')[0])
            }
            else
            {
                $computerInfo.Add('lastlogon',[UInt64]0)
            }
            if ($_.Properties.PropertyNames -icontains 'description')
            {
                $computerInfo.Add('description',$_.Properties.Item('description')[0])
            }
            else
            {
                $computerInfo.Add('description',[String]::Empty)
            }
            $arrayComputerInfo.Insert((-bnot $index),$computerInfo)
        }
        elseif (($_.Properties.PropertyNames -icontains 'lastLogon') -and ($arrayComputerInfo[$index]['lastlogon'] -lt $_.Properties.Item('lastlogon')[0]))
        {
            $arrayComputerInfo[$index]['lastlogon'] = $_.Properties.Item('lastlogon')[0]
        }
    }
}

#Main
cls

foreach ($computer in $arrayComputerInfo)
{

    Write-Host ('{0} - {1} - {2} - {3}' -f $computer['name'], $computer['enabled'], [DateTime]::FromFileTime($computer['lastlogon']), $computer['description'])
}

Thanks

Share this post


Link to post
Share on other sites



You should look at the AD UDF for help in using AutoIt to get the Acitve Directory information


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

You should look at the AD UDF for help in using AutoIt to get the Acitve Directory information

Hi, yeah I said it above already. The AD commands are way too slow. The only option is a ldap query.

Share this post


Link to post
Share on other sites

Have you looked at the functions inside the UDF, most of them are already using LDAP.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Getting the true last logon date is always very slow because you query every DC in the domain. If one of them is down or responds slowly then it takes forever.

Why do you need to query so many machines? Wouldn't a not so accurate logon date be sufficient?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

We're merging 4 domains onto one and the report will be shared between a few system engineers who will rely on those. Some of them need a true last logon date which I can get with the above powershell script, across all domain controllers (46 at the moment but the number will increase with the migrations) in only 15 minutes. It took 20ish via VPN.

Water, does your UDF have ldap queries? I've tried a couple of example I found on the forum, it is a great UDF but couldn't find something fast enough.

One thing to say about the above: With 6k clients and 46 DC's, it'll eat up almost 500MB of RAM but honestly, I'm not really preoccupied about that.

Cheers

Share this post


Link to post
Share on other sites

My UDF uses ADO to connect to a DC or GC and LDAP to query the database.

If you could query property LastLogon you would only need to query one DC and get a value that is off the real date by max. 2 weeks.

About the LastLogon property:

"Please note that this value is NOT replicated between domain controllers - if you want to know the exact last logon time for an account in a domain with more than one domain controllers, you have to check this value on all domain controllers! In Windows 2003 Active Directory, Microsoft introduced another user attribute named lastLogonTimestamp. This attribute is replicated to other DCs, but only after two weeks (minus a random percentage of 5 days), so it is suitable to locate inactive accounts which did not logon to the domain for a long time."


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hi Water,

I've tried to get a lastlogon with your UDF, across all domains and it took about 2 minutes (for a single machine). Same story with PS (Get-ADComputer etc...).

Unfortunately for the kind of cleanup we're doing, 2 weeks are lots of time.

Basically I'm personally looking after the licensing and to do so, we've got to have SCCM up to date and to do that, I'm running reports against AD and SCCM so that people onsite can start finding out what the heck they're doing with their machines.

Unfortunately working in a big organisation requires lots of work if people don't focus on theirs.

Once everything is settled down and we have a 99% of devices inventoried etc, then I can start looking at the lastlogontimestamp, which is indeed replicated. Now, I'll try to keep working with the .ps1 as a scheduled task.

I've started this project by using ADTidy (it also takes about 15/25 minutes to run through all DC's) and creating a new collection for each site we have, then exporting data manually and start comparing it manually. Then, obviously, I've noticed that it was too much work that I could automate, so I started automating the actual report part in excel so I only had to provide the script with the SCCM list for the specific site and the adtidy report, for the specific site (we use a sitecode for each site, so it includes laptops as well, so travellers, that's why I need all DC's). Then I build a report and a subscription in SCCM to automatically export the report against All Systems' collection. Then I made a script which requires the sitecode I want and will catch all the machines. Now, I'll do the same with this script. Once that's done, I'll look at fully automate the process based on a config file which will create a report, daily, for each site.

Pretty easy for now, just wanted to stick with AutoIT :)

Share this post


Link to post
Share on other sites

_AD_GetLastLoginDate first calls _AD_ListDomainControllers to get a list of all DCs to query for the last login date.

To speed up the query you could either limit _AD_GetLastLoginDate to the DCs serving for a site or you could pass an array with DCs to query as parameter 3.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

_AD_GetLastLoginDate first calls _AD_ListDomainControllers to get a list of all DCs to query for the last login date.

To speed up the query you could either limit _AD_GetLastLoginDate to the DCs serving for a site or you could pass an array with DCs to query as parameter 3.

 

Not really, the problem is with travellers. If I query the local DC in the US and the user's been in EU for 5 days, I'll never know its real last logon date. Plus, unfortunately, we have some connectivity issues with sites in SA or Poland which slow the process down..

Share this post


Link to post
Share on other sites

In this case I would do the following:

  • Grab a list of all computer objects you want to check
  • Split the list into (lets say) 5 parts and save each part into a separate file (computers1.txt etc.)
  • Run 5 copies of your script and pass the name of the input file as parameter
  • Let the script query the computers from the input file and write the last logon date into a separate file (result1.txt etc.)
  • Combine the restult files and you are done

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Hey water, I've tried some options, one of those is this:

It's pretty fast to get all last logons through each DC (about 10/15 minutes). What I do is first get a list of DC with csvde, then, always with csvde, I get a a .csv with all the major info I need (name, description) and I'll use this csv as a base to run through each item.

In order to get the last logons I use the below:

$sCommand='csvde -f '&$filename&' -s '&$dc&' -d "'&$Domain&'" -p subtree -r "(&(objectCategory=computer))" -l "lastlogon,samAccountName"'
_RunDos ( $sCommand )

This is ran in a For cycle for each DC found above.

Problem now is comparing then all :(

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  
Followers 0