Share via


FIM2010 / MIM2016: Run profile statistics with PowerShell and Excel Pivot Tables


Introduction

In many cases, you want to have a better insight in the performance of your FIM Synchronization run profiles.

The FIM/MIM Sync interface only provides an instant overview of the tasks that recently run. Moreover, the availability of data is limited to the run history records available in the FIM/MIM sync database. If you want to have reports over a longer period of time, you need to export the data before cleaning the run history.

There are various options to generate reports, as discussed in the master article.

This article has the focus on building run history statistics with Powershell and Excel Pivot Tables, to get a nice overview.

 


Credits

This article builds on logic that has been documented by Adam Weigert

 


Prerequisites

For the procedure below you need

  • FIM Sync engine with sufficient run profile data (the bare necessities for statistics, is sufficient data.)
  • Permissions to run queries via Powershell on FIM ( member of the FIM/MIM Sync admins)
  • PowerShell script to pull data from the FIMSync database (download script here)
  • The powershell script uses a Powershell module for Excel, you need to unpack/install: https://github.com/dfinke/ImportExcel
  • An Excel Macro sheet to show the query data (download a template sheet here)  

 


Dependencies

To support the creation of XLSX Excel sheets from PowerShell you need to have a Powershell Module installed.

It's very likely you won't have internet access on your FIM Server (AND YOU SHOULDN'T!).

So you better download the package from the admin workstation., unzip it and copy the module directory to one of your PowerShell module directories on your FIM Server, where you will run the analysis script.

 


Preparation

Download Excel Module

Download and unpack: https://github.com/dfinke/ImportExcel

Preparing the Excel Module

To find the Powershell Module path, open a PS console and type:

$Env:PSModulePath

To make your life, you can manipulate the output to be more readable like:

($env:PSModulePath).split("{;}")

Output should be like:

C:\Users\user>\Documents\WindowsPowerShell\Modules

C:\Program Files\WindowsPowerShell\Modules

C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

C:\Program Files\Common Files\Microsoft Lync Server 2013\Modules

C:\Program Files\SharePoint Online Management Shell\

C:\Program Files\Common Files\Skype for Business Online\Modules\

PS C:\Windows\system32>

Typically you'll see a module path under: C:\Program Files\WindowsPowerShell\Modules.

Suggestion:

  • Better not install modules under your personal profile, cannot be accessed by other users.
  • By preference do not copy data under the Windows or System directory.

Install the Powershell module

When you inspect the install.ps1 file, you'll notice it will try to open a web connection.

For your admin station, thats' fine, but not for your FIM/MIM server.

And the zip file has everything on board.

Better unzip, create a module folder under the PS Module path and copy the required files to the subfolder.

The install.ps1 file explains which files you need:

 

EPPlus.dll `
ImportExcel.psd1 `
ImportExcel.psm1 `
Export-Excel.ps1 `
New-ConditionalFormattingIconSet.ps1 `
Export-ExcelSheet.ps1 `
New-ExcelChart.ps1 `
Invoke-Sum.ps1 `
InferData.ps1 `
Get-ExcelColumnName.ps1 `
Get-XYRange.ps1 `
Charting.ps1 `
New-PSItem.ps1 `
Pivot.ps1 `
New-ConditionalText.ps1 `
Get-HtmlTable.ps1 `
Import-Html.ps1 `
Get-ExcelSheetInfo.ps1 `
Get-Range.ps1 `
plot.ps1

Create a subfolder ImportExcel in the Powershell Modules folder, and next copy the files into it

Test the module by loading the module and running the script.

PS C:\Windows\system32> Import-Module importexcel

WARNING: PowerShell 5 is required for plot.ps1

WARNING: PowerShell Excel is ready, except for that functionality

 

PS C:\Windows\system32>


Data collection 

Powershell

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

064

065

066

067

068

069

070

071

072

073

074

075

076

077

078

079

080

081

082

083

084

085

086

087

088

089

090

091

092

093

094

095

096

097

098

099

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

param(  

    [string]   $ComputerName = '.',  

   [string[]] $MaName       = $null,  

   [string[]] $RunProfile   = $null

   )  

  

process {

        Write-Host "PowerShell Version"

        $psversiontable.PSVersion

        $host.version

        (get-host).Version

        write-host

        

        $resultPath = $PSScriptRoot + '\'

        $file = $MyInvocation.MyCommand.Definition -replace 'ps1','xlsx'

        rm $file -ErrorAction Ignore

          

        #

        $allrunprofiles =  Get-WmiObject -Class 'MIIS_RunHistory' -Namespace 'root\MicrosoftIdentityIntegrationServer' -Filter 'RunStatus != "in-progress"' `

        |? {([int]$MaName.Count -eq 0 -or $MaName -contains $_.MaName) -and ([int]$RunProfile.Count -eq 0 -or $RunProfile -contains $_.RunProfile) } 

    

        $dates = $allrunprofiles | Select-Object -Property @{Name='RunTime';Expression={[DateTime]::Parse($_.RunStartTime)}}| Sort-Object -Property RunTime

        

        $firstdate = $dates | Select-Object -Expand RunTime -First 1

        $firstdate

        $lastdate = $dates | Select-Object -Expand RunTime -Last 1

        $lastdate

        $firstdate.ToString() | Export-Excel $file -WorkSheetname 'StartDate'

        

        $lastdate.ToString() | Export-Excel $file -WorkSheetname 'LastDate'

    $runprofiles = $allrunprofiles| Select-Object -Property MaName,RunProfile,RunStatus, @{Name='RunTime';Expression={[DateTime]::Parse($_.RunEndTime).Subtract([DateTime]$_.RunStartTime)}}` `

    |? {([int]$MaName.Count -eq 0 -or $MaName -contains $_.MaName) -and ([int]$RunProfile.Count -eq 0 -or $RunProfile -contains $_.RunProfile) }

    #$runprofiles

    #process all runprofile

    #only process successful runs

    $selection = $runprofiles | where {$_.RunStatus -eq 'success'}

    

    $selection |

      Export-Excel $file -WorksheetName 'Min' `

        -IncludePivotTable `

        -PivotRows MaName `

        -PivotColumns RunProfile `

        -PivotData @{RunTime='Min'} `

        -PivotDataToColumn `

        -Numberformat 'uu:mm:ss'

        

    $selection |

      Export-Excel $file -WorksheetName 'Max' `

        -IncludePivotTable `

        -PivotRows MaName `

        -PivotColumns RunProfile `

        -PivotData @{RunTime='Max'} `

        -PivotDataToColumn `

        -Numberformat 'uu:mm:ss'

    $selection |

      Export-Excel $file -WorksheetName 'Average' `

        -IncludePivotTable `

        -PivotRows MaName `

        -PivotColumns RunProfile `

        -PivotData @{RunTime='Average'} `

        -PivotDataToColumn `

        -Numberformat 'uu:mm:ss'

        

    #process error data

    $selection = $runprofiles | where {$_.RunStatus -ne 'success'}

    

    $selection |

      Export-Excel $file -WorksheetName 'Errors' `

        -IncludePivotTable `

        -PivotRows MaName `

        -PivotColumns RunProfile `

        -PivotData @{RunTime='Count'} `

        -PivotDataToColumn `

        -Numberformat 'uu:mm:ss'

    $selection |

      Export-Excel $file -WorksheetName 'ErrorTypes' `

        -IncludePivotTable `

        -PivotRows MaName `

        -PivotColumns RunStatus `

        -PivotData @{RunStatus='Count'} `

        -PivotDataToColumn `

        -Numberformat 'uu:mm:ss'

# once the data is exported,

# you need to format the data cells with numbers/datetime to a date tiem format of uu:mm:ss

Import-Module psexcel

# Open the previously created Excel file...

    $Excel = New-Excel -Path $file

# Format Data Worksheet

$Sheetnames = 'Min', 'Max', 'Average', 'Errors', 'ErrorTypes'

foreach ($sheet in $Sheetnames)

{

    $Worksheet = $Excel | Get-Worksheet -Name $sheet

    $Worksheet | Format-Cell -StartColumn 4 -EndColumn 4 -Autofit -NumberFormat 'hh:mm:ss'

}

    

# Format Pivot Worksheet

$Sheetnames = 'MinPivotTable', 'MaxPivotTable', 'AveragePivotTable'

foreach ($sheet in $Sheetnames)

{

    $Worksheet = $Excel | Get-Worksheet -Name $sheet

    $Worksheet | Format-Cell -StartColumn 2 -EndColumn 8 -Autofit -NumberFormat 'hh:mm:ss'

}

# Save and close

    $Excel | Save-Excel -Close

}  

 


Generating Statistics

Preparing the Excel sheet

Download the Excel Macro sheet (download here: ).

Rename the template to a name of your choice. 

Transfer XLSX sheet

The PowerShell script has dumped the data into the XLSX data file, that does not contain any macro.

Most FIM administrators work via an RDP connection, which supports to copy/paste information from the FIM console from the admin workstation.

Enable developer tab

To run the macro, it might be helpful to enable the developer tab in Excel.

For more info see: How to: Show the Developer Tab on the Ribbon

 

Run the macro

The macro will search for an XLSX sheet with the same name as the XLSM. The macro will apply dateTime (hh:mm:ss) format to the PivotTables and add some nice conditional formatting colors.

Results

Before

After


Downloads

PowerShell

Excel

 


See also

 


References

  •  How to: Show the Developer Tab on the Ribbon