Server-side scripting
Adaxes allows you to customize business rules, scheduled tasks and custom commands with PowerShell scripts. By means of server-side scripting you can perform custom directory operations, query and update enterprise data sources (such as a database or a web service), validate and correct user input, etc. To configure a business rule, scheduled task, or custom command to execute a script, you can use either the Run a program or PowerShell script action or the If PowerShell script returns true condition.
Getting information about the target object
To get information about the directory object, on which the operation that triggered execution of the script is performed, you can use either value references or the TargetObject property of the $Context
variable.
Using value references
A value reference is a pattern of text that contains the name (or alias) of the object property it refers to. For example, value reference %description% refers to the Description property of a directory object. You can use value references in your script to get property values of the target object. Before executing a script, Adaxes replaces all the value references contained in the script with corresponding property values of the object on which the operation that triggered execution of the script is performed.
For example, say, you have the following script:
$title = "%title%"
$username = "%username%"
$dn = "%distinguishedName%"
After the replacement of the value references, the script will look as follows:
$title = "Sales Manager"
$username = "jsmith"
$dn = "CN=John Smith,CN=Users,DC=company,DC=com"
For more information about value references, see Value references.
Using $Context.TargetObject
$Context
is a predefined PowerShell variable of type ExecuteScriptContext that is available for use in PowerShell scripts executed by business rules, scheduled tasks, and custom commands. The TargetObject
property of the variable represents the directory object, on which the operation is performed.
You can use ADSI interfaces to get information about the target object using the $Context.TargetObject
property. The interfaces you can use depend on the type of the directory object on which the operation is performed. If the operation is performed on a user object (e.g. a business rule is executed after creation of a new user), $Context.TargetObject
will support the IADsUser interface; if the operation is performed on a group, you can use the IADsGroup interface, etc. All object types support the IADs interface. For more information, see Interfaces supported by directory objects.
The following script uses the IADsUser::IsAccountLocked property to determine whether the account of the user on which the operation is performed is locked out. If the account is locked out, the script sends an email notification to the manager of the user.
$locked = $Context.TargetObject.IsAccountLocked
if ($locked)
{
$managerDN = $Context.TargetObject.Manager
$manager = $Context.BindToObjectByDN($managerDN)
$text = "The account of %fullname% is locked out."
$Context.SendMail($manager.EmailAddress, "Account Locked", $text, $null)
}
Getting information about the initiator
To get information about the user who initiated the operation that triggered execution of the script, you can use the Initiator
property of the $Context
variable. The $Context.Initiator
property returns an object of the ExecuteScriptInitiatorInfo class. The UserAdsObject
property of this class is an ADSI object that represents the user account of the initiator. You can use IADs, IADsUser, and IAdmUser interfaces to get information about the initiator's user account.
The following example uses the IADs interface to get Employee ID of the user who initiated the operation. To get the host from which the user connected to the Adaxes service, the script uses the Host
property of the ExecuteScriptInitiatorInfo class.
$initiatorEmployeeID = $Context.Initiator.UserAdsObject.Get("employeeID")
$initiatorHost = $Context.Initiator.Host
If your script is executed by a scheduled task, the $Context.Initiator.UserAdsObject
property will represent the scheduled task object, and you will be able to use the IAdmScheduledTask interface to get information about the task.
Also, there are virtual properties of directory objects that you can use to get information about the initiator (e.g. adm-InitiatorFirstName, adm-InitiatorMobile). To use such properties in your script, you can use value references. The following example shows how to get information about the initiator by getting values of virtual object properties.
$dn = "%adm-InitiatorDN%" # DN of the initiator
$email = "%adm-InitiatorEmail%" # Email of the initiator
$fullName = "%adm-InitiatorFullName%" # Full name of the initiator
$managerEmail = "%adm-InitiatorManagerEmail%" # Email of the initiator's manager
Getting and modifying operation parameters
To access parameters of the operation that triggered execution of a script, you can use the Action
property of the $Context
variable. This property returns a .NET object that represents the operation. The interfaces you can use to access parameters of the operation depend on the type of the operation.
Accessing operation parameters in business rules
If your script is executed by a business rule, the $Context.Action
property will represent the operation that triggered execution of the business rule. The interfaces supported by the $Context.Action
property depend on the type of the operation. For example, if your business rule is triggered on user modification, the $Context.Action
property will expose the IAdmSetPropertiesAction interface, if your business rule is triggered on adding or removing a member from a group, the $Context.Action
property will support the IAdmChangeGroupMembershipAction interface.
Interfaces supported by each operation type
All operation types support the IAdmAction and IAdmAction2 interfaces.
The following example shows how to get the old and new passwords in a business rule that is executed when a user changes their password. To get the old password, the script uses the IAdmChangePasswordAction2::OldPassword property; to get the new password, the script uses the IAdmResetPasswordAction2::Password property.
$oldPassword = $Context.Action.OldPassword
$newPassword = $Context.Action.Password
If your business rule is executed before an operation is performed, your script can modify parameters of the operation. The following script changes the destination organizational unit in a business rule that is executed before moving directory objects. The script uses the IAdmCopyMoveAction::TargetContainer property to get and modify the destination organizational unit.
$destOU = $Context.Action.TargetContainer
if ($destOU.AdsPath.Contains("Marketing Users"))
{
$newDN = "OU=Marketing Department,DC=company,DC=com"
$newDestOU = $Context.BindToObjectByDN(newDN)
$Context.Action.TargetContainer = $newDestOU
}
Accessing parameters of a custom command
If your script is executed by a custom command, the $Context.Action
property will support the IAdmCustomCommandAction interface. The following example uses the IAdmCustomCommandAction::CustomCommandId property to get the unique identifier of the custom command being executed.
$commandID = $Context.Action.CustomCommandId
Accessing parameters of a scheduled task
If your script is executed by a scheduled task, the $Context.Action
property will support the IAdmScheduledTaskAction interface. The following example uses the IAdmScheduledTaskAction::ScheduledTaskName property to get the name of the scheduled task being executed.
$taskName = $Context.Action.ScheduledTaskName
Getting values entered by the user
If your script is executed by a business rule that is triggered on object creation or modification, you can get and modify the data entered by the user. For example, if your business rule is triggered on user modification, you can determine whether a specific property was modified during the operation, get the value entered for the property, and, if necessary, modify the value.
To determine whether a property is modified, you can use the IsPropertyModified method of the $Context
variable. To get the value entered for the property, call $Context.GetModifiedPropertyValue
for single-valued properties, and $Context.GetModifiedPropertyValues
for multi-valued properties.
if ($Context.IsPropertyModified("department"))
{
$modifiedValue = $Context.GetModifiedPropertyValue("department")
}
To get the old value of a property, you need to use $Context.TargetObject
in a business rule executed before object modification. The following example uses the IADs::Get method to obtain the old value of the Manager property.
if ($Context.IsPropertyModified("manager"))
{
$oldManager = $Context.TargetObject.Get("manager")
$newManager = $Context.GetModifiedPropertyValue("manager")
}
If your business rule is executed before object creation or modification, you can modify the values entered by the user. To modify a property value, call $Context.SetModifiedPropertyValue
. If you want to specify multiple values for a multi-valued property, call $Context.SetModifiedPropertyValues
.
if ($Context.IsPropertyModified("title"))
{
$modifiedValue = $Context.GetModifiedPropertyValue("title")
# Remove all leading and trailing white-space characters.
$newValue = $modifiedValue.Trim()
$Context.SetModifiedPropertyValue("title", $newValue)
}
To determine whether a user's password is changed during the operation, call the $Context.IsPasswordChanged
method. To get the new password, call $Context.GetNewPassword
. If your business rule is executed before the operation changing the password, you can modify the new password. To modify the password, call $Context.SetNewPassword
.
if ($Context.IsPasswordChanged())
{
$newPassword = $Context.GetNewPassword()
if ($newPassword.Length -lt 8)
{
$Context.SetNewPassword("%adm-RandomString,8%")
}
}
Managing directory objects
Apart from updating the directory object the main operation is carried out for, your script can also perform operations on other objects. To perform an operation on a directory object, first you need to bind to the object. The following examples show how to bind to different directory objects.
Example 1 – Bind to a directory object by DN
$group = $Context.BindToObjectByDN("CN=My Group,DC=company,DC=com")
Example 2 – Bind to a directory object by ADS path
$group = $Context.BindToObject("Adaxes://CN=My Group,DC=company,DC=com")
Example 3 – Bind to the parent organizational unit of the target object
$parentPath = $Context.TargetObject.Parent
$parentOU = $Context.BindToObject($parentPath)
Example 4 – Bind to a child object of a specific organizational unit
$ouPath = "Adaxes://OU=Sales,DC=company,DC=com"
$ouPathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $ouPath
$childPath = $ouPathObj.CreateChildPath("CN=Child Object")
$child = $Context.BindToObject($childPath)
Example 5 – Bind to the manager of the target user
$manager = $Context.BindToObjectByDN("%manager%")
For more information on how to bind to directory objects, see Binding to ADSI objects.
After you've bound to a directory object, you can use the appropriate ADSI interfaces to perform operations on the object. The interfaces you can use depend on the type of the directory object. All object types support the IADs and IAdmTop interfaces. User objects support the IADsUser interface, group objects support the IADsGroup interface.
Container objects, such as organizational units, support the IADsContainer interface that allows you to enumerate and manage their child objects. For more information, see Interfaces supported by directory objects.
The following code sample adds the user on which the operation is performed to the list of owners of each group managed by the operation initiator.
# Search for all groups managed by the initiator.
$searcher = $Context.BindToObjectByDN("%adm-InitiatorDomainDN%")
$searcher.Criteria = New-AdmCriteria "group" {directOwners -eq "%adm-InitiatorDN%"}
$searcher.SearchScope = "ADS_SCOPE_SUBTREE"
$results = $searcher.ExecuteSearch()
# Add the user as the owner of each group.
foreach ($result in $results.FetchAll())
{
$group = $Context.BindToObject($result.ADsPath)
$group.PutEx("ADS_PROPERTY_APPEND", "adm-ManagedByList", "%distinguishedName%")
$group.SetInfo()
}
$results.Dispose()
For more information on how to manage directory objects, see Writing ADSI scripts.
Managing Adaxes-specific objects
In the same way you manage directory objects, you can manage Adaxes configuration objects, such as security roles, property patterns, business units, and scheduled tasks. For example, a script executed by a business rule on user creation can automatically add new users to a specific business unit, or specify a scheduled task that will delete the newly created user after a period of time.
Each type of Adaxes configuration object is stored in a separate container. That is, there is a separate container for business rules, security roles, property patterns, etc. To create a new configuration object, you need to bind to the appropriate container and use the IADsContainer interface to create a child object. To get the ADS path of a container that stores Adaxes configuration objects, you need to call the GetWellKnownContainerPath method of the $Context
variable and provide the alias of the desired container as the first parameter of the method.
The following code sample gets the ADS path of the container where scheduled tasks are stored.
$path = $Context.GetWellKnownContainerPath("ScheduledTasks")
See also: Aliases for containers that store Adaxes configuration objects.
To modify or delete an existing configuration object, first you need to bind to the object. To bind to a configuration object, you need to build its ADS path. To build the ADS path of a configuration object, first you need to get the ADS path of its parent container. Then, based on the parent's ADS path, you can build the ADS path of the object you want.
The following code sample gets the ADS path of a specific business unit.
$businessUnitsPath = $Context.GetWellKnownContainerPath("BusinessUnits")
$pathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $businessUnitsPath
$unitPath = $pathObj.CreateChildPath("CN=My Unit")
Example 1 – Modify a business unit to include members of a specific group
The following script modifies the business unit called My Unit to include members of the group on which the operation that triggered execution of the script is performed. The script can be executed by a business rule triggered after group creation.
# Bind to the business unit.
$businessUnitsPath = $Context.GetWellKnownContainerPath("BusinessUnits")
$pathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $businessUnitsPath
$unitPath = $pathObj.CreateChildPath("CN=My Unit")
$unit = $Context.BindToObject($unitPath)
# Modify the business unit.
$membershipRules = $unit.GetMembershipRules()
$rule = $membershipRules.Create("ADM_BUSINESSUNITMEMBERSHIPTYPE_GROUP")
$rule.Group = $Context.TargetObject
$rule.IncludeDirectMembersOnly = $false
$membershipRules.Add($rule)
$unit.SetMembershipRules($membershipRules)
$unit.SetInfo()
Example 2 – Create a scheduled task that will delete a user after a period of time
The following script creates a scheduled task that deletes the user account on which the main operation is performed. The task runs after a specific time interval and gets deleted after execution. The script can be used in a business rule triggered after user creation.
$scheduledTaskParent = "User Deletion Tasks"
$scheduledTaskName = "User Deleter [%username%]"
$runAfterDays = 30
# Bind to the 'Scheduled Tasks\User Deletion Tasks' container.
$containerPath = $Context.GetWellKnownContainerPath("ScheduledTasks")
$pathObj = New-Object "Softerra.Adaxes.Adsi.AdsPath" $containerPath
$parentPath = $pathObj.CreateChildPath("CN=$scheduledTaskParent")
$parent = $Context.BindToObject($parentPath)
# Create a scheduled task.
$task = $parent.Create("adm-ScheduledTask", "CN=$scheduledTaskName")
$task.DeleteTaskAfterExecution = $true
$recurrence = $task.GetRecurrencePattern()
$recurrence.RecurrenceType = "ADM_RECURRENCEPATTERNTYPE_ONCE"
$recurrence.PatternStartDateTime =
[System.DateTime]::Now.AddDays($runAfterDays)
$task.SetRecurrencePattern($recurrence)
$task.ExecutionMoment = "ADM_BUSINESSRULEEXECMOMENT_AFTER"
$task.ObjectType = "user"
$task.OperationType = "dummy"
$task.SetInfo()
# Create a set of actions and conditions.
$actionsAndConditions = $task.ConditionedActions.Create()
$actionsAndConditions.ConditionsLogicalOperation =
"ADM_LOGICALOPERATION_AND"
$actionsAndConditions.SetInfo()
# Add 'Delete Object' action.
$deleteAction =
$actionsAndConditions.Actions.CreateEx("adm-DeleteObjectAction")
$deleteAction.ExecutionOptions = "ADM_ACTIONEXECUTIONOPTIONS_SYNC"
$action = $deleteAction.GetAction()
$action.DeleteSubtree = $true
$deleteAction.SetAction($action)
$deleteAction.SetInfo()
$actionsAndConditions.Actions.Add($deleteAction)
$task.ConditionedActions.Add($actionsAndConditions)
# Add the user account to the activity scope of the task.
$scope = $task.ActivityScopeItems.Create()
$scope.BaseObject = $Context.TargetObject
$scope.Exclude = $false
$scope.Type = "ADM_SCOPEBASEOBJECTTYPE_CONTAINER"
$scope.Inheritance = "ADS_SCOPE_BASE"
$scope.SetInfo()
$task.ActivityScopeItems.Add($scope)
For more information on how to manage Adaxes configuration objects, see the Managing Adaxes configuration section.
Terminating execution
Using the Cancel
method of the $Context
variable, you can terminate execution of the operation. The method accepts a string that explains the reason for the termination.
$Context.Cancel("Something is wrong here!")
If your script is executed by a business rule that is triggered before an operation is performed, the $Context.Cancel
method will cancel the execution of the operation. The method also cancels all business rule actions that are scheduled for execution after running the script.
If the `$Context.Cancel method is called in a custom command or scheduled task, it cancels all actions that follow the Run a program or PowerShell script action that executes your script.
Updating the Execution log
Each operation executed in Adaxes has an Execution Log that contains errors, warnings and information messages related to the operation. The Execution Log is displayed when an operation is completed, provided there are records in the log.
Using the LogMessage
method of the $Context
variable, you can add a message to the Execution Log. The first parameter of the method is the text of the message; the second parameter is the type of the message. The second parameter can take the following values: "Information"
, "Warning"
, and "Error"
.
$Context.LogMessage("My message", "Information")
You can also output exceptions into the Execution Log via the LogException
method. For example, this method can be used in a try
catch
block to catch terminating exceptions and output them into the log.
try
{
$description = $Context.TargetObject.Get("description")
}
catch
{
# Description is empty.
$Context.LogException($_.Exception)
}
Sending emails and SMS
Using the $Context.SendMail
and $Context.SendSms
methods, your script can send email notifications and SMS messages. To enable Adaxes to send email notifications, you need to configure the outgoing mail settings for your Adaxes service. To send SMS messages, you need to configure SMS settings for the service.
The following script sends an email message with information about the account of the user on which the operation is performed. The email is sent to the manager of the user.
$manager = $Context.BindToObjectByDN("%manager%")
$to = $manager.EmailAddress
$subject = "User Account Info [%username%]"
$bodyText =
@"
Name: %fullname%
Username: %username%
Department: %department%
Job title: %title%
Account expiration: %accountExpires%
"@
$bodyHtml = $null
$Context.SendMail($to, $subject, $bodyText, $bodyHtml)
The following script can be used in a business rule that is executed after resetting user passwords. The script sends an SMS message with the new password to the user whose password is reset.
$password =
@'
%unicodePwd%
'@
$smsText = "New password: $password"
$Context.SendSms("%mobile%", $smsText)
Submitting for approval
Using the SubmitForApproval
method of the $Context
variable you can request an approval for the operation in the context of which the script is executed. If the script is executed in a business rule, the method will submit a request to approve the operation that triggered the business rule. Please note that the method will work correctly only if the business rule is executed before the operation that you want to submit for approval. When the method is called in a custom command or scheduled task, all the actions following the one executing the script will be suspended and will be executed only after an approval is issued.
The first parameter of the SubmitForApproval
method accepts an array of distinguished names (DNs) of users and groups that will be able to approve or reject the request. For details on how to get the DN of a directory object, see Get the DN of a directory object. The rest four boolean parameters of the method determine options like whether the manager of the user who initiated the operation can approve or deny it. For more details, see
SubmitForApproval.
The following code sample submits an operation for approval to user John Smith.
$Context.SubmitForApproval(@("CN=John Smith,CN=Users,DC=example,DC=com"),
$false, $false, $false, $false)
The following code sample submits an operation for approval to a specific user, group, and the manager of the operation initiator.
$approvers = @(
"CN=John Smith,CN=Users,DC=example,DC=com",
"CN=Group,OU=Groups,DC=example,DC=com")
$Context.SubmitForApproval($approvers, $true, $false, $false, $false)
Using Adaxes cmdlets
Adaxes includes a PowerShell extension module that provides cmdlets for directory management. You can use the cmdlets in scripts executed by business rules, scheduled tasks and custom commands.
To use Adaxes cmdlets, you need to install Adaxes PowerShell module on the computer, where your Adaxes service is running. The module is installed with the same installation package as used to install Adaxes service.
To load the Adaxes PowerShell module into the PowerShell session, you need to use the Import-Module
cmdlet in your script. The name of the Adaxes PowerShell module is Adaxes.
Import-Module Adaxes
Adaxes cmdlets can communicate with your directory either via Adaxes or by directly accessing Active Directory domain controllers (bypassing the Adaxes service). When accessing the directory through Adaxes, the directory data modifications will be supplemented with data validation policies configured via property patterns, provisioning and deprovisioning rules defined by business rules. You will take advantage of workflow capabilities and reporting benefits of Adaxes.
To access your directory via the Adaxes service, pass the AdaxesService
parameter to the cmdlet.
Import-Module Adaxes
Get-AdmUser -Filter * -AdaxesService "localhost"
To specify the Active Directory domain where to perform an operation, you need to pass the -Server
parameter to the cmdlet. If this parameter is omitted, the operation will be performed in the domain where the Adaxes service is installed. To get the domain name of a directory object, you can use the $Context.GetObjectDomain
method. The following example executes a cmdlet in the domain of the object, the operation that triggered execution of the script is performed on.
Import-Module Adaxes
$domain = $Context.GetObjectDomain("%distinguishedName%")
Get-AdmGroup -Filter * -AdaxesService "localhost" -Server $domain
To specify on which directory object to perform an operation, you need to pass the -Identity
parameter to the cmdlet. The parameter takes the distinguished name (DN), canonical name, GUID, SID, or, if applicable, logon name of a particular directory object. The following code sample passes the DN of the object on which the operation is executed to the Identity parameter of a cmdlet.
Import-Module Adaxes
$identity = "%distinguishedName%"
$domain = $Context.GetObjectDomain("%distinguishedName%")
$moveToDN = "OU=Sales,DC=company,DC=com"
Move-AdmObject -Identity $identity -TargetPath $moveToDN -Server $domain
All cmdlets in the Adaxes PowerShell module have the Adm prefix on their nouns, for example, New-AdmUser or Enable-AdmAccount.
To get a list of all cmdlets contained in the Adaxes PowerShell module, you can use the Get-Command -Module Adaxes
command. To learn about what each cmdlet does, use the built-in PowerShell help documentation via the Get-Help
command, for example: Get-Help Get-AdmUser -Full
.
The following code sample removes the user, on which the operation is performed, from all groups that contain Sales in their name.
Import-Module Adaxes
$identity = "%distinguishedName%"
$domain = $Context.GetObjectDomain("%distinguishedName%")
# Get all the groups the user is a member of.
$groups = Get-AdmPrincipalGroupMembership $identity -Server $domain -AdaxesService localhost
foreach ($group in $groups)
{
if ($group.Name.Contains("Sales"))
{
Remove-AdmGroupMember $group -Member $identity -Server $domain`
-AdaxesService localhost -Confirm:$false
}
}
Running the script as a specific user
By default, scripts in Adaxes are executed using the credentials of the Adaxes service account. However, you might need to run the commands in the script from the security context of another account. To do this, you can specify the credentials of such an account in the Run As section of your Run a program or PowerShell script action. This achieves several things:
- Adaxes will impersonate the specified account for network operations, meaning its rights will be effective when performing such operations in the script.
- You will be able to retrieve the specified credentials from within the script in a secure fashion and avoid hardcoding them in plain text.
To access the credentials from the script, use the RunAs property of the predefined $Context variable:
# Get saved credentials.
$username = $Context.RunAs.UserName
$password = $Context.RunAs.Password | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object System.Management.Automation.PsCredential($username, $password)
# Use credentials.
$session = New-PSSession -ComputerName MyServer01 -Credential $credential
You can specify the credentials of any account, even if it doesn't belong to a domain managed by Adaxes.
Script examples
Example 1 – Getting data from a database
The following script can be executed by a business rule that is triggered before creation of a user account. The script queries a MS SQL database to get the department name and job title of a user. The script uses the value of the Employee ID property specified for the user being created as the user ID. Then the script updates the Department and Title properties of the directory user.
$databaseHost = "host.company.com"
$databaseName = "MyDatabase"
# Use the credentials of the default Adaxes administrator
# to connect to the database.
$databaseUsername = $null
$databasePassword = $null
# Get the employee ID of the user.
$employeeID = %employeeID%
# Connect to the database.
$connectionString = "Data Source=$databaseHost; Initial Catalog=$databaseName;"
if ($databaseUsername -eq $null)
{
$connectionString = $connectionString +
"Integrated Security=SSPI;"
}
else
{
$connectionString = $connectionString +
"User ID=$databaseUsername;Password=$databasePassword;"
}
$connection = New-Object "System.Data.SqlClient.SqlConnection" $connectionString
$connection.Open()
# Query the database for the user identified by the employee ID.
$command = $connection.CreateCommand()
$command.CommandText = "
SELECT Department, Title FROM UsersTable WHERE ID = $employeeID"
$reader = $command.ExecuteReader()
if ($reader.Read())
{
# Get the department name and job title from the database.
$department = $reader["Department"]
$jobTitle = $reader["Title"]
# Update properties of the user.
$Context.SetModifiedPropertyValue("department", $department)
$Context.SetModifiedPropertyValue("title", $jobTitle)
}
else
{
$Context.LogMessage("User with ID '$employeeID' not found in the database.", "Error")
}
$reader.Close()
$command.Dispose()
$connection.Close()
Example 2 – Calling web services
PowerShell cmdlet New-WebServiceProxy
can be used to create a proxy object for a given web service. Using the proxy object, you can use and manage the web service. The following script calls the DoSomething
method of a specific web service.
$service = New-WebServiceProxy -uri http://www.company.com/Service.asmx?WSDL
$param = "%username%"
$service.DoSomething($param)
Example 3 – Opening a URL
The following script uses the System.Net.WebClient class to retrieve
data at a given URL.
$userID = "%username%"
$url = "http://www.company.com/userInfo.aspx?userID=$userID"
$webClient = New-Object "System.Net.WebClient"
$webClient.Headers.Add("user-agent", "PowerShell Script")
$result = $webClient.DownloadString($url)
Example 4 – Generating and emailing a report
The following script generates an HTML report on inactive user accounts, and sends the report to the specified recipients. You can use scheduled tasks to schedule execution of the script.
Import-Module Adaxes
$email = "recipient@company.com"
$inactivityDurationThreshold = "30" # Days
$baseDN = "DC=company,DC=com"
$domain = $Context.GetObjectDomain($baseDN)
function GetObjectDisplayName($objectDN)
{
$objectPath = New-Object -TypeName "Softerra.Adaxes.Adsi.AdsPath"`
-ArgumentList @($null, $objectDN)
return $Context.GetDisplayNameFromAdsPath($objectPath, $true)
}
$htmlBuilder = New-Object "System.Text.StringBuilder"
$htmlBuilder.append("<html><head>")
$htmlBuilder.append("<meta http-equiv=""Content-Type""`
content=""text/html charset=UTF-8""></head>")
$htmlBuilder.append("<body>")
$baseObjectDisplayName = GetObjectDisplayName $baseDN
$htmlBuilder.appendFormat(
"<p>Inactive Users (<b>{0}</b>)</p>",
$baseObjectDisplayName)
$htmlBuilder.append("<table width=""100%%"" border=""1"">")
$htmlBuilder.append("<tr>")
$htmlBuilder.append("<th>User Name</th>
<th>Parent</th><th>Last Logon</th>")
$htmlBuilder.append("</tr>")
# Find inactive users
$users = Search-AdmAccount -AccountInactive `
-TimeSpan $inactivityDurationThreshold `
-SearchBase $baseDN -UsersOnly `
-Server $domain -AdaxesService localhost
if ($users)
{
foreach ($user in $users)
{
$user = Get-AdmUser $user -Properties "LastLogonDate"`
-Server $domain -AdaxesService "localhost"
$userDN = New-Object "Softerra.Adaxes.Ldap.DN" $user.DistinguishedName
$parentDisplayName = GetObjectDisplayName $userDN.Parent.ToString()
$htmlBuilder.append("<tr>")
$htmlBuilder.appendFormat("<td>{0}</td>", $user.Name)
$htmlBuilder.appendFormat("<td>{0}</td>", $parentDisplayName)
$htmlBuilder.appendFormat("<td>{0}</td>", $user.LastLogonDate)
$htmlBuilder.append("</tr>")
}
}
$htmlBuilder.append("</table>")
$htmlBuilder.append("</body></html>")
$Context.SendMail($email, "[AD Report] Inactive Users", $null,
$htmlBuilder.ToString())