water Posted July 27, 2010 Author Posted July 27, 2010 Hi Thomas,Having a function _AD_GetAccountsExpired with a date + time? option would be very nice feature. An additional plus would be if it could filter $sUser so we could use smith* to select all accounts that start with smith.Thanks,TomHi Tom,at the moment it is not possible to do this in one go. Every AD function has a single purpose.As _AD_GetAccountsExpired returns an array containing the FQDN you can either split the FQDN and check the CN=xxx part or you can get the name of each user by calling _AD_GetObjectAttribute.Thomas My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
tom95521 Posted July 28, 2010 Posted July 28, 2010 Hi Tom,at the moment it is not possible to do this in one go. Every AD function has a single purpose.As _AD_GetAccountsExpired returns an array containing the FQDN you can either split the FQDN and check the CN=xxx part or you can get the name of each user by calling _AD_GetObjectAttribute.ThomasYes, that is easy enough to do by looping in the array and testing.Thanks,Tom
water Posted August 1, 2010 Author Posted August 1, 2010 Having a function _AD_GetAccountsExpired with a date + time? option would be very nice feature. Hi Tom, here is the _AD_GetAccountsExpired function with two new parameters. You can define a start and end date/time. All accounts that expire within this "window" are returned. Note: the 2nd parameter is the end date/time of the window and the 3rd parameter is the start date/time. expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name...........: _AD_GetAccountsExpired ; Description ...: Returns an array with FQDNs of expired accounts (user, computer). ; Syntax.........: _AD_GetAccountsExpired([$sAD_Class = "user"[ ,$sAD_DTEExpire = ""[ ,$sAD_DTSExpire = ""]]]) ; Parameters ....: $sAD_Class - Optional: Specifies if expired user accounts or computer accounts should be returned (default = "user"). ; "user" - Returns objects of category "user" ; "computer" - Returns objects of category "computer" ; $sAD_DTEExpire - YYYY/MM/DD HH:MM:SS (local time) returns all accounts that expire between $sAD_DTSExpire and the specified date/time (default = "" = Now) ; $sAD_DTSExpire - YYYY/MM/DD HH:MM:SS (local time) returns all accounts that expire between the specified date/time and $sAD_DTEExpire (default = "1601/01/01 00:00:00) ; Return values .: Success - One-based two dimensional array of FQDNs of expired accounts ; |1 - FQDNs of expired accounts ; |2 - account expired YYYY/MM/DD HH:NMM:SS UTC ; |3 - account expired YYYY/MM/DD HH:NMM:SS local time of calling user ; Failure - "", sets @error to: ; |1 - No expired accounts found ; |2 - Specified date/time is invalid ; |3 - Invalid value for $sAD_Class. Has to be "user" or "computer" ; Author ........: Thomas Rupp ; Modified.......: ; Remarks .......: ; Related .......: _AD_IsAccountExpired, _AD_SetAccountExpire ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _AD_GetAccountsExpired($sAD_Class = "user",$sAD_DTEExpire = "", $sAD_DTSExpire = "") If $sAD_Class <> "user" And $sAD_Class <> "computer" Then Return SetError(3,0,0) ; process end date/time If $sAD_DTEExpire = "" Then $sAD_DTEExpire = _Date_Time_GetSystemTime() ; Get current date/time (UTC) $sAD_DTEExpire = _Date_Time_SystemTimeToDateTimeStr($sAD_DTEExpire, 1) ; convert to format yyyy/mm/dd hh:mm:ss ElseIf Not _DateIsValid($sAD_DTEExpire) Then Return SetError(2,0,0) Else $sAD_DTEExpire = _Date_Time_EncodeSystemTime(StringMid($sAD_DTEExpire,6,2),StringMid($sAD_DTEExpire,9,2),StringLeft($sAD_DTEExpire,4), _ ; encode input StringMid($sAD_DTEExpire,12,2),StringMid($sAD_DTEExpire,15,2),StringMid($sAD_DTEExpire,18,2)) Local $sAD_DTEExpireUTC = _Date_Time_TzSpecificLocalTimeToSystemTime(DllStructGetPtr($sAD_DTEExpire)) ; convert local time to UTC $sAD_DTEExpire = _Date_Time_SystemTimeToDateTimeStr($sAD_DTEExpireUTC, 1) ; convert to format yyyy/mm/dd hh:mm:ss EndIf ; process start date/time If $sAD_DTSExpire = "" Then $sAD_DTSExpire = "1600/01/01 00:00:00" If Not _DateIsValid($sAD_DTSExpire) Then Return SetError(2,0,0) Else $sAD_DTSExpire = _Date_Time_EncodeSystemTime(StringMid($sAD_DTSExpire,6,2),StringMid($sAD_DTSExpire,9,2),StringLeft($sAD_DTSExpire,4), _ ; encode input StringMid($sAD_DTSExpire,12,2),StringMid($sAD_DTSExpire,15,2),StringMid($sAD_DTSExpire,18,2)) Local $sAD_DTSExpireUTC = _Date_Time_TzSpecificLocalTimeToSystemTime(DllStructGetPtr($sAD_DTSExpire)) ; convert local time to UTC $sAD_DTSExpire = _Date_Time_SystemTimeToDateTimeStr($sAD_DTSExpireUTC, 1) ; convert to format yyyy/mm/dd hh:mm:ss EndIf Local $iAD_DTEExpire = _DateDiff("s", "1601/01/01 00:00:00", $sAD_DTEExpire) * 10000000 ; convert end date/time to Integer8 Local $iAD_DTSExpire = _DateDiff("s", "1601/01/01 00:00:00", $sAD_DTSExpire) * 10000000 ; convert start date/time to Integer8 Local $iAD_Temp, $sAD_Temp Local $sAD_DTStruct = DllStructCreate("dword low;dword high") ; -1 to remove rounding errors Local $sAD_Query = "<LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain & ">;(&(objectCategory=person)(objectClass=" & $sAD_Class & ")" & _ "(!accountExpires=0)(accountExpires<=" & Int($iAD_DTEExpire)-1 & ")(accountExpires>=" & Int($iAD_DTSExpire)-1 &"));distinguishedName,accountExpires;subtree" Local $oAD_RecordSet = $oAD_Connection.Execute($sAD_Query) If Not IsObj($oAD_RecordSet) Or $oAD_RecordSet.RecordCount = 0 Then Return SetError(1, 0, "") Local $aAD_FQDN[$oAD_RecordSet.RecordCount + 1][3] $aAD_FQDN[0][0] = $oAD_RecordSet.RecordCount Local $iAD_Count = 1 While Not $oAD_RecordSet.EOF $aAD_FQDN[$iAD_Count][0] = $oAD_RecordSet.Fields(0).Value ; distinguishedName $iAD_Temp = $oAD_RecordSet.Fields(1).Value ; accountExpires DllStructSetData($sAD_DTStruct, "Low", $iAD_Temp.LowPart) DllStructSetData($sAD_DTStruct, "High", $iAD_Temp.HighPart) $sAD_Temp = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sAD_DTStruct)) $aAD_FQDN[$iAD_Count][1] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1) ; accountExpires as UTC $sAD_Temp = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sAD_Temp)) $aAD_FQDN[$iAD_Count][2] = _Date_Time_SystemTimeToDateTimeStr($sAD_Temp, 1) ; accountExpires as local time $iAD_Count += 1 $oAD_RecordSet.MoveNext WEnd $aAD_FQDN[0][0] = UBound($aAD_FQDN) - 1 Return $aAD_FQDN EndFunc ;==>_AD_GetAccountsExpired What do you think? My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
tom95521 Posted August 4, 2010 Posted August 4, 2010 Hi Thomas, I did not have time to test today, but the function looks great. I will test tomorrow in our AD. Thanks, Tom
water Posted August 5, 2010 Author Posted August 5, 2010 I missed to attach the example script for _AD_GetAccountsExpired: expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters= -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #AutoIt3Wrapper_AU3Check_Stop_OnWarning=Y #include <AD.au3> ; Open Connection to the Active Directory _AD_Open() Global $aDisabled[1] ; ***************************************************************************** ; Example 1 ; Get a list of expired user accounts ; ***************************************************************************** $aDisabled = _AD_GetAccountsExpired() If @error > 0 Then MsgBox(64, "Active Directory Functions - Example 1", "No expired user accounts could be found") Else _ArrayDisplay($aDisabled, "Active Directory Functions - Example 1 - Expired User Accounts") EndIf ; ***************************************************************************** ; Example 2 ; Get a list of user accounts that expire end of this year ; ***************************************************************************** $aDisabled = _AD_GetAccountsExpired("user", @YEAR & "/12/31") If @error = 0 Then _ArrayDisplay($aDisabled, "Active Directory Functions - Example 2 - Expired User Accounts") ElseIf @error = 1 Then MsgBox(64, "Active Directory Functions - Example 2", "No expired user accounts could be found") Else MsgBox(64, "Active Directory Functions - Example 2", "Invalid parameters provided") EndIf ; ***************************************************************************** ; Example 3 ; Get a list of user accounts that expire between january and october this year ; ***************************************************************************** $aDisabled = _AD_GetAccountsExpired("user", @YEAR & "/10/31", @YEAR & "/01/01") If @error = 0 Then _ArrayDisplay($aDisabled, "Active Directory Functions - Example 3 - Expired User Accounts") ElseIf @error = 1 Then MsgBox(64, "Active Directory Functions - Example 3", "No expired user accounts could be found") Else MsgBox(64, "Active Directory Functions - Example 3", "Invalid parameters provided") EndIf ; ***************************************************************************** ; Example 4 ; Get a list of expired computer accounts ; ***************************************************************************** $aDisabled = _AD_GetAccountsExpired("computer") If @error > 0 Then MsgBox(64, "Active Directory Functions - Example 4", "No expired computer accounts could be found") Else _ArrayDisplay($aDisabled, "Active Directory Functions - Example 4 - Expired Computer Accounts") EndIf ; Close Connection to the Active Directory _AD_Close() My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
tom95521 Posted August 5, 2010 Posted August 5, 2010 Hi Thomas, This is great. I ran your test script. I can use it to find soon to be expired AD accounts. I will use it in my next AD library card program. Thanks! Tom
water Posted August 5, 2010 Author Posted August 5, 2010 Glad to hear. Will be part of the upcoming version 0.40. My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
mnorland Posted August 9, 2010 Posted August 9, 2010 Glad to hear. Will be part of the upcoming version 0.40.This seems like the most logical place to give feedback / comments / suggestions / questions about the AD UDF you've written (awesome work, by the way!). This is, by the way, basically directed at water - though I encourage anyones comments/thoughts.I'm working on a script for our employees home machines (e.g. not domain machines), when on the VPN, to check their credentials and then map network drives. I have it working, but had to disable the checks I was using to test if their password is expired or if their account was disabled. It appears that the problem is because _AD_IsPasswordExpired and _AD_IsObjectLocked eventually call _AD_GetPasswordInfo() which doesn't make use of $oAD_Connection at all. In doing some searches, it looks like there are probably some other functions that do direct .Get()'s on hand-rolled LDAP queries instead of going through the existing connection.My question is twofold - one, is there any reason (beyond historic / that's how it was written) it's done this way, and two should I endeavor to rewrite _AD_GetPasswordInfo for you, or would you rather make the changes yourself? As it stands I can pull out the bits I need with _AD_GetObjectAttribute calls for what little I need, but it probably won't be much more effort to change it over if you'd rather.Thanks,-Martin
water Posted August 10, 2010 Author Posted August 10, 2010 This seems like the most logical place to give feedback / comments / suggestions / questions about the AD UDF you've written (awesome work, by the way!). This is, by the way, basically directed at water - though I encourage anyones comments/thoughts.I'm working on a script for our employees home machines (e.g. not domain machines), when on the VPN, to check their credentials and then map network drives. I have it working, but had to disable the checks I was using to test if their password is expired or if their account was disabled. It appears that the problem is because _AD_IsPasswordExpired and _AD_IsObjectLocked eventually call _AD_GetPasswordInfo() which doesn't make use of $oAD_Connection at all. In doing some searches, it looks like there are probably some other functions that do direct .Get()'s on hand-rolled LDAP queries instead of going through the existing connection.My question is twofold - one, is there any reason (beyond historic / that's how it was written) it's done this way, and two should I endeavor to rewrite _AD_GetPasswordInfo for you, or would you rather make the changes yourself? As it stands I can pull out the bits I need with _AD_GetObjectAttribute calls for what little I need, but it probably won't be much more effort to change it over if you'd rather.Thanks,-MartinHi Martin,there are two reasons why this is done the way it is:historical: I started with just converting the adfunctions to a UDF adding documentation, examples and a help file. Later new functions were added.technical: _AD_GetPasswordInfo directly connects to the PDC and therefore doesn't use $oAD_Connection. The PDC handles the login requests and "knows" about the locked out or disabled accounts, expired passwords etc. without having to wait for synchronization to occur.My knowledge of AD is quite limited (I'm learning as I'm working on this UDF) and I only have readonly access to our AD.If you have enhancements for the UDF I will be glad to incorporate them!Thomas My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
water Posted August 12, 2010 Author Posted August 12, 2010 (edited) I enhanced the _AD_Open function to get more information if the connection to the AD could not be established.When you provide a userid/password _AD_Open tries to test the credentials and returns an array with extended information in case of an error (for more details please see the heading of the _AD_Open function, return value: x).Unfortunately this only works with Windows 7 (and later). For Windows XP and lower you only get @error = 8. If you want to test it with Windows Vista (it should work but I can't test it) then you have to change the line containing If @OSVersion = "Win_7" Then to If @OSVersion = "Win_VISTA" ThenAnyone willing to test and post the results?Edit: I combined everything in the following attachment. Just run the following code:expandcollapse popup#include <AD.au3> $R = _AD_OpenEx("domain\userid","password") If @error <> 0 Then If @error <= 8 Then MsgBox(0,"AD Test Script","Error Code: " & @error & ", Extended: " & @extended & " returned by _AD_Open") Else If IsArray($R) Then _ArrayDisplay($R) EndIf EndIf _AD_Close() Exit ; #FUNCTION# ==================================================================================================================== ; Name...........: _AD_Open ; Description ...: Opens a connection to the Active Directory. ; Syntax.........: _AD_Open([$sAD_UserIdParam = "", $sAD_PasswordParam = ""[, $sAD_DNSDomainParam = "", $sAD_HostServerParam = "", $sAD_ConfigurationParam = ""]]) ; Parameters ....: $sAD_UserIdParam - Optional: UserId to authenticate with. This has to be a valid domain user ; $sAD_PasswordParam - Optional: Password to authenticate with ; $sAD_DNSDomainParam - Optional: Active Directory domain name if you want to connect to a different domain ; $sAD_HostServerParam - Optional: Name of the connected Domain Controller if you want to connect to a different domain ; $sAD_ConfigurationParam - Optional: Configuration naming context if you want to connect to a different domain ; Return values .: Success - 1 ; Failure - 0 or array, sets @error to: ; |1 - Installation of the custom error handler failed. @extended set to error code of ObjEvent ; |2 - Creation of the COM object to the AD failed. @extended set to error code of ObjCreate ; |3 - Open the connection to AD failed. @extended set to error code received by the COM error handler. ; | Happens when the User doesn't have query / modify access ; |4 - Creation of the RootDSE object failed. @extended set to error code received by the COM error handler. ; | Happens when the connection to the domain isn't successful. @extended is set to -2147023541 (0x8007054B) ; |5 - Creation of the DS object failed. @extended set to error code received by the COM error handler ; |6 - Parameter $sAD_HostServerParam and $sAD_ConfigurationParam have to be specified when $sAD_DNSDomainParam is specified ; |7 - Parameter $sAD_PasswordParam has to be specified when $sAD_UserIdParam is specified ; |8 - OpenDSObject method failed. @extended set to error code received by the COM error handler. ; | On Windows XP or lower this shows that $sAD_UserIdParam and/or $sAD_PasswordParam are invalid ; |x - For Windows 7 systems: Win32 error code (decimal). Returns an array with the following information: ; |1 - ADSI error code (decimal) ; |2 - Unicode string that describes the ADSI error ; |3 - name of the provider that raised the error ; |4 - Win32 error code extracted from element[2] ; |5 - description of the Win32 error code as returned by _WinAPI_FormatMessage ; Author ........: Jonathan Clelland ; Modified.......: Thomas Rupp ; Remarks .......: To close the connection to the Active Directory, use the _AD_Close function. ;+ ; _AD_Open will use the alternative credentials $sAD_UserIdParam and $sAD_PasswordParam if passed as parameters. ; $sAD_UserIdParam has to be in one of the following formats (assume the samAccountName = DJ) ; * Windows Login Name e.g. "DJ" ; * NetBIOS Login Name e.g. "<DOMAIN>\DJ" ; * User Principal Name e.g. "DJ@domain.com" ; All other name formats have not been successfully tested (see section "Link"). ;+ ; If you want to connect to a different domain (not the domain your computer is a member of) or your computer is no domain member ; then please provide $sAD_DNSDomainParam, $sAD_HostServerParam and $sAD_ConfigurationParam as FQDN as well as $sAD_UserIdParam and $sAD_PasswordParam. ; Example: ; $sAD_DNSDomainParam = "DC=subdomain,DC=example,DC=com" ; $sAD_HostServerParam = "servername.subdomain.example.com" ; $sAD_ConfigurationParam = "CN=Configuration,DC=subdomain,DC=example,DC=com" ;+ ; The COM error handler will be set up if there isn't an error handler already active. ; But be aware that some functions will not work correctly any more because they handle error codes ($iAD_COMError) that are set by the error handler. ;+ ; If you specify $sAD_UserIdParam and the OS is Windows 7 then _AD_Open will try to verify the userid/password (see return values). ; Related .......: _AD_Close ; Link ..........: http://msdn.microsoft.com/en-us/library/cc223499(PROT.10).aspx (Simple Authentication), http://msdn.microsoft.com/en-us/library/aa746471(VS.85).aspx (ADO) ; Example .......: Yes ; =============================================================================================================================== Func _AD_OpenEx($sAD_UserIdParam = "", $sAD_PasswordParam = "", $sAD_DNSDomainParam = "", $sAD_HostServerParam = "", $sAD_ConfigurationParam = "") ; A COM error handler will only be set up if there isn't an error handler already active. If ObjEvent("AutoIt.Error") = "" Then $oAD_MyError = ObjEvent("AutoIt.Error", "_AD_ErrorHandler") ; Install a custom error handler If @error <> 0 Then Return SetError(1, @error, 0) EndIf $iAD_COMError = 0 $oAD_Connection = ObjCreate("ADODB.Connection") ; Create COM object to AD If Not IsObj($oAD_Connection) Or @error <> 0 Then Return SetError(2, @error, 0) ; ConnectionString Property (ADO): http://msdn.microsoft.com/en-us/library/ms675810.aspx $oAD_Connection.ConnectionString = "Provider=ADsDSOObject" ; Set Service providertype If $sAD_UserIdParam <> "" Then If $sAD_PasswordParam = "" Then Return SetError(7, 0, 0) $oAD_Connection.Properties("User ID") = $sAD_UserIdParam ; Authenticate User $oAD_Connection.Properties("Password") = $sAD_PasswordParam ; Authenticate User ; If userid is the Windows login name then set the flag for secure authentifiction If StringInStr($sAD_UserIdParam, "\") = 0 And StringInStr($sAD_UserIdParam, "@") = 0 Then $oAD_Connection.Properties("ADSI Flag") = $ADS_SECURE_AUTH Else $oAD_Connection.Properties("ADSI Flag") = 0x0 EndIf $sAD_UserId = $sAD_UserIdParam $sAD_Password = $sAD_PasswordParam EndIf ; ADO Open Method: http://msdn.microsoft.com/en-us/library/ms676505.aspx $oAD_Connection.Open() If @error <> 0 Then Return SetError(3, @error, 0) ; Connect to another Domain if the Domain parameter is provided If $sAD_DNSDomainParam <> "" Then If $sAD_HostServerParam = "" Or $sAD_ConfigurationParam = "" Then Return SetError(6, 0, 0) $oAD_RootDSE = ObjGet("LDAP://" & $sAD_HostServerParam & "/RootDSE") If Not IsObj($oAD_RootDSE) Or @error <> 0 Then Return SetError(4, @error, 0) $sAD_DNSDomain = $sAD_DNSDomainParam $sAD_HostServer = $sAD_HostServerParam $sAD_Configuration = $sAD_ConfigurationParam Else $oAD_RootDSE = ObjGet("LDAP://RootDSE") If Not IsObj($oAD_RootDSE) Or @error <> 0 Then Return SetError(4, @error, 0) $sAD_DNSDomain = $oAD_RootDSE.Get("defaultNamingContext") ; Retrieve the current AD domain name $sAD_HostServer = $oAD_RootDSE.Get("dnsHostName") ; Retrieve the name of the connected DC $sAD_Configuration = $oAD_RootDSE.Get("ConfigurationNamingContext") ; Retrieve the Configuration naming context EndIf $oAD_OpenDS = ObjGet("LDAP:") If Not IsObj($oAD_OpenDS) Or @error <> 0 Then Return SetError(5, @error, 0) ; Check userid/password if provided If $sAD_UserIdParam <> "" Then Local $oAD_Temp = $oAD_OpenDS.OpenDSObject("LDAP://" & $sAD_HostServer, $sAD_UserId, $sAD_Password, $ADS_SERVER_BIND) If Not IsObj($oAD_Temp) Or @error <> 0 Then ; login error occurred - get extended information If @OSVersion = "Win_7" Then ; Delivers detailed error information for Windows 7 and later, sets @error for all other OS. Local $aAD_Errors = _AD_GetLastErrorEx() If $aAD_Errors[4] <> 0 Then If $iAD_Debug = 1 Then ConsoleWrite("_AD_Open: " & _ArrayToString($aAD_Errors, @CRLF, 1) & @CRLF) If $iAD_Debug = 2 Then MsgBox(64, "Active Directory Functions - Debug Info - _AD_Open", _ArrayToString($aAD_Errors, @CRLF, 1)) If $iAD_Debug = 3 Then FileWrite("AD_Debug.txt", @YEAR & "." & @MON & "." & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @CRLF & _ "-------------------" & @CRLF & "_AD_Open: " & _ArrayToString($aAD_Errors, @CRLF, 1) & @CRLF & _ "========================================================" & @CRLF) Return Seterror(Dec($aAD_Errors[4]), 0, $aAD_Errors) Endif Else Return SetError(8, @error, 0) EndIf Endif Endif Return 1 EndFunc ;==>_AD_Open ; #INTERNAL_USE_ONLY#============================================================================================================ ; Name...........: _AD_GetLastError ; Description ...: Uses the ADsGetLastError function to retrieve the calling thread's last-error code value. ; Syntax.........: _AD_GetLastError() ; Parameters ....: None ; Return values .: Success - An array containing the following values: ; |1 - ADSI error code (decimal) ; |2 - Unicode string that describes the error ; |3 - name of the provider that raised the error ; Failure - 0, sets @error to the return values of DLLCall ; Return values .: ; Author ........: Thomas Rupp ; Modified.......: ; Remarks .......: This function is used internally ; Related .......: ; Link ..........: http://msdn.microsoft.com/en-us/library/cc231199(PROT.10).aspx (Win32 Error Codes), http://forums.sun.com/thread.jspa?threadID=703398 ; Example .......: ; =============================================================================================================================== Func _AD_GetLastErrorEx() Local $aAD_LastError[6] = [5] Local $EC = DllStructCreate("DWord") Local $ED = DllStructCreate("wchar[256]") Local $PN = DllStructCreate("wchar[256]") DllCall("Activeds.dll", "DWORD", "ADsGetLastError", "ptr", DllStructGetPtr($EC), "ptr", DllStructGetPtr($ED), "DWORD", 256, "ptr", DllStructGetPtr($PN), "DWORD", 256) If @error <> 0 Then Return SetError(@error, @extended, "") $aAD_LastError[1] = DllStructGetData($EC, 1) ; error code (decimal) $aAD_LastError[2] = DllStructGetData($ED, 1) ; Unicode string that describes the error $aAD_LastError[3] = DllStructGetData($PN, 1) ; name of the provider that raised the error Local $sAD_Error = StringTrimLeft($aAD_LastError[2], StringInStr($aAD_LastError[2], "AcceptSecurityContext", 2)) $sAD_Error = StringTrimLeft($sAD_Error, StringInStr($sAD_Error, " data", 2) + 5) $aAD_LastError[4] = StringTrimRight($sAD_Error, StringLen($sAD_Error) - StringInStr($sAD_Error, ", vece", 2) + 1) _WinAPI_FormatMessage($__WINAPICONSTANT_FORMAT_MESSAGE_FROM_SYSTEM, 0, Dec($aAD_LastError[4]), 0, $aAD_LastError[5], 4096, 0) Return $aAD_LastError EndFunc ;==>_AD_GetLastErrorExample of error array (on a german system - row 5 means: user not found): Edited August 17, 2010 by water My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
supersonic Posted August 13, 2010 Posted August 13, 2010 Hi water, I've tested it, but I always get @error = 0. Greets, -supersonic.
water Posted August 14, 2010 Author Posted August 14, 2010 (edited) Hi supersonic,what OS do you run? The new feature only works for Windows 7. On Windows XP you should get @error = 8 (for this to work please download the changed code again). It might work for Vista but then you have to change the script according to my original postingIf you run Windows 7 how did you specify the userid (Domain\userid, userid or userid@microsoft.com)? Edited August 14, 2010 by water My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
supersonic Posted August 16, 2010 Posted August 16, 2010 (edited) Hi water, I run the example script as you provided: $R = _AD_Open("DE01\Administrator","password") If @error <> 0 Then If @error <= 7 Then MsgBox(0,"AD Test Script","Error Code: " & @error & " returned by _AD_Open") Else If IsArray($R) Then _ArrayDisplay($R) EndIf EndIf _AD_Close() Exit Edited August 16, 2010 by supersonic
water Posted August 16, 2010 Author Posted August 16, 2010 Hi supersonic,I combined everything in one script. Coulde you please download the code again from this post?So if you are running Windows XP you should at least get @error=8 when an invalid userid or password is provided.Thanks My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
supersonic Posted August 17, 2010 Posted August 17, 2010 Hi water! I tried running the script under W7 from your post again. Nothing happens. BTW: Please change '_AD_GetLastError' in line 117 to '_AD_GetLastErrorEx'. What can I do? Greets, -supersonic.
water Posted August 17, 2010 Author Posted August 17, 2010 Hi supersonic, BTW: Please change '_AD_GetLastError' in line 117 to '_AD_GetLastErrorEx'.Done. What can I do?Could you please insert #AutoIt3Wrapper_Run_Debug_Mode=ybefore$R = _AD_OpenEx("domain\userid","password")and post the console output? Thanks for testing! My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
supersonic Posted August 17, 2010 Posted August 17, 2010 Of course! expandcollapse popup0001: 0-0: #include ".\..\AUTOIT\Include\Water\AD\AD.au3" 0002: 0-0: #AutoIt3Wrapper_Run_Debug_Mode=y 0003: 0-0: $R = _AD_OpenEx("DOMAIN\Administrator", "password") 0071: 0-0: If ObjEvent("AutoIt.Error") = "" Then 0072: 0-0: $oAD_MyError = ObjEvent("AutoIt.Error", "_AD_ErrorHandler") ; Install a custom error handler 0073: 0-0: If @error <> 0 Then Return SetError(1, @error, 0) 0074: 0-0: EndIf 0075: 0-0: $iAD_COMError = 0 0076: 0-0: $oAD_Connection = ObjCreate("ADODB.Connection") ; Create COM object to AD 0077: 0-0: If Not IsObj($oAD_Connection) Or @error <> 0 Then Return SetError(2, @error, 0) 0079: 0-0: $oAD_Connection.ConnectionString = "Provider=ADsDSOObject" ; Set Service providertype 0080: 0-0: If $sAD_UserIdParam <> "" Then 0081: 0-0: If $sAD_PasswordParam = "" Then Return SetError(7, 0, 0) 0082: 0-0: $oAD_Connection.Properties("User ID") = $sAD_UserIdParam ; Authenticate User 0083: 0-0: $oAD_Connection.Properties("Password") = $sAD_PasswordParam ; Authenticate User 0085: 0-0: If StringInStr($sAD_UserIdParam, "\") = 0 And StringInStr($sAD_UserIdParam, "@") = 0 Then 0088: 0-0: $oAD_Connection.Properties("ADSI Flag") = 0x0 0089: 0-0: EndIf 0090: 0-0: $sAD_UserId = $sAD_UserIdParam 0091: 0-0: $sAD_Password = $sAD_PasswordParam 0092: 0-0: EndIf 0094: 0-0: $oAD_Connection.Open() 0095: 0-0: If @error <> 0 Then Return SetError(3, @error, 0) 0097: 0-0: If $sAD_DNSDomainParam <> "" Then 0105: 0-0: $oAD_RootDSE = ObjGet("LDAP://RootDSE") 0106: 0-0: If Not IsObj($oAD_RootDSE) Or @error <> 0 Then Return SetError(4, @error, 0) 0107: 0-0: $sAD_DNSDomain = $oAD_RootDSE.Get("defaultNamingContext") ; Retrieve the current AD domain name 0108: 0-0: $sAD_HostServer = $oAD_RootDSE.Get("dnsHostName") ; Retrieve the name of the connected DC 0109: 0-0: $sAD_Configuration = $oAD_RootDSE.Get("ConfigurationNamingContext") ; Retrieve the Configuration naming context 0110: 0-0: EndIf 0111: 0-0: $oAD_OpenDS = ObjGet("LDAP:") 0112: 0-0: If Not IsObj($oAD_OpenDS) Or @error <> 0 Then Return SetError(5, @error, 0) 0114: 0-0: If $sAD_UserIdParam <> "" Then 0115: 0-0: Local $oAD_Temp = $oAD_OpenDS.OpenDSObject("LDAP://" & $sAD_HostServer, $sAD_UserId, $sAD_Password, $ADS_SERVER_BIND) 0116: 0-0: If Not IsObj($oAD_Temp) Or @error <> 0 Then ; login error occurred - get extended information 0131: 0-0: Endif 0132: 0-0: Return 1 0004: 0-0: If @error <> 0 Then 0011: 0-0: _AD_Close() 0012: 0-0: Exit
water Posted August 17, 2010 Author Posted August 17, 2010 That helps a lot!The difference is that lineLocal $oAD_Temp = $oAD_OpenDS.OpenDSObject("LDAP://" & $sAD_HostServer, $sAD_UserId, $sAD_Password, $ADS_SERVER_BIND)seems to return a different result.Could you please insert ConsoleWrite(IsObj($oAD_Temp) & "-" & @error & "-" & @extended & @CRLF)after this line and post the output of the ConsoleWrite?I get 0-0-0 if I provide an invalid userid/password.BTW: What version is your Domain Controller? Windows 2003, Windows 2008? My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
supersonic Posted August 17, 2010 Posted August 17, 2010 (edited) Strange, strange... Now it works!? But I haven't change anything... The results are: 0-0-0 (invalid password and/or user, error code 8, extended code 0), 1-0-0 (valid password and user). We are currently using MS-Windows 2003 R2 as domain controllers. Edited August 17, 2010 by supersonic
water Posted August 17, 2010 Author Posted August 17, 2010 (edited) Strange, strange... Now it works!? But I haven't change anything...You didn't change anything but by inserting ConsoleWrite the script now checks the @error of ConsoleWrite which is always 0. But I think I found the bug: Could you please change the lineIf Not IsObj($oAD_Temp) Or @error <> 0 ThentoIf @error <> 0 Or IsObj($oAD_Temp) = 0 Then BTW: As you get returncode 8 I assume you are running Windows XP? Edited August 17, 2010 by water My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
Recommended Posts