Thursday, January 05, 2006

Exporting Active Directory users contacts and the Exchange GAL to a vCard

I’ve written a bit about vCards in the past mostly these where import scripts but one of the other ways you can use vCards with CDOEX is if you want to export active directory users or contacts to be used in another system. Basically with CDOEX you can use Iperson to create or modify Active directory users or contacts see the Exchange SDK for samples. You can also go the same way and use CDOEX and the GetvCardStream stream method to export an Active Directory user or contact to a vcard. eg

set iper = createobject("CDO.Person")
iper.datasource.open "LDAP://userdn"
Set strm = iper.GetvCardStream
strm.savetofile "c:\exp.vcf"

So if we expand out this idea a bit say I want to export the Exchange GAL to use in the palm desktop I can use an ADSI query to return all the distinguishedName’s of the user’s in the Exchange GAL and then use CDOEX and Iperson to connect to each object and use GetvCardStream method to get the Vcard text stream and create a vcard that contains all the users in the Exchange GAL that can them be imported in the palm desktop or any other application that you might want to have the Exchange GAL imported into.

I’ve created 2 versions of the script to do this the first version exptovcardsng.vbs exports all the users in the Exchange GAL to a single vcf file which is useful for programs like the Palm desktop. The other version exports all the users in the gal to separate VCF files for each user. Because these scripts use LDAP they don’t need to be run directly on a Exchange server as long as you have CDOEX installed locally on the workstation you are running the script from. I’ve put a downloadable copy of the 2 scripts here

The script itself looks like

Set objSystemInfo = CreateObject("ADSystemInfo")
set iper = createobject("CDO.Person")
strdname = objSystemInfo.DomainShortName
set conn = createobject("ADODB.Connection")
set com = createobject("ADODB.Command")
Set iAdRootDSE = GetObject("LDAP://RootDSE")
strNameingContext = iAdRootDSE.Get("defaultNamingContext")
Conn.Provider = "ADsDSOObject"
Conn.Open "ADs Provider"
Query = "<LDAP://" & strNameingContext & ">;(&(&(&(& (mailnickname=*)(!msExchHideFromAddressLists=TRUE)(|(&(objectCategory=person)
(objectClass=user)(msExchHomeServerName=*)) )))));samaccountname,displayname,distinguishedName;subtree"
Com.ActiveConnection = Conn
Com.CommandText = Query
Com.Properties("Page Size") = 1000
Set Rs = Com.Execute
vcardwrite = ""
While Not Rs.EOF
iper.datasource.open "LDAP://" & rs.fields("distinguishedName")
Set strm = iper.GetvCardStream
vcardwrite = vcardwrite & strm.readtext & vbcrlf
rs.movenext
Wend
Set fso = CreateObject("Scripting.FileSystemObject")
set wfile = fso.opentextfile("c:\temp\export.vcf",2,true)
wfile.writeline vcardwrite
wfile.close
set wfile = nothing

8 comments:

Anonymous said...

Excellent work

I am trying to get the GAL in Exchange 2003 out to a Public Folder .. could this scriptbe adapted to do just that?

Many Thanks
Sat

Glen said...

Yes if you can run the code locally on the exchange server where the public folder you want to export to is then something like this using CDOEX to create the appointment should work

Set objSystemInfo = CreateObject("ADSystemInfo")
set iper = createobject("CDO.Person")
strdname = objSystemInfo.DomainShortName
set conn = createobject("ADODB.Connection")
set com = createobject("ADODB.Command")
set conn1 = createobject("ADODB.Connection")
conn1.Provider = "ExOLEDB.Datasource"
conn1.Open "Http://servername/public/galexport/", "", "", -1
Set iAdRootDSE = GetObject("LDAP://RootDSE")
strNameingContext = iAdRootDSE.Get("defaultNamingContext")
Conn.Provider = "ADsDSOObject"
Conn.Open "ADs Provider"
Query = "<LDAP://" & strNameingContext & ">;(&(&(&(&
(mailnickname=*)(!msExchHideFromAddressLists=TRUE)(|(&(objectCategory=person)
(objectClass=user)(msExchHomeServerName=*))
)))));samaccountname,displayname,distinguishedName;subtree"
Com.ActiveConnection = Conn
Com.CommandText = Query
Com.Properties("Page Size") = 1000
Set Rs = Com.Execute
While Not Rs.EOF
iper.datasource.open "LDAP://" & rs.fields("distinguishedName")
wscript.echo rs.fields("samaccountname")
Set strm = iper.GetvCardStream
createcontractinpf(strm)
rs.movenext
Wend
Wscript.echo "Done"

function createcontractinpf(vcardstream)
on error resume next
set contobj1 = createobject("CDO.Person")
set stm1 = contobj1.getvcardstream()
vcard = vcardstream.readtext
stm1.type = 2
stm1.Charset = "x-ansi"
stm1.writetext vcard,0
stm1.Position = 0
stm1.type = 1
stm1.flush
contobj1.datasource.savetocontainer
"Http://servername/public/galexport/",conn1,3

end function

Kevin said...

Glen,
Your site is a wealth of information. Thanks!

I'm getting an error on my exchange server when I run the script. It's on the
Set strm = iper.GetvCardStream
line. it's returning:
Exception 0xc0000005 was generated at address 0x612752c7

Any ideas on where I should start trouble shooting this?

Thanks!

Anonymous said...

Hi Glen, Kevin,

Did you guys ever manage to work out the cause for the error Kevin reported above - "Exception 0xc0000005 was generated at address 0x612752c7."

TIA,
Karthik Reddy

karthik.reddy@sdgtechnology.com.au

Glen said...

I suspect its possible due to the version of CDOEX being used. Eg where are you trying to run the code (eg locally on the Exchange server or remotly) and what version of CDOEX are you using. If you going to use CDOEX to build an interop allways make sure you use the latest version from the lastest service pack from exchange. Several of the early version where quite buggy.

Roman Margold said...

I also experience this problem (i didn't use your script, but use very similar code written in C++). Everything works ok on a machine with Exchange Server 2003 SP1, but on machine with Exchange 2003 SP2 I always get this exception:

Exception 0xc0000005 was generated at address 0x612752c7

Maybe there's some other reason for this, but I'm pretty sure it's the SP2 which contains some bug :( unfortunatelly no Exchange update fixed this. So does anyone got around it? (I can still read every item and create the vCard at my own, what I do BTW, but I would rarther see it working in the easier way).

If anyone find a solution, please, let me know at roman[at]icewarp[dot]com

Glen said...

Its to do with a windows security patch. After that patch is applied its breaks this functionality on any windows machine. If it not happening on one server then that server is probably not fully patched. The only work around is really to build you own helper class to create the vcard or I've moved on to using Hcards instead which are easier to work with. I not sure if Microsoft are going to release a fix for the DLL its been broken for quite some time

Anonymous said...

This script no longer seems to work, can you update it ? I used this in the past and it was a great little tool

pjaneiro@hotmail.com
October 6th 2010