I need to have an Active Directory Shadow Groups (aka Active Directory Dynamic Group), based on several DN's.
I've searched high and low for a simple tool that would allow me to do this, and finally found Dan Holme's excellent script (quoted below) at http://kb.caresys.com.cn/4052785/need-script-add-all-accounts-active-directory-security-group (and a few other places)
I also found several PowerShell scripts, but they all appear to have much harder dependencies and I need a tool that's as stand-alone as possible. They also all have the same problem as I'm faced with here.
The Group_Shadow.vbs script performs exactly what I need with one exception:
I need to be able to specify the AD's Host, port number and credentials (login and password).
The script assumes that "LDAP://" is pointing to the correct AD, and I guess the AD Credentials are derived from the user running the script?
I did find a hint about how to set the host name and password, by changing the "LDAP://" string into "LDAP://LDAP_HOST:LDAP_PORT/".
That seems pretty easy to implement - but there were a few comments stating it didn't work...
I also found a hint about setting the credentials:
Dim LDAP ' As IADsOpenDSObject
Set LDAP = GetObject("LDAP:")
Set obj = LDAP.OpenDSObject("LDAP://", "domain\name", "password", ADS_USE_ENCRYPTION OR ADS_SECURE_AUTHENTICATION)
This appear to be the hard part (being totally novice in both the VBScript and Active Directory world), and I simply can't figure out how to combine to two.
I hope the community can help me out, either by assisting fixing this script or by pointing to a different solution.
Thanks in advance!
The Script:
'==========================================================================
'
' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 2007
'
' NAME: Group_Shadow.vbs
'
' AUTHOR: Dan Holme , Intelliem
' DATE : 12/12/2007
'
' USAGE:
' cscript.exe Group_Shadow.vbs
'
' Dynamically updates the membership of a group
' to match the objects returned from an Active Directory query
'
' See the Windows Administration Resource Kit for documentation
'
' Neither Microsoft nor Intelliem guarantee the performance
' of scripts, scripting examples or tools.
'
' See www.intelliem.com/resourcekit for updates to this script
'
' (c) 2007 Intelliem, Inc
'==========================================================================
Option Explicit
Dim sDomainDN
Dim sGroupSAMAccountName
Dim aSearchOUs
Dim sQuery
'==========================================================================
' CONFIGURATION BLOCK
' Domain's DN
sDomainDN = "dc=domain,dc=local"
' sAMAccountName of shadow group
sGroupSAMAccountName = "Security Group"
' An array of one or more OUs to search
aSearchOUs = Array("ou=Something,dc=domain,dc=local")
' LDAP query that will be run in each OU
sQuery = " (&(objectCategory=computer)(name=GA*));distinguishedName;subtree"
'==========================================================================
' Create dictionaries
Dim dResults
Set dResults = CreateObject("Scripting.Dictionary")
dResults.CompareMode = vbTextCompare ' Case INsensitive
Dim dTargetMembership
Set dTargetMembership = CreateObject("Scripting.Dictionary")
dTargetMembership.CompareMode = vbTextCompare ' Case INsensitive
Dim dCurrentMembership
Set dCurrentMembership = CreateObject("Scripting.Dictionary")
dCurrentMembership.CompareMode = vbTextCompare ' Case INsensitive
Dim dMembershipChanges
Set dMembershipChanges = CreateObject("Scripting.Dictionary")
dMembershipChanges.CompareMode = vbTextCompare ' Case INsensitive
' Perform LDAP searches, adding to final list stored in dTargetMembership
Dim sSearchOU
Dim sLDAPQuery
For Each sSearchOU In aSearchOUs
sLDAPQuery = "<LDAP://" & sSearchOU & ">;" & sQuery
Set dResults = AD_Search_Dictionary(sLDAPQuery)
Call DictionaryAppend(dResults, dTargetMembership)
Next
' Locate group
Dim sGroupADsPath
Dim oGroup
sGroupADsPath = ADObject_Find_Generic(sGroupSAMAccountName, sDomainDN)
If sGroupADsPath = "" Then
' Error handling: group not found
WScript.Quit
End If
Set oGroup = GetObject(sGroupADsPath)
' Get members and store in dictionary
Dim aMembers
aMembers = oGroup.GetEx("member")
Set dCurrentMembership = ArrayToDictionary(aMembers)
' Calculate the "delta" between the current and desired state
Set dMembershipChanges = Dictionary_Transform(dCurrentMembership, dTargetMembership)
' Make the membership changes based on the transform dictionary's instructions
Dim sMember
For Each sMember In dMembershipChanges
If UCase(dMembershipChanges.Item(sMember)) = "ADD" Then
oGroup.Add "LDAP://" & sMember
End If
If UCase(dMembershipChanges.Item(sMember)) = "DELETE" Then
oGroup.Remove "LDAP://" & sMember
End If
Next
WScript.Quit
' ======================
' FUNCTIONS FROM LIBRARY
' ======================
' #region Dictionary routines
Function ArrayToDictionary(ByRef aArray)
' Converts a one-dimensional array into a dictionary.
' Assumes elements in array are unique
Dim dDic
Dim aElement
Set dDic = CreateObject("Scripting.Dictionary")
dDic.CompareMode = vbTextCompare ' Case INsensitive
On Error Resume Next ' trap duplicate array elements
For Each aElement In aArray
dDic.Add aElement, 0
Next
On Error GoTo 0
Set ArrayToDictionary = dDic
End Function
Sub DictionaryAppend(ByRef dNewElements, ByRef dDictionary)
' Appends the elements of dNewElements to dDictionary
Dim sKey
On Error Resume Next ' trap duplicate array elements
For Each sKey In dNewElements.keys
dDictionary.Add sKey, dNewElements.Item(sKey)
Next
On Error GoTo 0
End Sub
Function Dictionary_Transform(ByVal dOriginal, ByVal dFinal)
' Retunrs a dictionary with a list of update operations required
' so that dOriginal is transformed to dFinal
Dim dTransform, sKey
Set dTransform = CreateObject("Scripting.Dictionary")
dTransform.CompareMode = vbTextCompare ' Case INsensitive
For Each sKey In dFinal.Keys
If Not dOriginal.Exists(sKey) Then
dTransform.Add sKey, "ADD"
End If
Next
For Each sKey In dOriginal.Keys
If Not dFinal.Exists(sKey) Then
dTransform.Add sKey, "DELETE"
End If
Next
Set Dictionary_Transform = dTransform
End Function
' #endregion
' #region Active Directory object find routines
Function ADObject_Find_Generic(ByVal sObject, ByVal sSearchDN)
' Version 071130
' Takes any input (name, DN, or ADsPath) of a user, computer, or group, and
' returns the ADsPath of the object as a way of validating that the object exists
'
' INPUTS: sObject DN or ADsPath to an object
' sAMAccountName (pre-Windows 2000 logon name) of a user or group
' computer name of a computer
' sSearchDN the DN within which to search (often, the DN of the domain, e.g. dc=contoso, dc=com)
'
' RETURNS: ADObject_Find_Generic ADsPath (LDAP://...) of the object
' blank if object was not found
'
' NOTES: ASSUMPTION: computers, users & groups have unique names. See note inline.
'
' REQUIRES AD_Search_Array routine
' AD_Search_RS routine
' ADObject_Validate routine
Dim aResults, sLDAPQuery
Select Case ADObject_NameType(sObject)
Case ""
ADObject_Find_Generic = ""
Case "adspath"
ADObject_Find_Generic = ADObject_Validate(sObject)
Case "distinguishedname"
ADObject_Find_Generic = ADObject_Validate("LDAP://" & sObject)
Case "name"
' Assumption: No computer has the same name as a user's or group's sAMAccountName
' otherwise, this query will return more than one result
sLDAPQuery = "<LDAP://" & sSearchDN & ">;" & _
"(|(samAccountName=" & sObject & ")(samAccountName=" & sObject & "$));" & _
"aDSPath;subtree"
aResults = AD_Search_Array (sLDAPQuery)
If Ubound(aResults) = -1 Then
ADObject_Find_Generic = ""
Else
ADObject_Find_Generic = aResults(0)
End If
End Select
End Function
Function ADObject_NameType(ByVal sObjectName)
' Version 071204
' Evaluates sObjectName to determine what type of name it is
' Returns ADObject_NameType adspath
' distinguishedname
' name
' blank if sObjectName = ""
Dim sNameType
If Len(sObjectName) = 0 Then
sNameType = ""
ElseIf Len(sObjectName) < 3 Then
' can't be a DN or an ADsPath - must be a name
sNameType = "name"
ElseIf Ucase(Left(sObjectName,3)) = "CN=" Then
' is a DN
sNameType = "distinguishedname"
ElseIf Len(sObjectName) < 8 Then
' too short to be an ADsPath and isn't a DN, so it must be a name
sNameType = "name"
ElseIf UCase(Left(sObjectName, 7)) = "LDAP://" Then
' is already an ADsPath
sNameType = "adspath"
Else
' must be a name
sNameType = "name"
End If
ADObject_NameType = sNameType
End Function
Function ADObject_Validate(ByVal sObjectADsPath)
' Version 071122
' Returns ADsPath of object as a way of validating that the object exists
'
' INPUTS: sObjectADsPath ADsPath of object to test
' RETURNS: ADObject_Validate Path of object (if it exists) or blank
Dim oObject
On Error Resume Next
Set oObject = GetObject(sObjectADsPath)
If Err.Number <> 0 Then
ADObject_Validate = ""
Err
Turns out there are two answers to take note of in regard to "LDAP://" credentials.
First, specifically to the script I posted, I simply had to open my eyes!
Almost the last line of the script there were already options to add the credentials:
oConnection.Open "", vbNullString, vbNullString
Simply had to be correctly populated:
oConnection.Open "", "username", "password"
Second, a more general description was already provided by #Harvey Kwok in this SO answer: Secure LDAP object manipulation with VBscript using alternate credentials
Related
I want to change the code below, so that it executes the sas guide project (.egp) and changes the parameter value according to the values of the array. (The idea is to open the project, run to the value of the array (0), close the project; open the project, run to the value array (1); ... until the array (n)).
But it executes only for the first value of the array, not the sequence for the other values. What's the mistake?
I added the line (for t = 0 to UBound (id)) and put (Next) before app.Quit
Dim t
Dim id
id=Array("111111111","22222222","33333333")
'-----------------------------------
' The name and location of the project file that will be opened and run by this script.
prjName = "C:\SAS\EG\Samples\XXXXX.egp" 'Project Name
for t = 0 to UBound(id)
And at the end of the code
Next
app.Quit
The full code
Option Explicit
'----------------------------------------------------------------
'AutomationPrompts.vbs
'This example program demonstrates how to use the 4.2 SAS Enterprise Guide
'automation interface to access and modify the prompts for a project and a stored
'process within that project. The project is opened and the project prompt names
'and values are displayed to the user. Subsequently, the stored processes within
'the project are opened and their prompt names and values are then displayed.
'
'The prompt value for the stored process is changed to 'M' (for male), the project
'is saved then run.
'
'The project is called AutomationwithPrompts.egp and the prjName variable should be
'modified to reflect the location of this proejct on the machine that is running
'this script.
'----------------------------------------------------------------
'--------------
'Declare the variables that will be used in the program
'--------------
Dim app
Dim prjName
Dim prjObject
Dim parmList
Dim parm
Dim spList
Dim sp
Dim spParamList
Dim spParam
Dim spParamName
Dim spParamValue
Dim n
Dim i
Dim t
Dim id
id=Array("111111111","22222222","33333333")
'-----------------------------------
' The name and location of the project file that will be opened and run by this script.
prjName = "C:\SAS\EG\Samples\XXXXX.egp" 'Project Name
for t = 0 to UBound(id)
' Start the app and open the project
Set app = CreateObject("SASEGObjectModel.Application.8.1")
Set prjObject = app.Open(prjName,"")
'---------------------------------
'Begin processing the project
'---------------------------------
' Discover the parameters for the project
Set parmList = prjObject.Parameters
Wscript.Echo "Project has " & parmList.Count & " parameters."
' Get the default value from the first parameter
Set parm = parmList.Item(0)
WScript.Echo parm.Name & " parameter has default value of " & parm.DefaultValue
' Change the value of the parameter to 'M' and display the new value.
parm.Value = id(t)
WScript.Echo parm.Name & " parameter has been set to value of " & parm.Value
'-------------------------------
'Begin processing the stored process
'-------------------------------
Set spList = prjObject.StoredProcessCollection
' Get the number of parameters for the store process
Wscript.Echo "StoredProcess has " & spList.Count & " parameters."
' Cycle through the list of stored processes and the parameters for each of them.
for n=0 to (spList.Count - 1)
Set sp = spList.Item(n)
' Get the list of parameters
Set spParamList = sp.Parameters
' Process each stored process parameter
for i=0 to (spParamList.Count - 1)
Set spParam = spParamList.Item(i)
' Get the name and default value for the parameter
spParamName = spParam.Name
spParamValue = spParam.DefaultValue
' Display the parameter information to the user
WScript.Echo spParamName & " parameter has default value of " & spParamValue
' Change the value of the parameter
spParam.Value = id(t)
' Display the modified value
WScript.Echo spParamName & " parameter has been set to value of " & spParam.Value
' Save the project with the updated stored process
prjObject.Save
Next
Next
' Run the new project
prjObject.Run
' Make sure the project is saved after it has been run.
prjObject.Save
' Close the project and application.
prjObject.Close
Next
app.Quit
I got it, the final code is below.
Option Explicit
'--------------
Dim app
Dim prjName
Dim prjObject
Dim parmList
Dim parm
Dim n
Dim i
Dim t
Dim id
id=Array("111111111","22222222","33333333")
'-----------------------------------
' The name and location of the project file that will be opened and run by this script.
prjName = "C:\SAS\EG\Samples\XXXXX.egp" 'Project Name
' Start the app and open the project
Set app = CreateObject("SASEGObjectModel.Application.8.1")
Set prjObject = app.Open(prjName,"")
'---------------------------------
'Begin processing the project
'---------------------------------
for t = 0 to UBound(id)
' Discover the parameters for the project
Set parmList = prjObject.Parameters
Wscript.Echo "Project has " & parmList.Count & " parameters."
' Get the default value from the first parameter
Set parm = parmList.Item(0)
WScript.Echo parm.Name & " parameter has default value of " & parm.DefaultValue
' Change the value of the parameter and display the new value.
parm.Value = id(t)
WScript.Echo parm.Name & " parameter has been set to value of " & parm.Value
' Run the new project
prjObject.Run
WScript.Sleep 5000
Next
' Make sure the project is saved after it has been run.
prjObject.Save
' Close the project and application.
prjObject.Close
app.Quit
How to add multiple email addresses in CC list for VB Script send mail.
option explicit
' --------------------------------------------------------------------------
' -- Create Lotus Notes email (and add attachment) using VB Script
' --
' -- Version 1.01
' --
' -- Created by : Michael Green
' -- migreen#westpac.com.au
' --
' -- Based on in-complete/partially working script from :
' -- http://en.allexperts.com/q/Using-Lotus-Notes-1427/Creating-LotusNotes-email-using-1.htm
' --
' -- Created : 06/10/2009
' -- Last Updated: 07/10/2009
' --------------------------------------------------------------------------
Dim oSession ' AS NotesSession
Dim strServer
Dim strUserName
Dim strMailDbName
Dim oCurrentMailDb ' as NOTESDATABASE
Dim oMailDoc ' as NOTESDOCUMENT
Dim ortItem ' as NOTESRICHTEXTITEM
Dim ortAttacment ' as NOTESRICHTEXTITEM
Dim oEmbedObject ' as ????
dim cstrAttachment
Dim blAttachment
cstrAttachment = "c:\Temp\Telstra.xls"
blAttachment = True
' Start a session to notes
wscript.echo "## Connecting to Lotus Notes session..."
Set oSession = CreateObject("Notes.NotesSession")
wscript.echo("NotesVersion : " & oSession.NotesVersion)
wscript.echo("NotesBuildVersion: " & oSession.NotesBuildVersion)
wscript.echo("UserName : " & oSession.UserName)
wscript.echo("EffectiveUserName: " & oSession.EffectiveUserName)
wscript.echo "## GetEnvironmentString..."
strServer = oSession.GetEnvironmentString("MailServer",True)
wscript.echo("Server :" & strServer)
' eg. CN=Michael V Green/OU=CORPAU/OU=WBCAU/O=WBG
strUserName = oSession.UserName
strMailDbName = Left(strUserName, 1) & Right(strUserName, (Len(strUserName) - InStr(1, strUserName, "")))&".nsf"
wscript.echo("MailDbName :" & strMailDbName)
wscript.echo "## Getting current Notes database..."
' open the mail database in Notes
set oCurrentMailDb = oSession.CurrentDatabase
wscript.echo("fileName:" & oCurrentMailDb.fileName)
wscript.echo("filePath:" & oCurrentMailDb.filePath)
wscript.echo("server:" & oCurrentMailDb.server)
wscript.echo("Title:" & oCurrentMailDb.Title)
If oCurrentMailDb.IsOpen = True Then
' Already open for mail
wscript.echo "## Lotus Notes mail database is already open !"
Else
wscript.echo "## Opening Lotus Notes mail database..."
oCurrentMailDb.OPENMAIL
End If
' Create a document in the back end
Set oMailDoc = oCurrentMailDb.CREATEDOCUMENT
' Set the form name to memo
OMailDoc.form = "Memo"
with oMailDoc
.SendTo = "migreen#westpac.com.au"
.BlindCopyTo = "mgreen#ozemail.com.au"
.CopyTo = "migreen#westpac.com.au"
.Subject = "This is a test of VB scripting driving Lotus Notes 7 "
end with
set ortItem = oMaildoc.CREATERICHTEXTITEM("Body")
with ortItem
.AppendText("Test of RTF Item append")
.AddNewLine(2)
.AppendText("Signature")
End With
' Create additional Rich Text item and attach it
If blAttachment Then
Set ortAttacment = oMailDoc.CREATERICHTEXTITEM("Attachment")
' Function EMBEDOBJECT(ByVal TYPE As Short, ByVal CLASS As String, ByVal SOURCE As String, Optional ByVal OBJECTNAME As Object = Nothing) As Object
' Member of lotus.NOTESRICHTEXTITEM
Set oEmbedObject = ortAttacment.EMBEDOBJECT(1454, "", cstrAttachment, "Attachment")
End If
wscript.echo "## Sending email..."
with oMailDoc
.PostedDate = Now()
.SAVEMESSAGEONSEND = "True"
.send(false)
end with
wscript.echo "## Sent !"
' close objects
set oMailDoc = nothing
set oCurrentMailDb = nothing
set oSession = nothing
Just use an array to set the values
with oMailDoc
.SendTo = Array( "migreen#westpac.com.au", "mgreen#westpac.com.au", "green#westpac.com.au" )
.BlindCopyTo = "mgreen#ozemail.com.au"
.CopyTo = "migreen#westpac.com.au"
.Subject = "This is a test of VB scripting driving Lotus Notes 7 "
end with
Originally I did not want to comment on the quality of the copied code at all. But the discussion with Lankymart made me think, it would be good to comment on it.
Set oSession = CreateObject("Notes.NotesSession")
This line creates an OLE interface to a running Notes- Client. If client does not run, then it will be started. If you used Set oSession = CreateObject("Lotus.NotesSession") then it would have been a COM- Object you get. Be aware, that Some OLE- Methods do not work in COM and vice versa. e.g. oCurrentMailDb.OPENMAIL is OLE, while the same thing in COM would be oCurrentMailDb.OpenMailDatabase()
' eg. CN=Michael V Green/OU=CORPAU/OU=WBCAU/O=WBG
strUserName = oSession.UserName
strMailDbName = Left(strUserName, 1) & Right(strUserName, (Len(strUserName) - InStr(1, strUserName, "")))&".nsf"
Getting the users' mailfile is completely nonsense, the code will get everything but a correct filename. As the variable is not used at all - can be forgotten
set oCurrentMailDb = oSession.CurrentDatabase
Just gets the database that is currently open in the client. If no database is open, an error will be thrown in the next wscript.echo- line, and we will never get to the next lines where it checks, if a database is open...
The problem with this line: Sending mails is possible from ANY database in Lotus Notes. If the database that is open e.g. is the personal addressbook, then the mail will be saved and sent from there (and you will never find it in the Sent- View of your mailfile.
I would suggest to use OPENMAIL first and only do a fallback to the currently open database if that fails.
The rest of the code seems to be OK.
Create an array of email address strings and set CopyTo to that array:
Dim addresses (2)
addresses(0) = "EMAIL"
addresses(1) = "EMAIL"
addresses(2) = "EMAIL"
with oMailDoc
.SendTo = "migreen#westpac.com.au"
.BlindCopyTo = "mgreen#ozemail.com.au"
.CopyTo = addresses
.Subject = "This is a test of VB scripting driving Lotus Notes 7 "
end with
how I should proceed to get all active PSOs on a specific domain.
I know that this domain contains the following PSOs:
CN=PSO-Standard
CN=PSO-Sensitive
But I must create a report to display them so I must load them in dynamic way.
I guess there is a kind of filter to get the PSO container and then loop through its recordset.
e.g.
.filter = "(CN=Password Settings Container)"
.attributes = "msDS-PasswordSettingsContainer"
thx in advance.
using classic asp with vbscript
The filter you are looking for is : "(objectClass=msDS-PasswordSettings)"
Here is a sample Vbscript to test :
'==========================================================================
'
' NAME: SearchPSO.vbs
'
' AUTHOR: JPB , Silogix
' DATE : 29/06/2011
'
' COMMENT:
'
'==========================================================================
Option Explicit
Dim machine
Dim oRootDSE ' Root Directory Service Specific Entry
Dim DomainContainer ' The Roor of the Domain
Dim conn ' ADODB connexion
Dim ldapBase ' Base DN of the search
Dim ldapFilter ' Search filter
Dim ldapAttributes ' Attributs to get
Dim ldapScope ' Search scope
Dim ldapStr ' String to execute
Dim rs ' Search result
Dim f '
Dim oADSI ' ADSI access
' ADODB cooking
machine = "WM2008R2ENT"
Set oRootDSE = GetObject("LDAP://"&machine&"/"&"RootDSE")
DomainContainer = oRootDSE.Get("defaultNamingContext")
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADSDSOObject"
conn.Properties("User ID") = "jpb"
conn.Properties("Password") = "test.2011"
conn.Properties("Encrypt Password") = True
conn.Open "ADs Provider"
' Building the request to exécute
ldapBase = "<LDAP://" & machine &"/"& DomainContainer & ">"
ldapFilter = "(objectClass=msDS-PasswordSettings)"
ldapAttributes = "cn,msDS-LockoutDuration,msDS-MaximumPasswordAge"
ldapScope = "subtree"
ldapStr = ldapBase&";"&ldapFilter&";"&ldapAttributes&";"&ldapScope
' Search request execution
Set rs = conn.Execute(ldapStr)
' Restitution du résultat
While Not rs.EOF
'For each f in rs.Fields
' WScript.Echo f.Name & ":" & f.Value
'Next
WScript.Echo rs.Fields("cn").Value
rs.MoveNext
Wend
Ok, so it's not, but...
so this is a quick script I found on the internet which runs on my Exchange server and dumps a list of email addresses that I can use for recipient validation on a spam filter:
' Export all valid recipients (= proxyAddresses) into a
' file virtual.txt
'
' Ferdinand Hoffmann & Patrick Koetter
' 20021100901
' Shamelessly stolen from
' http://www.microsoft.com/windows2000/techinfo/ \
' planning/activedirectory/bulksteps.asp
'Global variables
Dim Container
Dim OutPutFile
Dim FileSystem
'Initialize global variables
Set FileSystem = WScript.CreateObject("Scripting.FileSystemObject")
Set OutPutFile = FileSystem.CreateTextFile("virtual.txt", True)
Set Container=GetObject("LDAP://CN=Users,DC=office,DC=example,DC=com")
'Enumerate Container
EnumerateUsers Container
'Clean up
OutPutFile.Close
Set FileSystem = Nothing
Set Container = Nothing
'Say Finished when your done
WScript.Echo "Finished"
WScript.Quit(0)
'List all Users
Sub EnumerateUsers(Cont)
Dim User
'Go through all Users and select them
For Each User In Cont
Select Case LCase(User.Class)
'If you find Users
Case "user"
'Select all proxyAddresses
Dim Alias
If Not IsEmpty(User.proxyAddresses) Then
For Each Alias in User.proxyAddresses
OutPutFile.WriteLine "alias: " & Alias
'WScript.Echo Alias
Next
End If
Case "organizationalunit" , "container"
EnumerateUsers User
End Select
Next
End Sub
The catch is that the list of recipients comes back like this:
smtp:user#local.lan
SMTP:user#publicdomain.com
x400:c=US;a= ;p=local;o=Exchange;s=lastname;g=firstname;
smtp:postmaster#publicdomain.com
smtp:webmaster#publicdomain.com
The spam filter has an import scrip that only imports lines with "smtp" or "SMTP" prefixed so the x400 isn't an issue. What is an issue is that I don't want the VBscript exporting the "user#local.lan" address. I've tried this:
'List all Users
Sub EnumerateUsers(Cont)
Dim User
'Go through all Users and select them
For Each User In Cont
Select Case LCase(User.Class)
'If you find Users
Case "user"
'Select all proxyAddresses
Dim Alias
If Not IsEmpty(User.proxyAddresses) Then
For Each Alias in User.proxyAddresses
If Not Alias = "*.lan" Then
OutPutFile.WriteLine "alias: " & Alias
WScript.Echo Alias
End If
Next
End If
Case "organizationalunit" , "container"
EnumerateUsers User
End Select
Next
End Sub
But, that doesn't do anything. I've tried matching for the public domain (If Alias = "publicdomain" Then) but that didn't produce any results.
So, how do I filter the output so I only get addresses ont he public domain?
Replace
If Not Alias = "*.lan"
with
If Right(Alias, 4) <> ".lan"
(It can be done with regular expressions but it's Friday and I'm tired!)
You could use a regular expression to filter out lines that don't match your criteria. Something like the following.
smtp:.*#publicdomain\.com
Alternatively you could also tweak your LDAP query to only return users of a certain OU. Is there an AD group that only users with exchange accounts belong in?
Here's the VBS for RegEx matching...
Dim s : s = "smtp:user#local.lan" & VBCRLF & _
"SMTP:user#publicdomain.com" & VBCRLF & _
"x400:c=US;a= ;p=local;o=Exchange;s=lastname;g=firstname;" & VBCRLF & _
"smtp:postmaster#publicdomain.com" & VBCRLF & _
"smtp:webmaster#publicdomain.com"
Dim ex : ex = "smtp:.*#publicdomain\.com"
Dim oRE: Set oRE = New RegExp
oRE.IgnoreCase = True
oRE.Global = True
oRE.Pattern = ex
Dim matches : Set matches = oRE.Execute(s)
For Each match In matches
WScript.Echo match.Value
Next
Following the howto Extending the Active Directory Schema To Track Custom Info I'm able to setup a single-value schema attribute that is easily changeable via a context menu in ADUC. Multi-value schema attributes get considerably more complicated. Say (for the sake of argument) my value is "Projects" and each user may be a list as many projects as necessary.
Following is a sad little script that will set Project to a single value:
Dim oproject
Dim oUser1
Dim temp1
Set oproject = Wscript.Arguments
Set oUser1 = GetObject(oproject(0))
temp1 = InputBox("Project: " & oUser1.project & vbCRLF & vbCRLF & "Project")
if temp1 <> "" then oUser1.Put "project",temp1
oUser1.SetInfo
Set oUser1 = Nothing
Set oproject = Nothing
Set temp1 = Nothing
WScript.Quit
How can I modify this to allow, assign, and modify multiple values?
I gave up on an elegant UI and just went with the semicolon delimited list. Here's the code if anyone cares:
Dim objProject
Dim objUser
Dim temp1, title, message, default
Dim projects
title = "Projects"
Set objProject = Wscript.Arguments
Set objUser = GetObject(objProject(0))
'Find our current projects
projects = objUser.projects
If Not isArray(projects) Then
projects = Array(projects)
End If
'Setup our message box
message = "Semicolon-delimited list of Projects"
default = arrayToStr(projects)
temp1 = InputBox(message, title, default)
'catch cancels
if IsEmpty(temp1) Then
WScript.Quit
End If
' update our data
projects = strToArray(temp1)
objUser.Put "projects",projects
objUser.SetInfo
'Clean up and quit
Set projects = Nothing
Set objUser = Nothing
Set objProject = Nothing
Set temp1 = Nothing
Set title = Nothing
Set message = Nothing
Set default = Nothing
WScript.Quit
'Functions
Function strToArray(s)
Dim a
Dim token
' discard blank entries
For Each token in split(s, ";")
token = trim(token)
If token <> "" Then
If isEmpty(a) Then
a = token
Else
a = a & ";" & token
End If
End If
Next
' return array
strToArray = split(a, ";")
End Function
Function arrayToStr(a)
Dim s
Dim token
For Each token in a
If isEmpty(s) Then
s = token
Else
s = s & ";" & token
End If
Next
' return string
arrayToStr = s
End Function