|
|
|||||||
Having a problem getting a script to work when using an Array to feed information to a Function. I have modified Alex Heitz's ADSearch() function to get specific information. The first script works fine, but the second one gives me the IDispatch Pointers error. homemdb is an AD attribute indicating the user's Exchange mailstore. I am trying to get the homemdb and a partial on the servername where the homemdb is located. What am I doing wrong? *********************************************** ;1st script - this one works, but it is not practical for hundreds of names Code: break ON $test1="abernade" $test2="dbullock" $str="" $server="" adsearch($test1) ? $str ? $server $str="" $server="" adsearch($test2) ? $str ? $server Function ADSearch($ADAccountName) Dim $AdoCon dim $AdoCommand dim $Recordset dim $Filter dim $homemdb dim $store if len($ADAccountName)>0 $filter=" where samAccountName='"+$ADAccountName+"' " $AdoCon = CreateObject("ADODB.Connection") $AdoCon.Provider = "ADsDSOObject" ; Current credentials are used, as username and password aren't specified $AdoCon.Open("Active Directory Provider") ; Create ADO command object for the connection. $AdoCommand = CreateObject("ADODB.Command") $AdoCommand.ActiveConnection = $AdoCon $AdoCommand.CommandText ="Select homemdb from 'LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")+"' "+$filter ; Execute the query. $Recordset = $AdoCommand.Execute $homeMDB=split($recordset.fields("homemdb"),",") ;This is the line where I get the IDispatch Pointers error $store=split($homemdb[0],"=") $str=$store[1] $server=right($homemdb[3],4) Else Exit endif Endfunction ************************************************************ ;2nd script - this one fails Code: break ON dim $test[5] $test[1]="abernade" ;I don't normally create arrays this way, but for simplicity $test[2]="dbullock" for $x=1 to 2 $str="" $server="" adsearch($test[$x]) ? $str ? $server next Function ADSearch($ADAccountName) Dim $AdoCon dim $AdoCommand dim $Recordset dim $Filter dim $homemdb dim $store if len($ADAccountName)>0 $filter=" where samAccountName='"+$ADAccountName+"' " $AdoCon = CreateObject("ADODB.Connection") $AdoCon.Provider = "ADsDSOObject" ; Current credentials are used, as username and password aren't specified $AdoCon.Open("Active Directory Provider") ; Create ADO command object for the connection. $AdoCommand = CreateObject("ADODB.Command") $AdoCommand.ActiveConnection = $AdoCon $AdoCommand.CommandText ="Select homemdb from 'LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")+"' "+$filter ; Execute the query. $Recordset = $AdoCommand.Execute $homeMDB=split($recordset.fields("homemdb"),",") ;This is the line where I get the IDispatch Pointers error $store=split($homemdb[0],"=") $str=$store[1] $server=right($homemdb[3],4) Else Exit endif Endfunction Thanks for you assistance, Dale |
||||||||
|
|
|||||||
First I'd like to suggest you edit your post and put your code in the code tags (# button) so that it will be easier to read. The other odd thing I see is it looks like you've modified the UDF to pull different information, but its not returning anything, ie the ADSearch variable is not being defined with a return value. As for your error, You might try changing this: $homeMDB=split($recordset.fields("homemdb"),",") to (untested) $homeMDB=$recordset.fields("homemdb") $homeMDB=split($homeMDB,",") Also, your for loop could be much easier... $test="abernade","dbullock" for each $x in $test ? $x ;do stuff next |
||||||||
|
|
|||||||
Hello Daleco and welcome to the board. Please review this thread to further enhance your participation here on the board. The Post/Reply Formatting Box and How to use it http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=171901 Thanks . |
||||||||
|
|
|||||||
Thanks Allen By using the loop as you indicated it seems to work. It seems in this case that you can't use the array directly in the Function call as I did in the 2nd script. I did not have to change the homemdb line. This script will be used to capture information on up to several hundred accounts using the account name. Wioth a couple more tweeks this should work nicely in the main script I'm using. Hopefully I will not run into any more difficulty with it. |
||||||||
|
|
|||||||
I am still having difficulty with this piece of code. I have found that the function ADSearch() does not work well if the account name has a period in it, I get the IDispatch error. If the account name does not have a period in it the script below runs fine. The ADSearch function is modified slightly because I needed a different field returned. Code: break ON $test1="aber.nade" ; The period in this account name causes the IDispatch error $str="" $server="" adsearch($test1) ? $str ? $server Function ADSearch($ADAccountName) Dim $AdoCon dim $AdoCommand dim $Recordset dim $Filter dim $homemdb dim $store if len($ADAccountName)>0 $filter=" where samAccountName='"+$ADAccountName+"' " $AdoCon = CreateObject("ADODB.Connection") $AdoCon.Provider = "ADsDSOObject" ; Current credentials are used, as username and password aren't specified $AdoCon.Open("Active Directory Provider") ; Create ADO command object for the connection. $AdoCommand = CreateObject("ADODB.Command") $AdoCommand.ActiveConnection = $AdoCon $AdoCommand.CommandText ="Select homemdb from 'LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")+"' "+$filter ; Execute the query. $Recordset = $AdoCommand.Execute $homeMDB=split($recordset.fields("homemdb"),",") ; This gives the error $store=split($homemdb[0],"=") $str=$store[1] $server=right($homemdb[3],4) Else Exit endif Endfunction |
||||||||
|
|
|||||||
Maybe you can start in debug mode (/d) and step through each line to see which line gives the error. |
||||||||
|
|
|||||||
I marked the line in the code where the error occurs. |
||||||||
|
|
|||||||
It is this part: Code: $recordset.fields("homemdb") ; This gives the error That you cannot split Code: Split($recordset.fields("homemdb"),",") ; This gives the error You can put it in a variable Code: Dim $Var $Var = $recordset.fields("homemdb") |
||||||||
|
|
|||||||
Thanks for that Witto, but the problem still remains. If I use the account name "aber.nade" it does not work, but if the account name does not contain a period "abernade" then it works fine. The problem seems to center around the period in the account name. |
||||||||
|
|
|||||||
Not that this has anything to do with the error you are receiving, but I think you need to start by getting your code correct(as I noted earlier in this thread). The way you are using the UDF is not right. There is a FAQ on using and creating UDFs: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=82017&page=1#Post82017 Please consider the following changes: (I could not test this so its very possible there are bugs) Please read the faq and look through/test my example. If you don't understand why I did it this way then please ask. If we can get this correct, we might be able to figure out the other problem as well. |
||||||||
|
|
|||||||
Allen, Thanks for the test script. I had made the changes you suggested before, but I have the same results when the logon name has a period in it. This is part of what is in the HomeMDB record: CN=PAFB-SG7-AEN CN=PAFB-SG7 (T-Z) CN=InformationStore CN=serverML30 CN=Servers CN=First Administrative Group CN=Administrative Groups CN=AFSPC CN=Microsoft Exchange CN=Services CN=Configuration The parts I am capturing are in RED bold. I have written this script several different ways and the results are always the same, as long as there is no period in the account name it runs fine. The test script you wrote also runs fine if there is no period in the account name, but fails if there is one. Your script gets the IDispatch error on the same line as I do. Code: $homeMDB=split($recordset.fields("homemdb"),",") ; This gives the IDispatch error |
||||||||
|
|
|||||||
Okay... if it works but is broke with the periods.. that is good. Can you provide the same info for a user with a period in the name as you did above (the red)? |
||||||||
|
|
|||||||
It does not process for a user with the period in it. The information above is from a user with no period. BTW, your script does not fail if there is not period in the name, but is doesn't return the data I need either. The data will be different for many users and I need both pieces of information for each user. |
||||||||
|
|
|||||||
I changed the way the values are loaded... did you try the script exactly as it is? Do you MSN? |
||||||||
|
|
|||||||
MSN? I don't understand this. I ran your script exactly as you provided, except to remove the period or put it in. With the period in it fails with the IDispatch. The $store and $Server are empty. |
||||||||
|
|
|||||||
I understand that it did not fix the error... what I am confused about is why it did not return any values. Can you add some error checking to the function? MSN Messenger is what I meant to say. |
||||||||
|
|
|||||||
No I can't use MSN (not allowed here) Without a period in the account name: The $Homemdb is populated correctly in each instance below Code: $homeMDB=split($recordset.fields("homemdb"),",") select case $mode="Store" $store=split($homemdb[0],"=") $HOMEMDB=$store[1] case $mode="Server" $HOMEMDB=right($homemdb[3],4) endselect With a period in it fails on the first line above. Do you have a suggestion on a way to error check this? |
||||||||
|
|
|||||||
I may need some help from some of the COM gurus but try this and see if it says anything with and with out the period right after $Recordset = $AdoCommand.Execute add ? "_______________________" ? $recordset.recordcount ? "_______________________" ? |
||||||||
|
|
|||||||
With a period: _______________________ 0 _______________________ Without a period: _______________________ 1 _______________________ |
||||||||
|
|
|||||||
k... so that means that with a period it is not running the query correctly. The reason you are getting an error is because its trying to split something that has nothing there. Now to figure out why... |
||||||||
|
|
|||||||
Thanks, any help will be greatly appriciated. |
||||||||
|
|
|||||||
Try changing this line $filter=" where samAccountName='["+$ADAccountName+"]' " idea from... http://www.microsoft.com/technet/scriptcenter/resources/qanda/jun05/hey0621.mspx |
||||||||
|
|
|||||||
Looked like that might be a possible after reading the article, but with the brackets in, it doesn't work with or with out a period. 0 in both for the $recordset.recordcount |
||||||||
|
|
|||||||
Sorry... I'm at my end... but I'd be willing to bet Chris S's fnLDAPQuery() - http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=142043&page=1#Post142043 will do what you want. Maybe Chris will check in soon and give you some guidance... or maybe try messing with his example Code: Dim $aAttributes,$sADsPath,$strFilter Dim $aResults,$c,$r $aAttributes = "mail","telephoneNumber","msExchHomeServerName" $sADsPath = "LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext") $strFilter = "(&(objectCategory=person)(objectClass=user)(SAMAccountname="+@UserID+"))" $aResults = fnLDAPQuery($aAttributes,$sADsPath,$strFilter) For Each $r in $aResults If InStr($r,"=") Split($r,"=")[Ubound(Split($r,"="))] Else $r ? EndIf Next |
||||||||
|
|
|||||||
Thanks, I will give it a try, am done for the night. |
||||||||
|
|
|||||||
For splitting characters that are also used by kix, I prefer to avoid confusion and use the Chr() function for the charaters I'd like to Split. For instance: Code: $x = Split("somestr,ing",Chr(44)) |
||||||||
|
|
|||||||
Try using TranslateName() UDF to return the distinguuished name of the user object. Then use the DN in the query instead of the sAmAccountName. |
||||||||
|
|
|||||||
Howard, I had considered Translatename(), but had not tried it. If I use this function on an account name the does not have a period in it, it works fine, however, if I try it on an account name that does have a period in it, I get the following (Used your example): Code I used with the Translatename() Code: $DN = TranslateName (3, "", 3, "@LDomain\kelly.dague", 1) ? "DN = " + $DN[0] ? "Error = " + $DN[1] ? "ErrorText = " + $DN[2] This is the result Quote: DN = Error = -2147352567 ErrorText = COM exception error "Set" ((null) - (null)) [-2147352567/80020009] |
||||||||
|
|
|||||||
Something may be to be wrong or unexpected concerning your account properties. I have created a new test user in my domain with samAccountName "Howard.Bullock" and ran the attached script which properly returns the DN using TranslateName UDF. (This is an updated version but the internal COM is the same.) Open the resulting "Props.txt" file that is created in the current directory. Review your properties such as samAccountName to insure that the your account contains the data you expect. Let me know the result. Please Code: Break on DEL "Props.txt" $rc=SETOPTION ("WrapAtEOL","ON") Dim $NameArray $NameArray = TranslateName (3, "", 3, "@ldomain\Howard.Bullock", "1,2") if @error=0 $UserDN = $NameArray[1] $UserCanonicalname = $NameArray[2] ? "UserDN = " + $UserDN ? ? "UserCanonicalname = " + $UserCanonicalname ? WriteLog2("Props.txt", "UserDN = " + $UserDN) WriteLog2("Props.txt", "UserCanonicalname = " + $UserCanonicalname) WriteLog2("Props.txt","") else ? @serror endif ? ? $object = getobject("LDAP://" + substr(%LogonServer%,3) + "/"+$UserDN) EnumObjProps($object) ;-------------------------------------------------------------------------------------------------- ;FUNCTION EnumObjProps() ; ;AUTHOR Howard A. Bullock (hbullock@tycoelectronics.com) Function EnumObjProps($object) Dim $Class, $Schema, $Value, $property, $cont $Class = GetObject($object.schema) ? "Class: " + $Class.Name WriteLog2("Props.txt", "Class: " + $Class.Name) ? "GUID: " + $Class.GUID WriteLog2("Props.txt", "GUID: " + $Class.GUID) ? "Implemented by: " + $Class.CLSID WriteLog2("Props.txt", "Implemented by: " + $Class.CLSID) If $Class.Container ? ? "Container Object" WriteLog2("Props.txt", "Container Object") ? "Class Contains:" WriteLog2("Props.txt", "Class Contains:") For Each $cont In $Class.Containment ? " " + $cont WriteLog2("Props.txt", " " + $cont) Next Else ? ? "Leaf Object" WriteLog2("Props.txt", "Leaf Object") EndIf ? "Mandatory Properties in this Class: " For Each $property In $Class.MandatoryProperties ? " " + $property $val ="" if $property <> "nTSecurityDescriptor" and $property <> "objectClass" $RC=EXECUTE("$$VAL = $$object.$property") " " +$val WriteLog2("Props.txt", $property + " = " + $val) endif Next ? ? "Optional Properties in this Class: " For Each $property In $Class.OptionalProperties ? " " + $property $val ="" if $property <> "logonHours" and $property <> "dSCorePropagationData" and $property <> "accountExpires" and $property <> "badPasswordTime" and $property <> "lastLogoff" and $property <> "lastLogon" and $property <> "lockoutTime" and $property <> "memberOf" and $property <> "pwdLastSet" and $property <> "uSNChanged" and $property <> "uSNCreated" ;and ;left($property, 5) <> "mS-DS" $RC=EXECUTE('$$VAL = $$object.get("$property")') " = " + $val endif WriteLog2("Props.txt", $property + " = " + $val) Next EndFunction ;-------------------------------------------------------------------------------------------------- ;FUNCTION TranslateName() ; ;AUTHOR Howard A. Bullock (hbullock@tycoelectronics.com) ; ;VERSION 3.0 ; ;ACTION Translates from one name type to another. Good for converting an NT4 name ; like domain\user into an LDAP distinguished name or the reverse. ; ;SYNTAX TranslateName ($InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType) ; ;DATE 2005/04/22 ; ;PARAMETERS $InitType (Required) ; - Integer value ; 1 = ADS_NAME_INITTYPE_DOMAIN ; Initializes a NameTranslate object by setting the domain that the object will bind to. ; ; 2 = ADS_NAME_INITTYPE_SERVER ; Initializes a NameTranslate object by setting the server that the object will bind to. ; ; 3 = ADS_NAME_INITTYPE_GC ; Initializes a NameTranslate object by locating the global catalog that the object will bind to. ; ; $BindName (Required) ; - String value ; If an $InitType = 3 (ADS_NAME_INITTYPE_GC), then the $BindName = "". ; InitTypes 1 and 2 require a name of a domain or server to be input. Note: "" may default ; to the current server or domain. ; ; $LookupNameType (Required) ; - Integer value ; ; $LookupName (Required) ; - String value see below ; ; $ReturnNameType (Required) ; - single Integer or comma separated string of numbers ; ; Documentation of Name Types. Lookup the more info on http://MSDN.Microsoft.com ; Not all name types work. The two that have been most useful to are "1" and "3" ; ; 1 = ADS_NAME_TYPE_1779 ; Name format as specified in RFC 1779. For example, "CN=Jane Doe,CN=users, DC=Microsoft, DC=com". ; ; 2 = ADS_NAME_TYPE_CANONICAL ; Canonical name format. For example, "Microsoft.com/Users/Jane Doe". ; ; 3 = ADS_NAME_TYPE_NT4 ; Account name format used in Microsoft® Windows© NT® 4.0. For example, "Microsoft\JaneDoe". ; ; 4 = ADS_NAME_TYPE_DISPLAY ; Display name format. For example, "Jane Doe". ; ; 5 = ADS_NAME_TYPE_DOMAIN_SIMPLE ; Simple domain name format. For example, "JaneDoe@Microsoft.com". ; ; 6 = ADS_NAME_TYPE_ENTERPRISE_SIMPLE ; Simple enterprise name format. For example, "JaneDoe@Microsoft.com". ; ; 7 = ADS_NAME_TYPE_GUID ; Global Unique Identifier format. For example, {95ee9fff-3436-11d1-b2b0-d15ae3ac8436}. ; ; 8 = ADS_NAME_TYPE_UNKNOWN ; Unknown name type. The system will try to make the best guess. ; ; 9 = ADS_NAME_TYPE_USER_PRINCIPAL_NAME ; User principal name format. For example, "JaneDoe@Fabrikam.com". ; ; 10 = ADS_NAME_TYPE_CANONICAL_EX ; Extended canonical name format. For example, "Microsoft.com/Users Jane Doe". ; ; 11 = ADS_NAME_TYPE_SERVICE_PRINCIPAL_NAME ; Service principal name format. For example, "www/www.microsoft.com@microsoft.com" ; ; 12 = ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME ; A SID string, as defined in the Security Descriptor Definition Language (SDDL), for either ; the SID of the current object or one from the object's SID history. ; For example, "O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" For more information see ; Security Descriptor String Format under "Security" in the Microsoft Platform SDK documentation. ; ;REMARKS Not all name types seem to work. $ReturnNameType can be a single number or a comma separated ; list of numbers. The resulting array will have the coresponding array elements populated ; with the specific names requested. ; ;RETURNS This function returns a 13 element ARRAY. Use the array element that corresponds to the ; number of the name type listed above. ; ;DEPENDENCIES OS: Active Directory aware client ; ;EXAMPLES ; ; These two examples attempt to retrieve all names ; $Names = TranslateName (3, "", 3, @Domain + "\" @wksta + "$", "1,2,3,4,5,6,7,8,9,10,11,12") ; Dim $x ; ? "Ubound = " + ubound($names) ; for $x=0 to ubound($Names) ; ? ""+ $x +": " + $Names[$x] ; next ; ? ; $Names = TranslateName (3, "", 3, @LDomain + "\" + @userid, "1,2,3,4,5,6,7,8,9,10,11,12") ; Dim $x ; ? "Ubound = " + ubound($names) ; for $x=0 to ubound($Names) ; ? ""+ $x +": " + $Names[$x] ; next ; ; Get Distinguished Name (Name type #1) ; $Names = TranslateName (3, "", 3, @LDomain + "\" + @userid, 1) ; ? "DN = " + $Names[1] ; ; Function TranslateName ($InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType) Dim $NameTranslate, $Error, $ErrorText, $ReturnNameArray[12], $GetNameArray, $value $Error = 0 $ErrorText = "" $ReturnName = "" $NameTranslate = CREATEOBJECT ("NameTranslate") $Error = @error $ErrorText = @serror if $Error = 0 $NameTranslate.Init ($InitType, $BindName) $Error = @error $ErrorText = @serror if $Error = 0 $NameTranslate.Set ($LookupNameType, $LookupName) $Error = @error $ErrorText = @serror if $Error = 0 Dim $index $GetNameArray = split($ReturnNameType, ",") for $index=0 to ubound($GetNameArray) $value = $GetNameArray[$index] $ReturnNameArray[$value] = $NameTranslate.Get($value) next else WriteLog("TranslateName SET Error: (" + $Error + ") " + $ErrorText) exit $Error endif else WriteLog("TranslateName INIT Error: (" + $Error + ") " + $ErrorText) exit $Error endif else WriteLog("TranslateName CREATEOBJECT Error: (" + $Error + ") " + $ErrorText) exit $Error endif $TranslateName = $ReturnNameArray Exit 0 Endfunction ;-------------------------------------------------------------------------------------------------- ;FUNCTION WriteLog2() ; ;AUTHOR Howard A. Bullock (hbullock@tycoelectronics.com) ; ;ACTION Generic logging facility for scripts. Appends log entry to a file with an ; optional TimeStamp. ; ;SYNTAX WriteLog2($File, $text, [0|1]) ; ;PARAMETERS $File (Required) - String value ; $text (Required) - String value ; $TimeStamp (Optional) Default(0) no TimeStamp (1 or 0) ; ; ;REMARKS This function writes (appends) an optionally time stamped log entry to the file ; defined in function. This function searches for the first unused file handle, ; open the file, and write the entry. The file handle is then closed. When the ; function is unable to perform its it write the error is displayed in a message box. ; ;RETURNS Nothing ; ;DEPENDENCIES None ; ;EXAMPLES WriteLog2("junk.txt","This is a test") ; WriteLog2("junk.txt","This is a test",0) ; WriteLog2("junk.txt","This is a test",1) ; ; Function WriteLog2($File, $Text, optional $TimeStamp) dim $RC, $File, $text, $FH, $TimeStamp, $nul $FH=1 $RC=Open ($FH, $File, 5) while $RC = -3 and $FH < 11 $FH=$FH +1 $RC=Open ($FH, $File, 5) Loop Select Case $RC=0 if ($TimeStamp=1) $TimeStamp = @Date + " " + @Time + " - " else $TimeStamp = "" endif $RC=Writeline ($FH, $TimeStamp + $Text + @CRLF) if ($RC <> 0) $text = "WriteLine error: $RC @CRLF -4 = File not open for writing@CRLF" + " -3 = File number not open@CRLF -2 = Invalid file number specified@CRLF" + " -1 = End of file" $nul=MessageBox ($text,"Script Error",48) endif $nul=Close ($FH) exit $RC Case $RC=-2 $text = "WriteLog2: Invalid file handle ($FH) specified when trying to Open $File." $nul=MessageBox ($text,"Script Error",48) Case $RC=-1 $text = "WriteLog2: Invalid file name ($File) specified for log file." $nul=MessageBox ($text,"Script Error",48) Case $RC=>0 $text = "System Error($RC) while attempting to open log file ($File)." $nul=MessageBox ($text,"Script Error",48) Endselect exit $RC EndFunction |
||||||||
|
|
|||||||
If the script provided above does not work for your account with a period. I suggest you use LDP.exe to bind to your domain and view the properties of the account is question. |
||||||||
|
|
|||||||
I have tried your new script and it does work for most accounts with a period. There are a few that still have trouble and I will have to research them. I should be able to use the DN to pull the homemdb attribute. Hopefully I can make this work. It will save us a lot of manual work. Thanks |
||||||||
|
|
|||||||
This is an update to this issue. It is working fine now. I was reading lines from an Exmerge file with Exchange 2003. I had ASSUMED the name that exmerge was applying to the PST file was the logon name. I discovered this is not the case. It actually pulls the user name from the LegacyExchangeDN which may or may not be the logon name. Therefore the problem with it having a period in the name was only because I was looking for the logon name with data from the LegacyExchangeDN. In those cases where I was having trouble the LegacyExchangeDN and the logon name were not the same, hence the error I was getting. Howard, the Translatename() was not a fit for this project. Thanks for the suggestion though, it may come in handy elsewhere. Allen, the fnLDAPQuery() worked perfectly, thanks. Moral of the story: Always check the source! Thanks everyone for your assistance. |
||||||||
|
|
|||||||
We are glad to hear that your problem was resolved. |