Using PowerShell to start Run Profiles
Thanks to this powershell script, you can easily automatize the execution of run profiles for FIM management agents.You just have to adapt the PARAMETERS section to your needs.Here is a screenshot: And the source code:
# @author: Fabien Duchene
# @mail: fabien.duchene1 **at** googlemail.com
############
# PARAMETERS
############
$params_ComputerName = "." # "." is the current computer
$params_delayBetweenExecs = 30 #delay between each execution, in seconds
$params_numOfExecs = 0 #Number of executions 0 for infinite
$params_runProfilesOrder =
@(
@{
type="Forefront Identity Management (FIM)";
profilesToRun=@("Full Import";"Full Synchronization");
};
@{
type="Active Directory";
profilesToRun=@("Full Import";"Full Synchronization";"Export");
};
);
############
# FUNCTIONS
############
$line = "-----------------------------"
function Write-Output-Banner([string]$msg) {
Write-Output $line,("- "+$msg),$line
}
############
# DATAS
############
$MAs = @(get-wmiobject -class "MIIS_ManagementAgent" -namespace "root
\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
$numOfExecDone = 0
############
# PROGRAM
############
do {
Write-Output-Banner("Execution #:"+(++$numOfExecDone))
foreach($MATypeNRun in $params_runProfilesOrder) {
$found = $false;
foreach($MA in $MAS) {
if(!$found) {
if($MA.Type.Equals($MATypeNRun.type)) {
$found=$true;
Write-Output-Banner("MA: "+$MA.Type)
foreach($profileName in $MATypeNRun.profilesToRun) {
Write-Output (" "+$profileName)," -> starting"
$datetimeBefore = Get-Date;
$result = $MA.Execute($profileName);
$datetimeAfter = Get-Date;
$duration = $datetimeAfter - $datetimeBefore;
if("success".Equals($result.ReturnValue)){
$msg = "done. Duration: "+$duration.Hours
+":"+$duration.Minutes+":"+$duration.Seconds
} else { $msg = "Error: "+$result }
Write-Output (" -> "+$msg)
}
}
}
}
if(!$found) { Write-Output ("Not found MA type :"+$MATypeNRun.type); }
}
$continue = ($params_numOfExecs -EQ 0) -OR ($numOfExecDone -lt $params_numOfExecs)
if($continue) {
Write-Output-Banner("Sleeping "+$params_delayBetweenExecs+" seconds")
Start-Sleep -s $params_delayBetweenExecs
}
} while($continue)
You can also find more informations on my blog: http://fabienduchene.blogspot.com/2009/11/fim-execute-management-agents-run.html
November 18th, 2009 10:15am
Very cool, Fabien, thanks for sharing the script with the community!I have added your script to the catalog page.Cheers,MarkusMarkus Vilcinskas, Knowledge Engineer, Microsoft Corporation
Free Windows Admin Tool Kit Click here and download it now
November 18th, 2009 11:15am
Hello, I was testing with this script today and had a question. It seems in the configuration that I specify the "type" of MA that the run profiles should be selected from but I don't see how to specify the "name" of the MA that should be chosen. In my environment I will have several "Active Directory" MAs so I need to specify the MA name when I launch. is this possible in the power shell script? (sorry if this is a simple question but I'mm new to PS). Thanks.
December 13th, 2009 3:16pm
You're totally right, I selected the management agent according to its type (active directory, FIM, SAP...) but not from its name.
I will check tomorrow how to select a MA by its name and will keep you posted.
Cheers.
Free Windows Admin Tool Kit Click here and download it now
December 13th, 2009 3:26pm
In order to select the management agent by its name instead of by its type:
$params_runProfilesOrder =
@(
@{
name="FIM MA";
profilesToRun=@("Export";"Delta Import";"Delta Synchronization");
};
@{
name="adds";
profilesToRun=@("Export";"Delta Import";"Delta Synchronization");
};
);
and replace the line
if($MA.Type.Equals($MATypeNRun.type)) {
by
if($MA.Name.Equals($MATypeNRun.name)) {
Cheers.
December 14th, 2009 9:57am
Outstanding. I will test this right away. Thank you very much!
Free Windows Admin Tool Kit Click here and download it now
December 14th, 2009 10:28am
Something I do in my run scripts is put in a function to retrieve a MA by name, which can be assigned to a variable and then the Execute method can be called on that. If you have a lot of management agents, it can be a bit quicker and more efficient. Here's the one I use: function GetMA { param([string]$maName) $filter = "Name='" + $maName + "'" Get-WmiObject -Class MIIS_ManagementAgent -Namespace root/MicrosoftIdentityIntegrationServer -Filter $filter } I like your idea of using an array of profile names and iterating over that. I guess the next step would be to use a hashtable with the MA name as the key and the array of profiles to run. Hmmm....., serialize as XML, then you'd have a completely data-driven script that you'd never have to change.... I feel a PowerShell session coming on... James
December 14th, 2009 10:43am
I've made a few changes to it so that it e-mails "someone" when things go wrong.
# @author: Fabien Duchene
# @mail: fabien.duchene1 **at** googlemail.com
# @Modified by Peter Lambrechtsen to include sending errors via e-mail
# including run-history if things go wrong- plambrechtsen at gmail dot com
############
# PARAMETERS
############
$params_ComputerName = "." # "." is the current computer
$params_delayBetweenExecs = 30 #delay between each execution, in seconds
$params_numOfExecs = 1 #Number of executions 0 for infinite
$params_runProfilesOrder =
@(
@{
name="OracleMA";
profilesToRun=@("Load");
};
@{
name="Active Directory";
profilesToRun=@("Export";"Full Synchronization";"Export");
};
);
##################
# EMAIL PARAMETERS
##################
$emailFrom = "FIM@org.com"
$emailTo = "FIMAlertMailbox@org.com"
$smtpServer = "smtp.org.com"
############
# FUNCTIONS
############
$line = "-----------------------------"
function Write-Output-Banner([string]$msg) {
Write-Output $line,$msg,$line
}
############
# DATAS
############
$MAs = @(get-wmiobject -class "MIIS_ManagementAgent" -namespace "root\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
$numOfExecDone = 0
############
# PROGRAM
############
do {
Write-Output-Banner("Execution #:"+(++$numOfExecDone))
foreach($MATypeNRun in $params_runProfilesOrder) {
$found = $false;
foreach($MA in $MAS) {
if(!$found) {
# if($MA.Type.Equals($MATypeNRun.type)) {
if($MA.Name.Equals($MATypeNRun.name)) {
$found=$true;
Write-Output-Banner("- MA Name: "+$MA.Name,"`n- Type: "+$MA.Type)
# Write-Output-Banner("MA Type: "+$MA.Type)
foreach($profileName in $MATypeNRun.profilesToRun) {
Write-Output (" "+$profileName)," -> starting"
$datetimeBefore = Get-Date;
$result = $MA.Execute($profileName);
$datetimeAfter = Get-Date;
$duration = $datetimeAfter - $datetimeBefore;
if("success".Equals($result.ReturnValue)){
$msg = "done. Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds
} else {
$msg = "Error: "+$result
# Problems with RunHistory WMI not working with MaGuid or MaName, so I used RunDetails from the MA.
# $RunHistory = get-wmiobject -class "MIIS_RunHistory" -namespace "root\MicrosoftIdentityIntegrationServer" -filter("MaGuid='" + $MA.guid + "'")
# # Write the RunHistory file XML out to a file to then attach to the e-mail, and also set it to a XML attribute.
# $RunHistory[1].RunDetails().ReturnValue | Out-File RunHistory.xml
# Grab the first run-history, which always is the latest result.
# [xml]$RunHistoryXML = $RunHistory[1].RunDetails().ReturnValue
#Take the MA RunDetails RunHistory XML and write to file.
$MA.RunDetails().ReturnValue | Out-File RunHistory.xml
# Grab the MA run-history and put it into a XML var.
[xml]$RunHistoryXML = $MA.RunDetails().ReturnValue
# Build User Errors for Exports
$RunHistoryXML."run-history"."run-details"."step-details"."synchronization-errors"."export-error" | select dn,"error-type" | export-csv ErrorUsers.csv
# Build SMTP Message
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtpmsg = new-object Net.Mail.MailMessage
$smtpmsg.From = $emailFrom
$smtpmsg.To.Add($emailTo)
$smtpmsg.Subject = "FIM Processing Error: " + $result.ReturnValue
$smtpbody = "<!DOCTYPE html PUBLIC `"-//W3C//DTD XHTML 1.0 Strict//EN`" `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$smtpbody += "<html xmlns=`"http://www.w3.org/1999/xhtml`"><head>"
$smtpbody += "<title>FIM Processing Error</title></head><body>"
$smtpbody += "<b>A Forefront Identity Manager</b> error has occured: " + $result.ReturnValue
$smtpbody += "<br><b>MA Name</b>: " + $MA.Name
$smtpbody += "<br><b>MA Run Profile</b>: " + $profileName
$smtpbody += "<br><b>Start date & time</b>: " + $MA.RunStartTime().ReturnValue
$smtpbody += "<br><b>End date & time</b>: " + $MA.RunEndTime().ReturnValue
$smtpbody += "<br><b>Total connector space objects</b>: " + $MA.NumCSObjects().ReturnValue
$smtpbody += "<br><b>Total Connectors</b>: " + $MA.NumTotalConnectors().ReturnValue
$smtpbody += "<br><b>Connectors</b>: " + $MA.NumConnectors().ReturnValue
$smtpbody += "<br><b>Explicit Connectors</b>: " + $MA.NumExplicitConnectors().ReturnValue
$smtpbody += "<br><b>Total Disconnectors</b>: " + $MA.NumTotalDisconnectors().ReturnValue
$smtpbody += "<br><b>Disconnectors</b>: " + $MA.NumDisconnectors().ReturnValue
$smtpbody += "<br><b>Explicit Disconnectors</b>: " + $MA.NumExplicitDisconnectors().ReturnValue
$smtpbody += "<br><b>Filtered Disconnectors</b>: " + $MA.NumFilteredDisconnectors().ReturnValue
$smtpbody += "<br><b>Total Placeholders</b>: " + $MA.NumPlaceholders().ReturnValue
$smtpbody += "<br><b>Import Add</b>: " + $MA.NumImportAdd().ReturnValue
$smtpbody += "<br><b>Import Updates</b>: " + $MA.NumImportUpdate().ReturnValue
$smtpbody += "<br><b>Import Deletes</b>: " + $MA.NumImportDelete().ReturnValue
$smtpbody += "<br><b>Import No Change</b>: " + $MA.NumImportNoChange().ReturnValue
$smtpbody += "<br><b>Export Add</b>: " + $MA.NumExportAdd().ReturnValue
$smtpbody += "<br><b>Export Updates</b>: " + $MA.NumExportUpdate().ReturnValue
$smtpbody += "<br><b>Export Deletes</b>: " + $MA.NumExportDelete().ReturnValue
$smtpbody += "<br><br></body></html>"
# Write-Output ( $smtpbody )
$smtpmsg.Body = $smtpbody
$smtpmsg.IsBodyHTML = $true
$RHFile = new-object Net.Mail.Attachment([string](get-location)+'\RunHistory.xml')
$smtpmsg.Attachments.Add($RHFile)
$EUFile = new-object Net.Mail.Attachment([string](get-location)+'\ErrorUsers.csv')
$smtpmsg.Attachments.Add($EUFile)
$smtp.Send($smtpmsg)
$RHFile.Dispose()
$EUFile.Dispose()
}
Write-Output (" -> "+$msg)
Write-Output (" -> "+$result.ReturnValue)
}
}
}
}
if(!$found) { Write-Output ("Not found MA type :"+$MATypeNRun.type); }
}
$continue = ($params_numOfExecs -EQ 0) -OR ($numOfExecDone -lt $params_numOfExecs)
if($continue) {
Write-Output-Banner("Sleeping "+$params_delayBetweenExecs+" seconds")
Start-Sleep -s $params_delayBetweenExecs
}
} while($continue)
Free Windows Admin Tool Kit Click here and download it now
May 31st, 2010 3:59am
Hi,
How do i get past this?
PS C:\users\appfimda\desktop> get-wmiobject -class "MIIS_ManagementAgent"
Get-WmiObject : Invalid class
At line:1 char:14
+ get-wmiobject <<<< -class "MIIS_ManagementAgent"
I'm guessing i need to define some cmdlet or somethin?
September 21st, 2010 2:42am
Hi, first note the correct command is
$MAs = @(get
-wmiobject -class
"MIIS_ManagementAgent"
-namespace
"root\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
Then you obviously would need to the wmi class MIIS_ManagementAgent registred. Thus I am assuming installing MIIS synchronization server, formerly named FIM 2010 Sync server would be enough for this class to be registred.
Cheers
Free Windows Admin Tool Kit Click here and download it now
September 21st, 2010 2:47am
I do something similar, and I'm attaching methods to the returned PSObject so that it's simpler to run profiles:
# run a profile and print execution time and result
function RunProfile ($agent,[string] $profileName) {
$runStart = [System.DateTime]::UtcNow
Write-Host -noNewLine "$($agent.Name) ${profileName} "
$res = $agent.Execute($profileName)
$runTime = [System.DateTime]::UtcNow - $runStart
if ($res.ReturnValue -eq "success") {
Write-Host "[$runTime] : $($res.ReturnValue)"
} else {
Write-Host -ForegroundColor Yellow "[$runTime] : $($res.ReturnValue)"
}
}
# get an MA by name and attach functions to run profiles
function ManagementAgent([string] $name) {
$ma = get-wmiobject -class MIIS_ManagementAgent `
-namespace root\MicrosoftIdentityIntegrationServer `
-filter "name='$name'" -ErrorAction SilentlyContinue
Add-Member -InputObject $ma ScriptMethod FullImport { RunProfile $this "Full Import" }
Add-Member -InputObject $ma ScriptMethod FullSynch { RunProfile $this "Full Synch" }
Add-Member -InputObject $ma ScriptMethod DeltaImport { RunProfile $this "Delta Import" }
Add-Member -InputObject $ma ScriptMethod DeltaSynch { RunProfile $this "Delta Synch" }
Add-Member -InputObject $ma ScriptMethod Export { RunProfile $this "Export" }
Add-Member -InputObject $ma ScriptMethod Run {
if ($args.Length -eq 0) {
throw "Specify the name of the profile to run."
}
RunProfile $this $args[0]
}
$ma
}
# get the MA named "AD"
$ad = ManagementAgent "AD"
At this point, to run a profile from the PS shell you just need to type e.g.
$ad.FullImport()
and the best part is that if you hit tab you get auto-completion for the method name :)
Paolo Tedesco - http://cern.ch/idm
September 21st, 2010 8:12am
Hi, first note the correct command is
$MAs = @(get
-wmiobject -class
"MIIS_ManagementAgent"
-namespace
"root\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
Then you obviously would need to the wmi class MIIS_ManagementAgent registred. Thus I am assuming installing MIIS synchronization server, formerly named FIM 2010 Sync server would be enough for this class to be registred.
Cheers
Registrering the wmi class MIIS_ManagementAgent would be what i'm missing. Apparently it's not enough to install the FIM Sync server. I'll find out how to do that, and post i here, then maybe you could add it to the post?
Free Windows Admin Tool Kit Click here and download it now
September 23rd, 2010 3:22am
very useful info
has anyboy managed to find a way to get past the
Get-WmiObject : Invalid namespace
At C:\Run Profiles\1-TEST-RUN-PROFILE.ps1:44 char:23
error. I'm quiet new in the scripting world and don't really know how to register the wmi class.
ThanksThanks a mil, a mil, a mil
October 28th, 2010 10:04am
Hi....Can anyone help me to configure connector filter for MA using powershell script....
Thanks in advance..
Vijai Anand.R
Free Windows Admin Tool Kit Click here and download it now
January 5th, 2011 2:42am
Hi Vijai,
that powershell script is only to ordonance management agents.
I am not sure about what you are trying to perform, but I am assuming you would like to run a management agent tasks, and passing it a connector filter, right?Information Security Engineer
January 5th, 2011 7:04am
Hello,
i also made some modifications, one is to seperate the configuration into a XML file. also some other modifications.
MyScript goes like this:
<#
.Synopsis
Starts the FIM 2010 Management Agents in a sequence
.Description
Starting FIM 2010 Management Agents in a sequence based on a XML config file
.Example
FIMRunCycle -configfile config.xml
Starts the RunCycle based on the specified config file.
.Parameter configfile
Specify the name of the XML config file
.Notes
NAME: FIMRunCycle
AUTHOR: Author
LASTEDIT: 01/06/2011
KEYWORDS: FIM 2010, Run Cycle, Management Agent
#Requires -Version 2.0
#>
param([string]$configfile=$(Read-Host -prompt "Configfile"))
### Load Configuration Data ###
[xml]$maconfig=(Get-Content $configfile)
"" > $maconfig.runcycle.logfile
### Functions ###
$line = "---------------------------------------------------------------------------------"
function Write-Output-Banner([string]$msg) {
Write-Output $line,(" "+$msg),$line
Write-Output $line,(" "+$msg),$line >> $maconfig.runcycle.logfile
}
function Write-Output-Text([string]$msg) {
Write-Output $msg
Write-Output $msg >> $maconfig.runcycle.logfile
}
### Get Management Agent Data ###
$allMA = @(get-wmiobject -class "MIIS_ManagementAgent" -namespace "root\MicrosoftIdentityIntegrationServer" -computername $maconfig.runcycle.computername)
$numOfExecDone = 0
### Main Script ###
do {
Write-Output-Banner("Execution #:"+(++$numOfExecDone)+" - Date: "+(date))
foreach($MANextRun in $maconfig.runcycle.ma) {
$found = $false;
foreach($MA in $allMA) {
if(!$found) {
if($MA.Name.Equals($MANextRun.name)) {
$found=$true;
Write-Output-Banner("MA: "+$MA.Name+" [Type: "+$MA.Type+"]")
Write-Output-Text(" - Starting Pre-Script: "+$MANextRun.preScript)
invoke-expression $MANextRun.preScript | Out-Null
Write-Output-Text(" - Done`n")
foreach($profileName in $MANextRun.profilesToRun) {
Write-Output-Text(" - Starting Profile: "+$profileName)
$datetimeBefore = Get-Date;
$result = $MA.Execute($profileName);
$datetimeAfter = Get-Date;
$duration = $datetimeAfter - $datetimeBefore;
Write-Output-Text(" - Done with status: "+$result.ReturnValue+" - Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds+"`n")
}
Write-Output-Text(" - Starting Post-Script: "+$MANextRun.postScript)
invoke-expression $MANextRun.postScript | Out-Null
Write-Output-Text(" - Done`n")
Start-Sleep -s $MANextRun.waitSeconds
}
}
}
if(!$found) { Write-Output-Text("Not found MA name :"+$MANextRun.name); }
}
$continue = ($maconfig.runcycle.cycleWaitSeconds -EQ 0) -OR ($numOfExecDone -lt $maconfig.runcycle.numOfExecs)
if($continue) {
Write-Output-Banner("Sleeping "+$maconfig.runcycle.cycleWaitSeconds+" seconds")
Start-Sleep -s $maconfig.runcycle.cycleWaitSeconds
}
} while($continue)
and the XML config file is like this:
<?xml version="1.0" encoding="utf-8" ?>
<runcycle computerName="." cycleWaitSeconds="15" numOfExecs="1" logFile=".\runcycle.log">
<MA>
<name>HR MA</name>
<preScript>.\pre.cmd</preScript>
<profilesToRun>FISO</profilesToRun>
<profilesToRun>DS</profilesToRun>
<postScript>.\post.cmd</postScript>
<waitSeconds>5</waitSeconds>
</MA>
<MA>
<name>FIM MA</name>
<preScript>.\pre.bat</preScript>
<profilesToRun>FISO</profilesToRun>
<profilesToRun>DS</profilesToRun>
<profilesToRun>E</profilesToRun>
<profilesToRun>DISO</profilesToRun>
<postScript>.\post.bat</postScript>
<waitSeconds>5</waitSeconds>
</MA>
<MA>
<name>AD MA</name>
<preScript>cscript .\pre.vbs</preScript>
<profilesToRun>E</profilesToRun>
<profilesToRun>DISO</profilesToRun>
<profilesToRun>DS</profilesToRun>
<postScript>cscript .\post.vbs</postScript>
<waitSeconds>5</waitSeconds>
</MA>
</runcycle>
Greets
Peter
Free Windows Admin Tool Kit Click here and download it now
January 6th, 2011 5:39am
very useful info
has anyboy managed to find a way to get past the
Get-WmiObject : Invalid namespace
At C:\Run Profiles\1-TEST-RUN-PROFILE.ps1:44 char:23
error. I'm quiet new in the scripting world and don't really know how to register the wmi class.
Thanks
Thanks a mil, a mil, a mil
I can run Paolo's script directly in the Powershell window all day long, but as soon as I add it as a Scheduled Task I get these WMI errors (once I remove the "SilentlyContinue" from the ErrorAction option). I'm not sure about what's different in my
environment than what is in the Scheduled Task environment.....
Any ideas on where to look for more information? I've been fighting this all day and I really don't want to have to revert to .vbs files and csript to run these jobs. ;)
Get-WmiObject : Access denied
At E:\Source\FIM Scripts\current\fim-test-script.ps1:131 char:21
+ $ma = get-wmiobject <<<< -class MIIS_ManagementAgent `
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], Managemen
tException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.C
ommands.GetWmiObjectCommand
June 28th, 2011 2:45pm
If you do not need a lot just run
get-wmiobject -namespace "root\MicrosoftIdentityIntegrationServer" -query "SELECT * FROM MIIS_ManagementAgent WHERE Name LIKE 'AD %'" -computername "." | ForEach-Object {$_.Execute("FI FS")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='AD 0" -computername "." | ForEach-Object {$_.Execute("ex di")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='AD 1" -computername "." | ForEach-Object {$_.Execute("ex di")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='AD 2" -computername "." | ForEach-Object {$_.Execute("ex di")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='AD 3" -computername "." | ForEach-Object {$_.Execute("ex di")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='AD 4" -computername "." | ForEach-Object {$_.Execute("ex di")}
get-wmiobject -class MIIS_ManagementAgent -namespace "root\MicrosoftIdentityIntegrationServer" -filter "Name='5" -computername "." | ForEach-Object {$_.Execute("ex di")}
Free Windows Admin Tool Kit Click here and download it now
September 17th, 2011 6:31pm
Disclaimer: I am not the original author of this script. He is given credit for his work and I do not claim to have written this. What I have done is add a few functions to the script which make the everyday usage and automation of its running safer and
a little more convenient.
Further Disclaimer: This script works for me and has worked for the past year. HOWEVER, I provide no warranty that it will work. Anything that happens to your FIM environment as a result of this script is not my responsibility or my fault. I may or may not
support the script. It's a contribution to the community with no strings attached. If anyone wants to make it even better, that is awesome! Enjoy.
The first part of the script, the guts, if you will. It should be named RunSequencerProg.ps1.
#################################################################################################################################
# FIM 2010 Management Agent Runner #
# Author : Lance Hext #
# Mail : lhext@h-cp.us #
# Version : 1.2.3 #
# Information : This Powershell script execcutes an array of managements agents supplied form the calling Powershell #
# script. This powershell script utilizes the FIM wmi interface for the execution and statistics #
# gathering. #
# For each Management executed either a single email is generted per management agent #
# or a combined email is generated which will contain all the statistic from the run. #
# The email containes the following information as part on the email body #
# 1: The Managemenmt agent name #
# 2: The Mnagement Agent complition status #
# 3: All Connector space statistics #
# 4: All Inbound Metaverse statistices #
# 5: All Export data counts #
# The email contains the following attachments #
# 1: The complete run history xml #
# 2: All inbound syncronization errors #
# 3: All Exported syncronization errors #
# #
# #
# #
#################################################################################################################################
# #
# START OF POWERSHELL SCRIPT #
# #
#################################################################################################################################
# #
# * * * * * * * * * * * D O N O T M O D I F Y B E L O W * * * * * * * * * * * * * #
# __________________________________ #
# #
#################################################################################################################################
#################################################################################################################################
# START OF FUNCTIONS #
#################################################################################################################################
$line = "-----------------------------"
function Write-Output-Banner([string]$msg)
{
Write-Output $line,("- "+$msg),$line
}
#################################################################################################################################
# END OF FUNCTIONS #
#################################################################################################################################
# START OF DATA #
#################################################################################################################################
$MAs = @(get-wmiobject -class "MIIS_ManagementAgent" -namespace "root\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
$numOfExecDone = 0
$SendEmails = $true;
#################################################################################################################################
# END OF DATA #
#################################################################################################################################
# START OF PROGRAM #
#################################################################################################################################
Write-Output-Banner($SequenceInfo)
do
{
Write-Output-Banner("Execution #:"+(++$numOfExecDone))
if (!$EmailperMA)
{
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtpmsg = new-object Net.Mail.MailMessage
$smtpmsg.From = $emailFrom
$smtpmsg.To.Add($emailTo)
if ($emailCC)
{
$smtpmsg.Cc.Add($emailCC)
}
if ($emailCC1)
{
$smtpmsg.Cc.Add($emailCC1)
}
$RunStart = Get-Date
$AllRunTimeStart = Get-Date -uformat "%Y%m%d%I%M%S"
$smtpmsg.Subject = "FIM Run Sequence Results Started : " +$RunStart
$smtpbody = "<!DOCTYPE html PUBLIC `"-//W3C//DTD XHTML 1.0 Strict//EN`" `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$smtpbody += "<html xmlns=`"http://www.w3.org/1999/xhtml`"><head>"
$smtpbody += "<title>FIM Processing Results</title></head><body>"
if ($debug)
{
$dbugmsg = "--> DB ---- In Single Email Create Mail Object"
Write-Output ($dbugmsg)
}
$AllRuns = "AllRuns-" + $AllRunTimeStart + ".xml"
$AllImportErrorRuns = "AllRuns-" + $AllRunTimeStart + "-ImportErrors.csv"
$AllExportErrorRuns = "AllRuns-" + $AllRunTimeStart + "-ExportErrors.csv"
}
foreach($MATypeNRun in $params_runProfilesOrder)
{
$found = $false;
$SendEmails = $true;
foreach($MA in $MAS)
{
if(!$found)
{
if($MA.Name.Equals($MATypeNRun.name))
{
$abortnow = $false
$found=$true;
$maname = $MA.Name
Write-Output-Banner("MA Name: "+$MA.Name,"`n- Type: "+$MA.Type)
foreach($profileName in $MATypeNRun.profilesToRun)
{
## Added 01/23/2012 :: Author: Ethan Turk
## Change Info: Added to allow sleeping for individual Sync Cycle
## Steps instead of a sleep which must run for every step.
if($MATypeNRun.sleep -gt 0) {
"Found Sleep. Sleeping for " + $MATypeNRun.sleep + " seconds" | Out-Host
Start-Sleep -Seconds $MATypeNRun.sleep
}
## End Addition
## Added 03/05/2012 :: Author: Ethan Turk
## Change Info: Added to set thresholds for maximum number of changes
## which are allowed in a single run step. You can set individual limits
## for add, updates and deletes.
$abortthreshold = "Threshold Reached on $maname $profileName. Cancelling run cycle..."
if($MATypeNRun.addthreshold) {
$ttype = "Add"
$addstatus = .\FIM_ActionThresholds.ps1 $MA.Name $ttype $MATypeNRun.addthreshold
if($addstatus) {
$abortnow = "$ttype $abortthreshold"
break
}
}
if($MATypeNRun.updthreshold) {
$ttype = "Update"
$updstatus = .\FIM_ActionThresholds.ps1 $MA.Name $ttype $MATypeNRun.updthreshold
if($updstatus) {
$abortnow = "$ttype $abortthreshold"
break
}
}
if($MATypeNRun.delthreshold) {
$ttype = "Delete"
$delstatus = .\FIM_ActionThresholds.ps1 $MA.Name $ttype $MATypeNRun.delthreshold
if($delstatus) {
$abortnow = "$ttype $abortthreshold"
break
}
}
## End Addition
Write-Output ("Run Profile "+$profileName,"`n -> starting")
$RunTimeStart = Get-Date -uformat "%Y%m%d%I%M%S"
$datetimeBefore = Get-Date;
$result = $MA.Execute($profileName);
$datetimeAfter = Get-Date;
$duration = $datetimeAfter - $datetimeBefore;
# Setup SMTP Message
if($EmailperMA)
{
if ($debug)
{
$dbugmsg = "--> DB ---- In Multiple Email Create new Mail Object"
Write-Output ($dbugmsg)
}
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
if ($UseEmailCreds)
{
$smtp.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
}
$smtpmsg = new-object Net.Mail.MailMessage
$smtpmsg.From = $emailFrom
$smtpmsg.To.Add($emailTo)
if ($emailCC)
{
$smtpmsg.Cc.Add($emailCC)
}
$smtpbody = "<!DOCTYPE html PUBLIC `"-//W3C//DTD XHTML 1.0 Strict//EN`" `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$smtpbody += "<html xmlns=`"http://www.w3.org/1999/xhtml`"><head>"
$smtpbody += "<title>FIM Processing Results</title></head><body>"
#$smtpbody += "<table><tr><td colspan=2 align=center><u>Forefront Identity Manager Management Agent Run Results for: <b>" + $MA.Name +"</b></u></td></tr>"
$smtpbody += "<table><tr><td colspan=2 align=center><u>Forefront Identity Manager Management Agent Run Results</b></u></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpmsg.Subject = "FIM Management Agent - " + $MA.Name
if("success".Equals($result.ReturnValue))
{
$msg = "Done. Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds
$smtpmsg.Subject += " Processing Success"
$smtpbody += "<tr><td colspan=2><b>" + $MA.Name +"<font color=Green> Completed Successfully</font></b></td></tr>"
if ($EmailOnErrorOnly)
{
$SendEmails = $false;
}
}
else
{
$msg = "Done with Error. Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds +" - Error: "+$result
$smtpmsg.Subject += " Processing Error"
$smtpbody +="<tr><td colspan=2><b>" + $MA.Name +":<font color=Red> Completed.</font></b></td></tr>"
$smtpbody +="<tr><td colspan=2>MA Synchronization Status: <font color=Red><b>" + $result.ReturnValue + "</font></b></td></tr>"
}
}
else
{
$smtpbody += "<table><tr><td colspan=2 align=center><u>Forefront Identity Manager Management Agent Run Results</u></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
if("success".Equals($result.ReturnValue))
{
$msg = "Done. Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds
$smtpbody += "<tr><td colspan=2><b>" + $MA.Name +"<font color=Green> Completed Successfully</font></b></td></tr>"
$smtpbody += "<tr><td colspan=2>MA Synchronization Status: <font color=Green><b>" + $result.ReturnValue + "</font></b></td></tr>"
if ($EmailOnErrorOnly)
{
$SendEmails = $false;
}
}
else
{
$msg = "Done with Error. Duration: "+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds +" - Error: "+$result
$smtpbody += "<tr><td colspan=2>" + $MA.Name +":<font color=Red> Completed.</font></b></td></tr>"
$smtpbody += "<tr><td colspan=2>MA Synchronization Status: <font color=Red><b>" + $result.ReturnValue + "</font></b></td></tr>"
}
$SendEmails = $true
if ($debug)
{
$dbugmsg = "--> DB ---- In Single Email : New Table "
Write-Output ($dbugmsg)
}
}
# Problems with RunHistory WMI not working with MaGuid or MaName, so I used RunDetails from the MA.
# $RunHistory = get-wmiobject -class "MIIS_RunHistory" -namespace "root\MicrosoftIdentityIntegrationServer" -filter("MaGuid='" + $MA.guid + "'")
# # Write the RunHistory file XML out to a file to then attach to the e-mail, and also set it to a XML attribute.
# $RunHistory[1].RunDetails().ReturnValue | Out-File RunHistory.xml
# Grab the first run-history, which always is the latest result.
# [xml]$RunHistoryXML = $RunHistory[1].RunDetails().ReturnValue
#Take the MA RunDetails RunHistory XML and write to file.
$RunHistFileName = $MA.Name + "-" + $RunTimeStart +"-RunHistory.xml"
$ImportErrorUserFileName = $MA.Name + "-" + $RunTimeStart + "-ImportErrors.csv"
$ExportErrorUserFileName = $MA.Name + "-" + $RunTimeStart + "-ExportErrors.csv"
$MA.RunDetails().ReturnValue | Out-File $RunHistFileName
# Grab the MA run-history and put it into a XML var.
[xml]$RunHistoryXML = $MA.RunDetails().ReturnValue
[xml]$RunHistory1XML = $MA.RunDetails().ReturnValue
# Build User Errors for Exports
$RunHistoryXML."run-history"."run-details"."step-details"."synchronization-errors"."import-error" | select dn,"error-type" | export-csv $ImportErrorUserFileName
$RunHistoryXML."run-history"."run-details"."step-details"."synchronization-errors"."export-error" | select dn,"error-type" | export-csv $ExportErrorUserFileName
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2><u><b>" + $MA.Name + " Run Statistics</b></u></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td width=800px>MA Run Profile:</td><td width=800px align=left><b>" + $profileName+"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Start Date & Time:</td><td width=800px align=left><b>" + $MA.RunStartTime().ReturnValue + "</b></td></tr>"
$smtpbody += "<tr><td width=800px>End Date & Time:</td><td width=800px align=left><b>" + $MA.RunEndTime().ReturnValue + "</b></td></tr>"
$smtpbody += "<tr><td width=800px>Total Run Time:</td><td width=800px align=left><b>"+$duration.Hours+":"+$duration.Minutes+":"+$duration.Seconds + "</b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2><u><b>Connector Space Statistics<b></u></td></tr>"
$smtpbody += "<tr><td width=800px>Total Connector Space Objects:</td><td width=800px align=left><b>" + $MA.NumCSObjects().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Total Connectors:</td><td width=800px align=left><b>" + $MA.NumTotalConnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Connectors:</td><td width=800px align=left><b>" + $MA.NumConnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Explicit Connectors:</td><td width=800px align=left><b>" + $MA.NumExplicitConnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Total Disconnectors:</td><td width=800px align=left><b>" + $MA.NumTotalDisconnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Disconnectors:</td><td width=800px align=left><b>" + $MA.NumDisconnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Explicit Disconnectors:</b></td><td><b>" + $MA.NumExplicitDisconnectors().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Total Placeholders:</b></td><td width=800px align=left><b>" + $MA.NumPlaceholders().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td width=800px>Total Placeholders:</b></td><td width=800px align=left><b>" + $MA.NumPlaceholders().ReturnValue +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
#################################################################################################################################
# Discovery Counters #
#################################################################################################################################
$smtpbody += "<tr><td colspan=2><u><b>Discovoery Statistics</b></u></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/ma-discovery-counters/filtered-deletions")
$smtpbody += "<tr><td width=800px>Filtered Deletions</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/ma-discovery-counters/filtered-objects")
$smtpbody += "<tr><td width=800px>Filtered Objects:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
#################################################################################################################################
# Staging Counters #
#################################################################################################################################
$smtpbody += "<tr><td colspan=2><u><b>Stage Import Statistics</b></u></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-no-change")
$smtpbody += "<tr><td width=800px>Import Stage Unchanged:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-add")
$smtpbody += "<tr><td width=800px>Import Stage Add:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-update")
$smtpbody += "<tr><td width=800px>Import Stage Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-delete")
$smtpbody += "<tr><td width=800px>Import Stage Deletes:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-delete-add")
$smtpbody += "<tr><td width=800px>Import Stage Delete-Adds:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/staging-counters/stage-failure")
$smtpbody += "<tr><td width=800px>Import Stage Failures:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
#################################################################################################################################
# MV Inbound Counters #
#################################################################################################################################
$smtpbody += "<tr><td colspan=2 align=center><u><b>Inbound Statistics</b></u></td></tr>"
$smtpbody += "<tr><td colspan=2 align=left><u><b>Disconnectors</b></u></td></tr>"
$smtpbody += "<tr><td width=800px align=right>Filtered Disconnectors:</b></td><td><b>" + $MA.NumFilteredDisconnectors().ReturnValue +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-remains")
$smtpbody += "<tr><td width=800px align=right>Disconnectors</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=center> </td></tr>"
$smtpbody += "<tr><td colspan=2 align=left><u><b>Metaverse</b></u></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-projected-flow")
$smtpbody += "<tr><td width=800px align=right>Projections - With Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-projected-no-flow")
$smtpbody += "<tr><td width=800px align=right>Projections - Without Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-joined-flow")
$smtpbody += "<tr><td width=800px align=right>Joins - With Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-joined-no-flow")
$smtpbody += "<tr><td width=800px align=right>Joins - Without Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-flow-remove-mv")
$smtpbody += "<tr><td width=800px align=right>Deleted Metaverse Objects</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-delete-leave-mv")
$smtpbody += "<tr><td width=800px align=right>Disconnected Metaverse Objects</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/flow-failure")
$smtpbody += "<tr><td width=800px align=right>Metaverse Flow Failures</b></td><td width=800px align=left><b><font=Red>" + $mvValue.InnerText +"</font></b></td></tr>"
$smtpbody += "<tr><td colspan=2 align=left><u><b>Connector Objects</b></u></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-flow")
$smtpbody += "<tr><td width=800px align=right>Connector With Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-no-flow")
$smtpbody += "<tr><td width=800px align=right>Connector Without Flow Updates:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-filtered-leave-mv")
$smtpbody += "<tr><td width=800px align=right>Connector Filtered</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-filtered-remove-mv")
$smtpbody += "<tr><td width=800px align=right>Connector Filtered Deleted</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/connector-delete-add-processed")
$smtpbody += "<tr><td width=800px align=right>Connector Delete-Add</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
# $mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-projected-remove-mv")
# $smtpbody += "<tr><td width=800px>Metaverse Disconnectors Projected</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
# $mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/inbound-flow-counters/disconnector-joined-remove-mv")
# $smtpbody += "<tr><td width=800px>MV Deleted - Joined Disconnectors</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2> </td></tr>"
$smtpbody += "<tr><td colspan=2><u><b>Export Statistics</b></u></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-add")
$smtpbody += "<tr><td width=800px>Export Adds</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-update")
$smtpbody += "<tr><td width=800px>Export Updates</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-rename")
$smtpbody += "<tr><td width=800px>Export Renames</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-delete")
$smtpbody += "<tr><td width=800px>Export Deletes</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-delete-add")
$smtpbody += "<tr><td width=800px>Export Delete-Adds</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $RunHistory1XML.SelectSingleNode("run-history/run-details/step-details/export-counters/export-failure")
$smtpbody += "<tr><td width=800px>Export Failures</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2> </td></tr>"
#################################################################################################################################
# Outbound Counters #
#################################################################################################################################
$outboundCounters=$RunHistory1XML.SelectNodes("run-history/run-details/step-details/outbound-flow-counters")
foreach($outboundCounter in $outboundCounters)
{
$mvValue = $outboundCounter.ma
if ($debug)
{
Write-Output ($outboundCounter)
Write-Output ($mvValue)
}
$smtpbody += "<tr><td colspan=2><u><b>OutBound Statistics for: " + $mvValue + "</b></u></td></tr>"
$mvValue = $outboundCounter.SelectSingleNode("provisioned-add-flow")
$smtpbody += "<tr><td width=800px>Provisioning Adds:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $outboundCounter.SelectSingleNode("provisioned-disconnect")
$smtpbody += "<tr><td width=800px>Provisioning Disconnect:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$mvValue = $outboundCounter.SelectSingleNode("connector-flow")
$smtpbody += "<tr><td width=800px>Export Attribute Flow:</b></td><td width=800px align=left><b>" + $mvValue.InnerText +"</b></td></tr>"
$smtpbody += "<tr><td colspan=2> </td></tr>"
}
$smtpbody += "<tr><td colspan=2> </td></tr>"
$smtpbody += "</table></body></html>"
# Write-Output ( $smtpbody )
if($EmailperMA)
{
if ($debug)
{
$dbugmsg = "--> DB ---- In Multiple Email Send"
Write-Output ($dbugmsg)
}
$RHFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $RunHistFileName)
$smtpmsg.Attachments.Add($RHFile)
$IUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $ImportErrorUserFileName)
$smtpmsg.Attachments.Add($IUFile)
$EUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $ExportErrorUserFileName)
$smtpmsg.Attachments.Add($EUFile)
$smtpmsg.Body = $smtpbody
$smtpmsg.IsBodyHTML = $true
if ($SendEmails)
{
$smtp.Send($smtpmsg)
}
$RHFile.Dispose()
$IUFile.Dispose()
$EUFile.Dispose()
remove-item $RunHistFileName
remove-item $ImportErrorUserFileName
remove-item $ExportErrorUserFileName
}
else
{
if ($debug)
{
$dbugmsg = "--> DB ---- In Single Email Conat files"
Write-Output ($dbugmsg)
}
cat $RunHistFileName > $AllRuns
cat $ImportErrorUserFileName > $AllImportErrorRuns
cat $ExportErrorUserFileName > $AllExportErrorRuns
remove-item $RunHistFileName
remove-item $ImportErrorUserFileName
remove-item $ExportErrorUserFileName
}
Write-Output (" -> "+$msg)
Write-Output (" -> "+$result.ReturnValue)
}
}
}
if($abortnow) { break }
}
if(!$found -and !$abortnow)
{
Write-Output ("Not found MA Name:"+$MATypeNRun.name);
}
}
if($abortnow) { $abortnow | Out-Host }
$continue = ($params_numOfExecs -EQ 0) -OR ($numOfExecDone -lt $params_numOfExecs)
if($continue)
{
Write-Output-Banner("Sleeping "+$params_delayBetweenExecs+" seconds")
if ($debug)
{
$dbugmsg = "--> DB ---- In Single Email SLEEP Send"
Write-Output ($dbugmsg)
}
if(!$EmailperMA)
{
$smtpbody = "<font style='font-size: x-large; color: red;'>" + $abortnow +
"</font><br /><br />" + $smtpbody
$RHFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllRuns)
$smtpmsg.Attachments.Add($RHFile)
$IUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllImportErrorRuns )
$smtpmsg.Attachments.Add($IUFile)
$EUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllExportErrorRuns )
$smtpmsg.Attachments.Add($EUFile)
$smtpmsg.Body = $smtpbody
$smtpmsg.IsBodyHTML = $true
if ($SendEmails -and $abortnow)
{
$smtp.Send($smtpmsg)
}
$RHFile.Dispose()
$IUFile.Dispose()
$EUFile.Dispose()
remove-item $AllRuns
remove-item $AllImportErrorRuns
remove-item $AllExportErrorRuns
}
Start-Sleep -s $params_delayBetweenExecs
}
else
{
Write-Output ("******************************")
}
}
while($continue)
if(!$EmailperMA)
{
$smtpbody = "<font style='font-size: x-large; color: red;'>" +
$abortnow + "</font><br /><br />" + $smtpbody
if ($debug)
{
$dbugmsg = "--> DB ---- In Single Email Send"
Write-Output ($dbugmsg)
}
$RHFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllRuns)
$smtpmsg.Attachments.Add($RHFile)
$IUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllImportErrorRuns )
$smtpmsg.Attachments.Add($IUFile)
$EUFile = new-object Net.Mail.Attachment([string](get-location)+'\'+ $AllExportErrorRuns )
$smtpmsg.Attachments.Add($EUFile)
$smtpmsg.Body = $smtpbody
$smtpmsg.IsBodyHTML = $true
if ($SendEmails -and $abortnow)
{
$smtp.Send($smtpmsg)
}
$RHFile.Dispose()
$IUFile.Dispose()
$EUFile.Dispose()
remove-item $AllRuns
remove-item $AllImportErrorRuns
remove-item $AllExportErrorRuns
}
The Guts gets its parameters from a separate file, The Parameters, which allows for multiple run sequences without modifying the standard code. It can be named anything. This is the script that you will run to kick off your Sync Cycle.
#@author: Lance Hext
#@mail: lhext@h-cp.us
#############################################################################################
# PARAMETERS #
#############################################################################################
# #
# $debug #
# debug on = $true; #
# Debug off = $false; #
# #
#############################################################################################
#
$debug = $false;
#
#############################################################################################
# #
# $SequenceInfo #
# Place some meaningfull information for display at the #
# begininiong of the squ3nce #
# #
#############################################################################################
#
$SequenceInfo = "Hourly Syncronization Sequence"
#
#############################################################################################
# #
# $params_ComputerName #
# The name of the server running FIM #
# Use "." if running on the Powershell script on the FIM server #
# #
#############################################################################################
#
$params_ComputerName = "."
#
#############################################################################################
# #
# $params_delayBetweenExecs #
# delay between each execution, in seconds #
# 1 Minute = 60 #
# 10 Minutes = 600 #
# 15 Minutes = 900 #
# 30 Minutes = 1800 #
# 1 Hour = 3600 #
# #
#############################################################################################
#
$params_delayBetweenExecs = 0
#
#############################################################################################
# #
# $params_numOfExecs #
# The number of executions the script will run before terminating #
# 0 for infinite #
# #
#############################################################################################
#
$params_numOfExecs = 1
#
#############################################################################################
# RUN Profile Sequenec Section #
# #
# The array below contains the MA run sequence order #
# #
# Format #
# @{ #
# name="<This has to match exactly the MA name in FIM>"; #
# profilesToRun=@("<This has to match the Run profile to Execute>"); #
# }; #
# #
#############################################################################################
#
## Addition Info :: Author: Ethan Turk
## Change Info 1: Added to set thresholds for maximum number of changes
## which are allowed in a single run step. You can set individual limits
## for add, updates or deletes.
##
## Ex: Add 'addthreshold=100;', 'delthreshold=100;' or 'updthreshold=1000;' to the
## cycle step below.
## See the 'AD MA' Export step below.
##
## Change Info 2: Added ability to set a mandatory sleep for individual
## sync cycle steps instead of a sleep for the whole set of steps.
##
## Ex: Add 'sleep=120;' to the cycle step below.
## See the 'FIM MA' Delta Import step below.
$params_runProfilesOrder =
@(
@{
name="HR MA";
profilesToRun=@("Full Import");
};
@{
name="HR MA";
profilesToRun=@("Full Sync");
};
@{
name="FIM MA";
profilesToRun=@("Export");
};
@{
name="FIM MA";
profilesToRun=@("Delta Import");
sleep=120;
};
@{
name="FIM MA";
profilesToRun=@("Delta Sync");
};
@{
name="AD MA";
profilesToRun=@("Export");
addthreshold=100;
delthreshold=100;
updthreshold=1000;
};
@{
name="AD MA";
profilesToRun=@("Delta Import");
};
@{
name="AD MA";
profilesToRun=@("Delta Sync");
};
@{
name="AD MA";
profilesToRun=@("Export");
addthreshold=100;
delthreshold=100;
updthreshold=1000;
};
@{
name="AD MA";
profilesToRun=@("Delta Import");
};
@{
name="AD MA";
profilesToRun=@("Delta Sync");
};
@{
name="FIM MA";
profilesToRun=@("Export");
};
@{
name="FIM MA";
profilesToRun=@("Delta Import");
};
@{
name="FIM MA";
profilesToRun=@("Delta Sync");
};
@{
name="FIM MA";
profilesToRun=@("Export");
};
@{
name="FIM MA";
profilesToRun=@("Full Import");
};
@{
name="FIM MA";
profilesToRun=@("Delta Sync");
};
);
#
#############################################################################################
# EMAIL PARAMETERS #
#############################################################################################
# #
# $UseEmailCreds #
# Directs the PowerShell script to send Using Credentials #
# $true; = Send email with Creds #
# $false; = Send email without Creds #
# #
#############################################################################################
#
$UseEmailCreds = $false;
#
#############################################################################################
# #
# $emailFrom #
# A Well formated email address for the FIM Server #
# Example "FIMSequencer@xyz.com" #
# #
#############################################################################################
#
$emailFrom = "SentFrom@yourdomain.com"
#
#############################################################################################
# #
# $emailTo #
# A Well formated email address for Receipent of the email #
# Example "someone@xyz.com" #
# #
#############################################################################################
#
$emailTo = "AdminEmail@yourdomain.com"
#
#############################################################################################
# #
# $emailCC #
# A Well formated email address for send a Copy of the email to #
# Example "carboncopy@xyz.com" #
# #
#############################################################################################
#
$emailCC = ""
#
#############################################################################################
# #
# $emailCC1 #
# A Well formated email address for send a Copy of the email to #
# Example "carboncopy@xyz.com" #
# #
#############################################################################################
#
$emailCC1 = ""
#
#############################################################################################
# #
# $smtpServer #
# A FQDN of a mail server #
# Example "mail.xyz.com" #
# #
#############################################################################################
#
$smtpServer = "your SMTP Server"
#
#############################################################################################
# #
# $EmailperMA #
# Directs the PowerShell script to either send an email at the completion #
# of each MA OR generate One email at the end of the sequence run #
# #
# $true; = Send an email for each MA #
# $false; = Send 1 (one) email at the completion on the Sequence #
# #
#############################################################################################
#
$EmailperMA = $false;
#
#############################################################################################
# #
# $EmailOnErrorOnly #
# Directs the PowerShell script to send and email on failues only #
# $true; = Send email only on an MA Sync Failure ie MA.Result <> "success" #
# $false; = Send email when MA finishes #
# #
#############################################################################################
#
$EmailOnErrorOnly = $false;
#
#############################################################################################
# #
# INCLUDE THE PROGRAM #
# #
# Location of the Actural Program. This can be a relative or physical path #
# #
# NOTE the 1st pewriod is required #
# Examples #
# Physical Path #
# .<space>C:\powershell\RunSequencerProg.ps1 #
# Relative Path #
# .<space>.\RunSequencerProg.ps1 #
# #
#############################################################################################
#
.\RunSequencerProg.ps1
So there is one more piece, The Helper, which contains the functions used to check for the number of pending adds, updates or deletes on a particular MA. It should be named FIM_ActionThresholds.ps1.
param(
[String]$maname,
[String]
[ValidateSet('Delete','Add','Update')]$checktype,
[Int]$itemthreshold = 100,
[String]$servername = "."
)
$found = $false
$lstSrv = @(get-wmiobject -class "MIIS_ManagementAgent" -namespace "root\MicrosoftIdentityIntegrationServer" -computer $servername)
$lstSrv | ForEach-Object {
if($_.Name -eq $maname) {
$found = $true
if($checktype.ToLower() -eq "delete") {
$numactions = [Int]$_.NumExportDelete().ReturnValue
} elseif($checktype.ToLower() -eq "update") {
$numactions = [Int]$_.NumExportUpdate().ReturnValue
} elseif($checktype.ToLower() -eq "add") {
$numactions = [Int]$_.NumExportAdd().ReturnValue
}
if($numactions -ge $itemthreshold) {
return $true
} else {
return $false
}
break
}
}
if($found -eq $false) {
$errmsg = "Did not find MA by the name: $maname"
return $errmsg
}
You are free to modify and redistribute this as you choose. I hope it helps someone else.
May 2nd, 2012 11:21am
Hi, first note the correct command is
$MAs = @(get
-wmiobject -class
"MIIS_ManagementAgent"
-namespace
"root\MicrosoftIdentityIntegrationServer" -computername $params_ComputerName)
Then you obviously would need to the wmi class MIIS_ManagementAgent registred. Thus I am assuming installing MIIS synchronization server, formerly named FIM 2010 Sync server would be enough for this class to be registred.
Cheers
Registrering the wmi class MIIS_ManagementAgent would be what i'm missing. Apparently it's not enough to install the FIM Sync server. I'll find out how to do that, and post i here, then maybe you could add it to the post?
I found out how to re-register it at:
http://www.apollojack.com/2009/04/cannot-connect-to-mms-wmi-service.html
Free Windows Admin Tool Kit Click here and download it now
May 23rd, 2012 12:27pm
About the Access Denied (0x80070005) issue when running PS script for FIM:
I don't know why exactly, but on a particular FIM Synchronization Server I had similar issues running Powershell script from Task Scheduler.
They ran from under the security context of the FIM (domain) service account.
The .ps1 files were called from a .bat file in Task Scheduler.
Kept running into these 3 events in the Eventlog:
Source: MsiInstallerUser: NETWORK SERVICEEvent ID's: 1004, 1001, 1015
Some product GUID could not find feature 'ILM_Server' with a component GUID for a resource which had a path to the FIM installation folder.
It said it 'did not exist'... I stared at the folders for over an hour to convince myself they were really, really there...
To solve this I had to grant the local NETWORK SERVICE account read access to the FIM installation folder and subfolders.
That solved it. I see similar issues with Sharepoint Profile Sync (which has FIM under the hood),
see here.Danny Alvares, Solutions Architect
May 24th, 2012 6:44pm