water Posted September 21, 2018 Author Share Posted September 21, 2018 (edited) The latest available AD UDF can be found here: https://www.autoitscript.com/forum/files/file/355-ad-active-directory-udf/ The version you run can be found by running _AD_VersionInfo.au3 or by checking line 9 ("UDF Version ...:") in the UDF code. Edited September 21, 2018 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 Link to comment Share on other sites More sharing options...
water Posted September 21, 2018 Author Share Posted September 21, 2018 (edited) This test version should display the array of DCs two times (1st all DCs, then the list of DCs for the specified site). Further error information should get written to the SciTE console. 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() If @error Then Exit MsgBox(16, "Active Directory Example Skript", "Function _AD_Open encountered a problem. @error = " & @error & ", @extended = " & @extended) Global $iLLDate = _AD_GetLastLoginDateEX(default, "NFRZ") If @error Then Exit MsgBox(16, "Error", "User: @error=" & @error & ", @extended=" & @extended) MsgBox(64, "Active Directory Functions - Example 1", "Last Login Date for User '" & @UserName & "'" & @CRLF & $iLLDate) ; Close Connection to the Active Directory _AD_Close() ; #FUNCTION# ==================================================================================================================== ; Name...........: _AD_GetLastLoginDate ; Description ...: Returns the lastlogin information for user and computer accounts from all DCs using the SamAccountName. ; Syntax.........: _AD_GetLastLoginDate([$sObject = @Username[, $sSite = ""[, $aDCList = ""]]]) ; Parameters ....: $sObject - Optional: SamAccountName of a user or computer account to get the last login date (default = @Username). ; $sSite - Optional: Only query DCs that belong to this site(s) (default = all sites). ; +This can be a single site or a list of sites separated by commas ; $aDCList - Optional: one-based two dimensional array of Domain Controllers as returned by function _AD_ListDomainControllers (default = "") ; Return values .: Success - Last login date returned as YYYYMMDDHHMMSS. @extended is set to the total number of Domain Controllers. ; +@error could be > 0 and contains the number of DCs that could not be reached or returns no data ; Failure - 0, sets @error to: ; |1 - $sObject could not be found. @extended = 0 ; |2 - $sObject has never logged in to the domain. @extended = 0 ; |3 - $aDCList has to be an array or blank ; |4 - $aDCList has to be a 2-dimensional array ; Warning - Last login date returned as YYYYMMDDHHMMSS (see Success), sets @error and @extended to: ; |x - Number of DCs which could not be reached. Result is returned from all available DCs. @extended is set to the total number of Domain Controllers ; Author ........: Jonathan Clelland ; Modified.......: water, Stephane ; Remarks .......: If it takes (too) long to get a result either some DCs are down or you have too many DCs in your AD. ; +Case one: Please check @error and @extended as described above ; +Case two: Specify parameter $sSite to reduce the number of DCs to query and/or retrieve the list of DCs yourself and pass the array as parameter 3 ; Related .......: ; Link ..........: http://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx ; Example .......: Yes ; =============================================================================================================================== Func _AD_GetLastLoginDateEX($sObject = @UserName, $sSite = "", $aDCList = "") If $sObject = Default Then $sObject = @UserName If $sSite = Default Then $sSite = "" If $aDCList = Default Then $aDCList = "" If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, 0) If Not IsArray($aDCList) And $aDCList <> "" Then Return SetError(3, 0, 0) If IsArray($aDCList) And UBound($aDCList, 0) <> 2 Then Return SetError(4, 0, 0) If $aDCList = "" Then $aDCList = _AD_ListDomainControllers() _ArrayDisplay($aDCList, "List of all DCs") ; ~~ Local $aSite, $sSingleDC, $bWasIn ; Delete all DCs not belonging to the specified site $aSite = StringSplit($sSite, ",", 2) If UBound($aSite) > 0 And $aSite[0] <> "" Then For $iCount1 = $aDCList[0][0] To 1 Step -1 $bWasIn = False For $sSingleDC In $aSite If $aDCList[$iCount1][3] = $sSingleDC Then $bWasIn = True Next If Not $bWasIn Then _ArrayDelete($aDCList, $iCount1) Next $aDCList[0][0] = UBound($aDCList, 1) - 1 EndIf _ArrayDisplay($aDCList, "List of all DCs for the specified site") ; ~~ ; Get LastLogin from all DCs Local $aResult[$aDCList[0][0] + 1] Local $sLDAPEntry, $oObject, $oRecordSet Local $iError1 = 0, $iError2 = 0 For $iCount1 = 1 To $aDCList[0][0] ConsoleWrite("Pinging DC " & $aDCList[$iCount1][2] & @CRLF) If Ping($aDCList[$iCount1][2]) = 0 Then ConsoleWrite(" Result: @error = " & @error & @CRLF) $iError1 += 1 ContinueLoop EndIf ConsoleWrite("Query DC " & $aDCList[$iCount1][2] & @CRLF) $__oAD_Command.CommandText = "<LDAP://" & $aDCList[$iCount1][2] & "/" & $sAD_DNSDomain & ">;(sAMAccountName=" & $sObject & ");ADsPath;subtree" $oRecordSet = $__oAD_Command.Execute ; Retrieve the ADsPath for the object ; -2147352567 or 0x80020009 is returned when the service is not operational ; If @error = -2147352567 Or $oRecordSet.RecordCount = 0 Then If @error Or $oRecordSet.RecordCount = 0 Then ConsoleWrite($aDCList[$iCount1][2] & " returned @error=" & @error & ", @extended=" & @extended & @CRLF) $iError1 += 1 Else $sLDAPEntry = $oRecordSet.fields(0).Value $oObject = __AD_ObjGet($sLDAPEntry) ; Retrieve the COM Object for the object If @error Then ConsoleWrite("ObjGet for " & $aDCList[$iCount1][2] & " returned @error=" & @error & ", @extended=" & @extended & @CRLF) $aResult[$iCount1] = $oObject.LastLogin ; -2147352567 or 0x80020009 is returned when the attribute "LastLogin" isn't defined on this DC ; If @error = -2147352567 Then $iError2 += 1 If @error Then ConsoleWrite("PropertyGet for " & $aDCList[$iCount1][2] & " returned @error=" & @error & ", @extended=" & @extended & @CRLF) $iError2 += 1 EndIf $oObject.PurgePropertyList EndIf Next _ArraySort($aResult, 1, 1) ; If error count equals the number of DCs then the user has never logged in If $iError2 = $aDCList[0][0] Then Return SetError(2, 0, 0) Return SetError($iError1, $aDCList[0][0], $aResult[1]) EndFunc ;==>_AD_GetLastLoginDateEX Edited September 25, 2018 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 Link to comment Share on other sites More sharing options...
Valnurat Posted September 21, 2018 Share Posted September 21, 2018 1st is 79 2nd is 7 and then I get an error: Yours sincerely Kenneth. Link to comment Share on other sites More sharing options...
water Posted September 21, 2018 Author Share Posted September 21, 2018 Which messages do you get on the SciTE console? 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 Link to comment Share on other sites More sharing options...
Valnurat Posted September 24, 2018 Share Posted September 24, 2018 Yours sincerely Kenneth. Link to comment Share on other sites More sharing options...
water Posted September 25, 2018 Author Share Posted September 25, 2018 I modified my above script so it writes to the Console every DC it pings and the error code, if any. 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 Link to comment Share on other sites More sharing options...
CrabChuck Posted November 7, 2018 Share Posted November 7, 2018 Long time reader, first time poster. I'm struggling a bit with _AD_GetObjectOU. If I run this code with @username, it works. But with @computername I get error 1. My user and computer objects are in the same OU. I've already got working code which moves a PC to a new OU, and I'm wanting to prevent these moves for specific OUs. I figured the easiest way would be to drop all the excluded OUs into an array and compare them to the machine's OU. But I can't seem to get this to work for a computer object. _AD_Open("username","password","","","",3) $dnTest = _AD_GetObjectOU(@ComputerName, "distinguishedName") msgbox(48,"Debug", "Name: " & @ComputerName & " Computer DN: " & $dnTest & " Error: " & @error) _AD_Close() Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted November 7, 2018 Moderators Share Posted November 7, 2018 @CrabChuck as shown in the example script for _AD_GetObjectOU, when dealing with computer objects you need to add $ after them. Thhis works just fine for me: #include <AD.au3> _AD_Open() $dnTest = _AD_GetObjectOU(@ComputerName & "$", "distinguishedName") msgbox(48,"Debug", "Name: " & @ComputerName & " Computer DN: " & $dnTest & " Error: " & @error) _AD_Close() "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
CrabChuck Posted November 7, 2018 Share Posted November 7, 2018 How the heck did I miss that!?!? Link to comment Share on other sites More sharing options...
water Posted November 7, 2018 Author Share Posted November 7, 2018 The wiki is a valuable ressource as well: https://www.autoitscript.com/wiki/Active_Directory_UDF_-_General#Tips_.26_Tricks 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 Link to comment Share on other sites More sharing options...
supersonic Posted November 14, 2018 Share Posted November 14, 2018 water, thank you for your UDF and keeping it supported! Sometimes _AD_GetPasswordInfo() produces an error in our environment. Calling $aTemp = _AD_GetObjectProperties($sObject, "MSDS-UserPasswordExpiryTimeComputed") seems to be domain controller dependent. Connected to a 2003 (R2) DC an empty array will return (@error = 0). This seems to be no real failure due to the fact that 2003 does not support this computed value (please see https://docs.microsoft.com/en-us/windows/desktop/adschema/a-msds-userpasswordexpirytimecomputed). A 2008+ (R2) DC returns as expected. As a simple workaround I use this: If @error = 0 And UBound($aTemp, 1) > 1 Then $aPwdInfo[13] = $aTemp[1][1] Else ; Required if DC version < 2008. $aPwdInfo[13] = $aPwdInfo[9] EndIf ... instead of If @error = 0 Then $aPwdInfo[13] = $aTemp[1][1]. I will be pleased if this function could handle this case. Thank you! Link to comment Share on other sites More sharing options...
water Posted November 14, 2018 Author Share Posted November 14, 2018 This is the modified version: expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name...........: _AD_GetPasswordInfo ; Description ...: Returns password information retrieved from the domain policy and the specified user or computer account. ; Syntax.........: _AD_GetPasswordInfo([$sSamAccountName = @UserName]) ; Parameters ....: $sObject - Optional: User or computer account to get password info for (default = @UserName). Format is sAMAccountName or FQDN ; Return values .: Success - Returns a one-based array with the following information: ; |1 - Maximum Password Age (days) ; |2 - Minimum Password Age (days) ; |3 - Enforce Password History (# of passwords remembered) ; |4 - Minimum Password Length ; |5 - Account Lockout Duration (minutes). 0 means the account has to be unlocked manually by an administrator ; |6 - Account Lockout Threshold (invalid logon attempts) ; |7 - Reset account lockout counter after (minutes) ; |8 - Password last changed (YYYY/MM/DD HH:MM:SS in local time of the calling user) or "1601/01/01 00:00:00" (means "Password has never been set") ; |9 - Password expires (YYYY/MM/DD HH:MM:SS in local time of the calling user) or empty when password has not been set before or never expires ; |10 - Password last changed (YYYY/MM/DD HH:MM:SS in UTC) or "1601/01/01 00:00:00" (means "Password has never been set") ; |11 - Password expires (YYYY/MM/DD HH:MM:SS in UTC) or empty when password has not been set before or never expires ; |12 - Password properties. Part of Domain Policy. A bit field to indicate complexity / storage restrictions ; | 1 - DOMAIN_PASSWORD_COMPLEX ; | 2 - DOMAIN_PASSWORD_NO_ANON_CHANGE ; | 4 - DOMAIN_PASSWORD_NO_CLEAR_CHANGE ; | 8 - DOMAIN_LOCKOUT_ADMINS ; | 16 - DOMAIN_PASSWORD_STORE_CLEARTEXT ; | 32 - DOMAIN_REFUSE_PASSWORD_CHANGE ; |13 - Calculated password expiration date/time. Identical with element 9 of this array. ; | Returns a value even when fine grained password policy is in use; which means that most of the other elements of this array are blank or 0. ; | This is a Virtual Attribute (aka "Pseudo Attribute", "Constructed Attribute" or "Back-link") where the value is calculated by the LDAP Server Implementation and is not actually part of the LDAP Entry. ; Failure - "", sets @error to: ; |1 - $sObject not found ; |2 - Function _AD_GetObjectProperties returned an error which is returned in @extended ; Warning - Returns a one-based array (see Success), sets @extended to: ; |1 - Password does not expire (User Access Control - UAC - is set) ; |2 - Password has never been set ; |4 - The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire ; |8 - The version of the accessed DC (needs to be >= 2008) does not support property MSDS-UserPasswordExpiryTimeComputed. Element 13 of the returned array is set to element 9. ; |The @extended value can be a combination of the above values e.g. 3 = 1 (Password does not expire) + 2 (Password has never been set) ; Author ........: water ; Modified.......: ; Remarks .......: For details about password properties please check: http://msdn.microsoft.com/en-us/library/aa375371(v=vs.85).aspx ; Related .......: _AD_IsPasswordExpired, _AD_GetPasswordExpired, _AD_GetPasswordDontExpire, _AD_SetPassword, _AD_DisablePasswordExpire, _AD_EnablePasswordExpire, _AD_EnablePasswordChange, _AD_DisablePasswordChange ; Link ..........: http://www.autoitscript.com/forum/index.php?showtopic=86247&view=findpost&p=619073, http://windowsitpro.com/article/articleid/81412/jsi-tip-8294-how-can-i-return-the-domain-password-policy-attributes.html ; Example .......: Yes ; =============================================================================================================================== Func _AD_GetPasswordInfo($sObject = @UserName) If $sObject = Default Then $sObject = @UserName If _AD_ObjectExists($sObject) = 0 Then Return SetError(1, 0, "") If StringMid($sObject, 3, 1) <> "=" Then $sObject = _AD_SamAccountNameToFQDN($sObject) ; sAMAccountName provided Local $iExtended = 0, $aPwdInfo[14] = [13], $oObject, $oUser, $sPwdLastChanged, $iUAC, $aTemp $oObject = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain) $aPwdInfo[1] = Int(__AD_Int8ToSec($oObject.Get("maxPwdAge"))) / 86400 ; Convert to Days $aPwdInfo[2] = __AD_Int8ToSec($oObject.Get("minPwdAge")) / 86400 ; Convert to Days $aPwdInfo[3] = $oObject.Get("pwdHistoryLength") $aPwdInfo[4] = $oObject.Get("minPwdLength") ; Account lockout duration: http://msdn.microsoft.com/en-us/library/ms813429.aspx ; http://www.autoitscript.com/forum/topic/158419-active-directory-udf-help-support-iii/page-5#entry1173322 $aPwdInfo[5] = __AD_Int8ToSec($oObject.Get("lockoutDuration")) / 60 ; Convert to Minutes If $aPwdInfo[5] < 0 Or $aPwdInfo[5] > 99999 Then $aPwdInfo[5] = 0 $aPwdInfo[6] = $oObject.Get("lockoutThreshold") $aPwdInfo[7] = __AD_Int8ToSec($oObject.Get("lockoutObservationWindow")) / 60 ; Convert to Minutes $oUser = __AD_ObjGet("LDAP://" & $sAD_HostServer & "/" & $sObject) $sPwdLastChanged = $oUser.Get("PwdLastSet") $iUAC = $oUser.userAccountControl ; Has user account password been changed before? If $sPwdLastChanged.LowPart = 0 And $sPwdLastChanged.HighPart = 0 Then $iExtended = BitOR($iExtended, 2) $aPwdInfo[8] = "1601/01/01 00:00:00" $aPwdInfo[10] = "1601/01/01 00:00:00" Else Local $sTemp = DllStructCreate("dword low;dword high") DllStructSetData($sTemp, "Low", $sPwdLastChanged.LowPart) DllStructSetData($sTemp, "High", $sPwdLastChanged.HighPart) ; Have to convert to SystemTime because _Date_Time_FileTimeToStr has a bug (#1638) Local $sTemp2 = _Date_Time_FileTimeToSystemTime(DllStructGetPtr($sTemp)) $aPwdInfo[10] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1) ; Convert PwdlastSet from UTC to Local Time $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2)) $aPwdInfo[8] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1) ; Is user account password set to expire? If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Or $aPwdInfo[1] = 0 Then If BitAND($iUAC, $ADS_UF_DONT_EXPIRE_PASSWD) = $ADS_UF_DONT_EXPIRE_PASSWD Then $iExtended = BitOR($iExtended, 1) If $aPwdInfo[1] = 0 Then $iExtended = BitOR($iExtended, 4) ; The Maximum Password Age is set to 0 in the domain. Therefore, the password does not expire Else $aPwdInfo[11] = _DateAdd("d", $aPwdInfo[1], $aPwdInfo[10]) $sTemp2 = _Date_Time_EncodeSystemTime(StringMid($aPwdInfo[11], 6, 2), StringMid($aPwdInfo[11], 9, 2), StringMid($aPwdInfo[11], 1, 4), StringMid($aPwdInfo[11], 12, 2), StringMid($aPwdInfo[11], 15, 2), StringMid($aPwdInfo[11], 18, 2)) ; Convert PasswordExpires from UTC to Local Time $sTemp2 = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($sTemp2)) $aPwdInfo[9] = _Date_Time_SystemTimeToDateTimeStr($sTemp2, 1) EndIf EndIf $aPwdInfo[12] = $oObject.Get("pwdProperties") $aTemp = _AD_GetObjectProperties($sObject, "MSDS-UserPasswordExpiryTimeComputed") If @error = 0 Then If UBound($aTemp, 1) > 1 Then $aPwdInfo[13] = $aTemp[1][1] Else ; Required if DC version < 2008. $aPwdInfo[13] = $aPwdInfo[9] $iExtended = BitOR($iExtended, 8) EndIf Else Return SetError(2, @error, "") EndIf Return SetError(0, $iExtended, $aPwdInfo) EndFunc ;==>_AD_GetPasswordInfo What I changed: SCRIPT BREAKING: The old function returned some warning information in @error. Now the warning info gets returned in @extended (which is more sensible). The values have changed (old: 2-4 , now: 1, 2, 4, 8). The old form could lead to wrong results. New warning value added: 8 describes that the DC does not support the computed property. If _AD_GetObjectProperties returns an error _AD_GetPasswordInfo returns this error and sets the return value to "". 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 Link to comment Share on other sites More sharing options...
supersonic Posted November 14, 2018 Share Posted November 14, 2018 (edited) water, this was fast! - Rearranging @error/@extended is OK for me (even across all my scripts) - indeed it "is more sensible". - An empty return value in case of @error = 2 is also OK. Can't wait for V1.4.11 Edited November 14, 2018 by supersonic Link to comment Share on other sites More sharing options...
rossy Posted November 15, 2018 Share Posted November 15, 2018 Hi, thanks so much for including the Exchange create mailbox function in the UDF, it's working great. Personally, I'd rather the user not see the Powershell command prompt when creating a mailbox, and just wondering whether this can hidden, either permanently or through a parameter? I've manually changed line 4203 to @SW_HIDE for myself but just a suggestion to include in the UDF Link to comment Share on other sites More sharing options...
water Posted November 15, 2018 Author Share Posted November 15, 2018 Good idea Will add an additional parameter to the next release to set the showflag parameter. 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 Link to comment Share on other sites More sharing options...
water Posted November 16, 2018 Author Share Posted November 16, 2018 This is the modified function. Show_flag is set to Default which means @SW_Hide. What do you think? expandcollapse popup; #FUNCTION#==================================================================================================================== ; Name...........: _AD_CreateMailboxPS ; Description ...: Creates a mailbox for a user using PowerShell ; Syntax.........: _AD_CreateMailboxPS($sUser, $sURI[, $sSessionParam = Default[, $sMailboxParam = Default[, $sRunShowFlag = Default]]) ; Parameters ....: $sUser - User account (SamAccountName or FQDN) for which you want to create the mailbox ; $sURI - Specifies a URI that defines the connection endpoint for the session. The URI must be fully qualified. ; Example: http://YourExchangeServerNameGoesHere.CompanyName.com ; $sSessionParam - Optional: One or multiple additional parameters for the PowerShell "Session" command e.g. " -Authentication Kerberos" ; $sMailboxParam - Optional: One or multiple additional parameters for the PowerShell "Enable-Mailbox" command (see parameter $sSessionParam) ; $sRunShowFlag - Optional: Sets the show-flag parameter of the Run command. Default = Default keyword ; Return values .: Success - Zero based one-dimensional array holding the StdOut messages written by PowerShell ; Failure - "", sets @error to: ; |1 - $sUser does not exist ; |2 - $sUser already has a mailbox ; |3 - $sUser is invalid (empty) ; |4 - $sURI is invalid (empty) ; |5 - Run returned an error (PowerShell could not be started). @extended is set to the @error returned by Run ; |6 - Writing to StdIn returned an error. @extended is set to the @error returned by StdinWrite ; Failure - Zero based one-dimensional array holding the StdErr messages written by PowerShell, sets error to: ; |7 - PowerShell has written some error messages to StdErr. ; Author ........: water ; Modified.......: ; Remarks .......: The mailbox is created using PowerShell. No additional tools need to be installed on the local mchine. ; Related .......: ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _AD_CreateMailboxPS($sUser, $sURI, $sSessionParam = Default, $sMailboxParam = Default, $sRunShowFlag = Default) Local $aResult, $sProperty, $oRecordSet, $sLDAPEntry, $oUser, $iPID, $sCMD = "Powershell -Command -", $sSTDOUT = "", $sSTDERR = "", $sOutput = "", $bError = False If StringStripWS($sUser, $STR_STRIPALL) = "" Then Return SetError(3, 0, "") If StringStripWS($sURI, $STR_STRIPALL) = "" Then Return SetError(4, 0, "") If $sSessionParam = Default Then $sSessionParam = "" If $sMailboxParam = Default Then $sMailboxParam = "" If Not _AD_ObjectExists($sUser) Then Return SetError(1, 0, "") $sProperty = "sAMAccountName" If StringMid($sUser, 3, 1) = "=" Then $sProperty = "distinguishedName" ; FQDN provided $__oAD_Command.CommandText = "<LDAP://" & $sAD_HostServer & "/" & $sAD_DNSDomain & ">;(" & $sProperty & "=" & $sUser & ");ADsPath;subtree" $oRecordSet = $__oAD_Command.Execute ; Retrieve the ADsPath for the object $sLDAPEntry = $oRecordSet.fields(0).Value $oUser = __AD_ObjGet($sLDAPEntry) ; Retrieve the COM Object for the object If $oUser.HomeMDB <> "" Then Return SetError(2, 0, "") $iPID = Run($sCMD, @SystemDir, $sRunShowFlag, $STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD) If $iPID = 0 Or @error Then Return SetError(5, @error, "") $sCMD = "$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri " & $sURI & " " & $sSessionParam & _ ";Import-PSSession $Session" & _ ";Enable-Mailbox -Identity " & $sUser & " " & $sMailboxParam & _ ";Remove-PSSession $Session" StdinWrite($iPID, $sCMD) If @error Then Return SetError(6, @error, "") StdinWrite($iPID) ; Process STDOUT While 1 $sOutput = StdoutRead($iPID) If @error Then ExitLoop If $sOutput <> "" Then $sSTDOUT = $sSTDOUT & $sOutput WEnd ; Process STDERR While 1 $sOutput = StderrRead($iPID) If @error Then ExitLoop If $sOutput <> "" Then $sSTDERR = $sSTDERR & $sOutput $bError = True WEnd If $bError Then $aResult = StringSplit($sSTDERR, @CRLF, $STR_ENTIRESPLIT + $STR_NOCOUNT) Return SetError(7, 0, $aResult) Else $aResult = StringSplit($sSTDOUT, @CRLF, $STR_ENTIRESPLIT + $STR_NOCOUNT) Return $aResult EndIf EndFunc ;==>_AD_CreateMailboxPS 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 Link to comment Share on other sites More sharing options...
supersonic Posted December 7, 2018 Share Posted December 7, 2018 water, thank you for V1.4.11.0 - I'm currently updating my scripts regarding _AD_GetPasswordInfo. Differently than originally thought/written, it's somehow "unhandy" to error out this function by @error = 2 if _AD_GetObjectProperties fails. It will be OK for me if it stays that way, but I think @extended += 8 reflects this issue sufficiently. My idea: If @error = 0 And UBound($aTemp, 1) > 1 Then $aPwdInfo[13] = $aTemp[1][1] Else ; Required if DC version < 2008. $aPwdInfo[13] = $aPwdInfo[9] $iExtended = BitOR($iExtended, 8) EndIf What do you think? Link to comment Share on other sites More sharing options...
water Posted December 7, 2018 Author Share Posted December 7, 2018 With the current implementation I wanted to grab ALL possible situations: The property has been found The property has not been found Another error occurred With your solution I can only grab situation 1 and 2. In which cases do you get @error = 2 where the cause isn't "DC version < 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 Link to comment Share on other sites More sharing options...
supersonic Posted December 10, 2018 Share Posted December 10, 2018 water, I did not express myself well: All of the @extended return codes should stay unchanged - but why should this function error out if _AD_GetObjectProperties fails? As you say yourself "In which cases do you get @error = 2 where the cause isn't "DC version < 2008"?" - so I understand that way both causes happen mostly same time and @extended = 8 currently reflects this situation well enough. I don't really like to bother you, here's a idea of how to reflect both situations using @extended w/o erroring out by @error = 2: $aTemp = _AD_GetObjectProperties($sObject, "MSDS-UserPasswordExpiryTimeComputed") If @error = 0 Then If UBound($aTemp, 1) > 1 Then $aPwdInfo[13] = $aTemp[1][1] Else ; Required if DC version < 2008. $aPwdInfo[13] = $aPwdInfo[9] $iExtended = BitOR($iExtended, 16) EndIf Else $aPwdInfo[13] = $aPwdInfo[9] $iExtended = BitOR($iExtended, 8) EndIf Anyway you decide I'm happy with it - I just liked to let you know. Link to comment Share on other sites More sharing options...
water Posted December 19, 2018 Author Share Posted December 19, 2018 We have 3 cases the function should handle: DC >= 2008: @error = 0, @extended = 0 DC < 2008: @error = 0, @extended = 8 All other situations: @error = 2, @extended depends on the error that happened You get @error = 2 in case number 2? 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 Link to comment Share on other sites More sharing options...
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