Skip to content

Instantly share code, notes, and snippets.

@cainejunkazama
Created August 7, 2013 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cainejunkazama/6178122 to your computer and use it in GitHub Desktop.
Save cainejunkazama/6178122 to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
Create a simple, yet good looking Employee Directory in HTML format.
.DESCRIPTION
Run this script and create a HTML based Employee Directory that your users
can use to locate each other's information. Supports title, extension, cell,
fax, description, manager, home page link and email. Also fully utilizies Active
Directory's ability to store photos and you will have the choice of how you
want to display those pictures, either hover over or click their first name or
last name to see the picture (you choose).
Script includes a search box and will dynamically generate a "button bar" for
searching for groups based on Location, Department or Manager.
When the script runs, it will not pull the photo from Active Directory if
the image file already exists in the $OutputPath\images directory. To fully refresh
all images (in case one is changed or removed) you just use the -Refresh parameter.
Recommend the script be run hourly to keep it up to date. Once a day I recommend
it be run with the -Refresh parameter, which will fully refresh all images
and delete any images from employee's no longer in Active Directory.
If you need a simple application for editing this information and for uploading
pictures to Active Directory, try my Employee Editor application:
http://community.spiceworks.com/scripts/show/1369-employee-directory-editor
The Office field (LDAP field name is physicalDeliveryOfficeName) is a key field for
the script. Put the word "Exclude" in the field and even if the object matches
the search parameter it will not be put in the Employee Directory. Any other
value in here will be used as the Location display field, if you use this as your
field to key the button bar off of, than you will get a custom button with whatever
value you put in that field. If the field is left blank then the script will
assign the default location parameter into the field (only on the Employee
Directory, Active Directory will not be updated).
.PARAMETER Title
Title used for the Employee Directory
.PARAMETER SearchOU
Comma separated search values. These values will be checked against the distinguished
name of every user and contact, if there is a match than that object will be
included in the directory.
.PARAMETER LocationDefault
Comma separated location names. This parameter has a one to one relationship with
SearchOU. So the first element in LocationDefault will be the default name of any
object that matches the first element in SearchOU. Second element in LocationDefault
to second element of SearchOU and so on.
.PARAMETER OutputPath
The destination where you place the resultant HTML page. Script will also
create a $OutputPath\Images directory if it does not already exist. All photo's
from Active Directory will be stored there.
.PARAMETER HTMLPath
Script will look for two files in this directory: Heading.HTML and CSS.HTML. If
Heading.HTML is located all contents will be inserted into the heading zone of the
Employee Directory. Use this for custom headings, banners, images or text that you
wish to include on your page. Text needs to be an HTML fragment, only including
the text you wish. Make sure there is no HTML, HEAD, BODY or other HTML tags.
If CSS.HTML is found, this will be used instead of the default CSS settings. Text
file should include CSS only, no HEAD or STYLE tags.
.PARAMETER Fields
Comma separated string with a list of the fields you want included in your
Employee Directory. Valid fields are:
Field Description
----- -----------
Picture Small 64x64 thumbnail of the employee photo. Hover over the
photo to see full sized version.
LastName Last Name
FirstName First Name
LNLink Last Name as a hyperlink to user's Web Page
LNLinkPic Last Name as a hyperlink to user's photo
FNLink First Name as a hyperlink to user's Web Page
FNLinkPic First Name as a hyperlink to user's photo
Ext Active Directory field: TelephoneNumber
Department Department
Title Title
Fax Fax
Email Email Address as mailto: hyperlink
Location Active Directory field: Office, if blank LocationDefault will be used
Link Active Directory field: Web Page
Cell Active Directory field: Mobile
Manager First and last name of user's Manager, if set
Description User's description field
.PARAMETER SortBy
Single field entry of which of the above fields you want to sort on. Valid entries
are: LastName, FirstName, Ext, Department, Title, Fax, Email, Location, Link, Cell, Manager
.PARAMETER ButtonBy
Create the button row based on the field in this parameter. Valid entries are:
Department, Location and Manager.
.PARAMETER Refresh
If specified this parameter will clear all images from the $OutputPath\Images
folder and freshly download everything from Active Directory. If not specified
it will only pull a photo from Active Directory if it does not already exist
in the $OutputPath\Images folder.
.INPUTS
Heading.HTML - Custom block for your HTML
CSS.HTML - Custom CSS
.OUTPUTS
EmployeeDirectory.HTML file
.EXAMPLE
.\Out-EmployeeDirectory.ps1
Runs the script with all defaults
.EXAMPLE
.\Out-EmployeeDirectory.ps1 -Title "YourCompany Rolodex" -Refresh
Runs the script setting the Title and with the $refresh being true, all images
will be deleted and re-downloaded from Active Directory.
.NOTES
Author: Martin Pugh
Twitter: @thesurlyadm1n
Spiceworks: Martin9700
Blog: www.thesurlyadmin.com
Changelog:
2.0 Major version upgrade! You can now choose what fields you want to display,
what field you want to sort on and what field you want to the button bar
to be based on. There is also the capacity to select which OU's you want
to include in the search (Regex search). You can also have a section for
custom information (imported from a file--HTML format) and you can import
custom CSS. Verbose output is available during testing, if you want to
see it.
1.01 No functional change, updated comment-based help and a couple
of small formatting pieces here and there. Also changed the
REFRESH parameter to a switch type to make it a little
friendlier to use.
1.0 Initial Release
.LINK
http://thesurlyadmin.com/2013/05/16/new-version-employee-directory/
.LINK
http://community.spiceworks.com/scripts/show/1652-create-employee-directory-web-page
.LINK
http://community.spiceworks.com/scripts/show/1369-employee-directory-editor
#>
[CmdletBinding()]
Param (
[string]$Title = "Spiceworks Employee Directory",
[string[]]$SearchOU = ("OU=Boston","OU=NewYork","OU=Gaithersburg","OU=Faxes"),
[String[]]$LocationDefault = ("Boston","New York","Gaithersburg","Boston"),
[ValidateScript({Test-Path $_ -PathType Container})]
[string]$OutputPath = "\\server\wwwshare",
[ValidateScript({Test-Path $_})]
[string]$HTMLPath = (Split-Path $MyInvocation.MyCommand.Path),
[ValidatePattern("Picture|LastName|FirstName|LNLink|LNLinkPic|FNLink|FNLinkPic|Ext|Department|Title|Fax|Email|Location|Link|Cell|Manager|Description")]
[string]$Fields = "Picture,LastName,FirstName,Title,Manager,Location,Ext,Cell,Fax,Email",
[ValidatePattern("LastName|FirstName|Ext|Department|Title|Fax|Email|Location|Link|Cell|Manager")]
[string]$SortBy = "LastName",
[ValidatePattern("Department|Location|Manager")]
[string]$ButtonBy = "Location",
[switch]$Refresh
)
#Setup
Write-Verbose "$(Get-Date): Script begins"
$ImagesPath = "$OutputPath\images"
#Check if paths exist
If (-not (Test-Path $OutputPath -PathType Container))
{ Write-Error "`nPath $OutputPath does not exist, script cannot continue."
Exit
}
Else
{ If (-not (Test-Path $ImagesPath))
{ Write-Verbose "$(Get-Date): $ImagesPath not detected, attempting to create"
Try {
New-Item -Path $ImagesPath -ItemType Directory -ErrorAction Stop | Out-Null
}
Catch {
Write-Error $Error[0]
Exit
}
}
}
#Verify all field entries are good
$Regex = "Picture|LastName|FirstName|LNLink|LNLinkPic|FNLink|FNLinkPic|Ext|Department|Title|Fax|Email|Location|Link|Cell|Manager|Description"
ForEach ($Field in $Fields.Split(","))
{ If ($Field -notmatch $Regex)
{ Write-Error "Field: $Field, is not a valid field"
Exit
}
}
#Determine Filter Column
If (-not ($ButtonBy -match "Department|Location|Manager"))
{ Write-Error "ButtonBy must be either Department, Location or Manager. Set to: $ButtonBy"
Exit
}
Else
{ $FilterColumn = 0
ForEach ($Column in $Fields.Split(","))
{ If ($Column -eq $ButtonBy)
{ $Found = $true
Break
}
$FilterColumn ++
}
If (-not $Found)
{ Write-Error "ButtonBy parameter does not match a specified field"
Exit
}
}
#Verify Good Sort Field
$Regex = $Fields.Replace(",","|") + "|LastName|FirstName"
If ($SortBy -notmatch $Regex)
{ Write-Error "SortBy parameter does not match a specified field in `$Fields"
Exit
}
#Change the Search parameter to Regex
$SearchRegexOU = $SearchOU -join "|"
$SearchRegexOU = $SearchRegexOU.Replace("/","\/") #Escape some likely characters
$SearchRegexOU = $SearchRegexOU.Replace(".","\.")
Write-Verbose "$(Get-Date): Search: $SearchRegexOU"
Write-Verbose "$(Get-Date): Output Path: $OutputPath"
Write-Verbose "$(Get-Date): Images Path: $ImagesPath"
#Refresh images?
If ($Refresh)
{ Write-Verbose "$(Get-Date): Full refresh requested, deleting old images..."
Try {
Remove-Item $ImagesPath\*.jpg -Force -ErrorAction Stop
}
Catch {
Write-Error $Error[0]
Exit
}
}
#Custom heading?
If (Test-Path $HTMLPath\Heading.HTML)
{ Write-Verbose "$(Get-Date): Custom heading detected $HTMLPath\Heading.HTML. Adding to Employee Directory"
$HeadingHTML = Get-Content $HTMLPath\Heading.HTML
}
Else
{ Write-Verbose "$(Get-Date): Custom $HeadingPath\Heading.HTML not found, will not be included in Employee Directory"
}
#Custom CSS?
If (Test-Path $HTMLPath\CSS.HTML)
{ Write-Verbose "$(Get-Date): Custom CSS detected $HTMLPath\CSS.HTML overriding default CSS"
$CSSHTML = Get-Content $HTMLPath\CSS.HTML
}
Else
{ Write-Verbose "$(Get-Date): No Custom CSS detected, using default"
#Define Default CSS
$CSSHTML = @"
form {
margin: 0;
}
table {
background:#D3E4E5;
border:1px solid gray;
border-collapse:collapse;
color:#fff;
font:normal 12px verdana, arial, helvetica, sans-serif;
width:95%;
}
caption { border:1px solid #5C443A;
color:#5C443A;
font-weight:bold;
padding:6px 4px 8px 0px;
text-align:center;
}
td, th { color:#363636;
padding:.4em;
}
tr { border:1px dotted gray;
}
thead th, tfoot th { background:#5C443A;
color:#FFFFFF;
padding:3px 10px 3px 10px;
text-align:left;
text-transform:uppercase;
}
tbody th, tbody td { text-align:left;
vertical-align:top;
}
tbody tr:hover { background:#99BCBF;
border:1px solid #03476F;
color:#000000;
}
"@ #End Default CSS
} #End Custom or Default CSS
#Additional CSS
$CSSHTML += @"
.styleHidePicture {
position:absolute;
visibility:hidden;
}
.styleShowPicture {
position:absolute;
visibility:visible;
border:solid 7px Black;
padding:1px;
}
"@
$JSHTML = @"
<BODY>
<script type='text/javascript'>
function filter (phrase, _id){
var words = phrase.value.toLowerCase().split(" ");
var table = document.getElementById(_id);
var ele;
for (var r = 1; r < table.rows.length; r++){
ele = table.rows[r].innerHTML.replace(/<[^>]+>/g,"");
var displayStyle = 'none';
for (var i = 0; i < words.length; i++) {
if (ele.toLowerCase().indexOf(words[i])>=0)
displayStyle = '';
else {
displayStyle = 'none';
break;
}
}
table.rows[r].style.display = displayStyle;
}
}
function filtbutton(phrase){
var tableMain = document.getElementById('TableMain');
for(i=1;i<tableMain.rows.length;i++){
ele = tableMain.rows[i].innerHTML.replace(/<[^>]+>/g,"");
tableMain.rows[i].style.display = '';}
for(i=1;i<tableMain.rows.length;i++){
ele = tableMain.rows[i].cells[$FilterColumn].innerHTML.replace(/<[^>]+>/g,"");
if (ele != phrase && phrase != '') {
tableMain.rows[i].style.display = 'none';
} else {
}
}
}
<!--
function ShowPicture(id) {
var currentDiv = document.getElementById(id);
currentDiv.className='styleShowPicture'
}
function HidePicture(id) {
var currentDiv = document.getElementById(id);
currentDiv.className='styleHidePicture'
}
//-->
</script>
"@ #End JSHTML
$HeaderHTML = @"
<HTML>
<HEAD>
<TITLE>$Title</TITLE>
<style type='text/css'>
"@ #End HeaderHTML
$EndHeaderHTML = @"
</style>
</HEAD>
"@ #End EndHeaderHTML
$SearchHTML = @"
</tr></table><table id='Filterline'><TD><div align='right'><FORM><FONT face='verdana,arial,helvetica,sans-serif' size=2><b>Search: </b></FONT><input name='filt' onkeyup="filter(this, 'TableMain', '1')" type='text'></FORM></div><br></TD>
</TABLE>
"@ #End SearchHTML
$FooterHTML = @"
</TBODY>
</TABLE>
</BODY>
</HTML>
"@ #End FooterHTML
#Functions
#region Functions
Function Set-Grid {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[object[]]$HTMLInput
)
Begin {
$HTMLOutput = @()
}
Process {
ForEach ($Line in $HTMLInput)
{
Switch -regex ($Line)
{ "<td>\[image\](.*?)<\/td>"
{ If ($Data[$Matches[1]].PicturePath)
{ $Line = $Line.Replace("[image]$($Matches[1])","<a onMouseOver=""ShowPicture('div$($Data[$Matches[1]].SamAccountName)')"" onMouseOut=""HidePicture('div$($Data[$Matches[1]].SamAccountName)')""><img src="".\images\$($Data[$Matches[1]].SamAccountName).jpg"" height=64 width=64></a><div class=""styleHidePicture"" id=""div$($Data[$Matches[1]].SamAccountName)""><img src="".\images\$($Data[$Matches[1]].SamAccountName).jpg""></div>")
}
Else
{ $Line = $Line.Replace("[image]$($Matches[1])","")
}
} #End Image
"<td>\[email\](.*?)<\/td>"
{ If ($Matches[1])
{ $Line = $Line.Replace("[email]$($Matches[1])","<a href=""mailto:$($Matches[1])"" TITLE=""Click to E-mail Employee"">$($Matches[1])</a>")
}
Else
{ $Line = $Line.Replace("[email]","")
}
} #End Email
"<td>\[fnlinkpic\](.*?)<\/td>"
{ If ($Data[$Matches[1]].FirstName)
{ $FN = $Data[$Matches[1]].FirstName
}
Else
{ $FN = "Link"
}
If ($Data[$Matches[1]].PicturePath)
{ $Line = $Line.Replace("[fnlinkpic]$($Matches[1])","<a href=""$($Data[$Matches[1]].PicturePath)"">$FN</a>")
}
Else
{ $Line = $Line.Replace("[fnlinkpic]$($Matches[1])",$FN.Replace("Link",""))
}
} #End FirstName Link to Pic
"<td>\[lnlinkpic\](.*?)<\/td>"
{ If ($Data[$Matches[1]].LastName)
{ $LN = $Data[$Matches[1]].LastName
}
Else
{ $LN = "Link"
}
If ($Data[$Matches[1]].PicturePath)
{ $Line = $Line.Replace("[lnlinkpic]$($Matches[1])","<a href=""$($Data[$Matches[1]].PicturePath)"">$LN</a>")
}
Else
{ $Line = $Line.Replace("[lnlinkpic]$($Matches[1])",$LN.Replace("Link",""))
}
} #End LastName Link to Pic
"<td>\[fnlink\](.*?)<\/td>"
{ $DN = $Matches[1]
If ($Data[$DN].FirstName)
{ $FN = $Data[$DN].FirstName
}
Else
{ $FN = "Link"
} #End If
If ($Data[$DN].URL)
{ $Link = Set-URL $Data[$DN].URL
$Line = $Line.Replace("[fnlink]$DN","<a href=""$Link"" target=""_blank"">$FN</a>")
}
Else
{ $Line = $Line.Replace("[fnlink]$($Matches[1])",$FN.Replace("Link",""))
} #End If
} #End FirstName Link to Home Page
"<td>\[lnlink\](.*?)<\/td>"
{ $DN = $Matches[1]
If ($Data[$DN].LastName)
{ $LN = $Data[$DN].LastName
}
Else
{ $LN = "Link"
} #End If
If ($Data[$DN].URL)
{ $Link = Set-URL $Data[$DN].URL
$Line = $Line.Replace("[lnlink]$DN","<a href=""$Link"" target=""_blank"">$LN</a>")
}
Else
{ $Line = $Line.Replace("[lnlink]$($Matches[1])",$LN.Replace("Link",""))
} #End If
} #End LastName Link to Home Page
"<td>\[link\](.*?)<\/td>"
{ $DN = $Matches[1]
If ($Data[$DN].URL)
{ $Link = Set-URL $Data[$DN].URL
$Line = $Line.Replace("[link]$DN","<a href=""$Link"" TITLE=""Home Page"" target=""_blank"">Home Page</a>")
}
Else
{ $Line = $Line.Replace("[link]$DN","")
}
} #End Link to Home Page
} #End Switch
$Line = $Line.Replace("<table>","<table id='TableMain'>")
$Line = $Line.Replace("<colgroup>","")
$Line = $Line.Replace("<col/>","")
$Line = $Line.Replace("</colgroup>","<CAPTION><h2>$Title</h2></CAPTION><THEAD>")
$Line = $Line.Replace("</th></tr>","</th></TR></THEAD><TBODY>")
$Line = $Line.Replace("</table>","")
$Line = $Line.Replace("FirstName","First Name")
$Line = $Line.Replace("FNLinkPic","First Name")
$Line = $Line.Replace("FNLink","First Name")
$Line = $Line.Replace("LastName","Last Name")
$Line = $Line.Replace("LNLinkPic","Last Name")
$Line = $Line.Replace("LNLink","Last Name")
$HTMLOutput += $Line
} #End ForEach
} #End Process
End {
Return $HTMLOutput
} #End End
} #End Set-Grid Function
Function Set-URL
{ Param (
[string]$URL
)
If ($URL -match "https?:\/\/")
{ $Link = $URL
}
Else
{ If ($URL)
{ $Link = "http://$URL"
}
Else
{ $Link = $null
}
} #End If
Return $Link
} #End Set-URL Function
#endregion
#Get User Information load it into an object for later
Write-Verbose "$(Get-Date): Gathering data from Active Directory"
$Domain = New-Object System.DirectoryServices.DirectoryEntry("")
$ADSearch = New-Object System.DirectoryServices.DirectorySearcher
$ADSearch.SearchRoot = $Domain
$ADSearch.SearchScope = "Subtree"
$ADSearch.Filter = "(objectCategory=User)"
$PropertiesToLoad = "SamAccountName,useraccountcontrol,distinguishedname,GivenName,sn,Title,description,department,physicaldeliveryofficename,manager,TelephoneNumber,Mobile,facsimiletelephonenumber,mail,thumbnailphoto,wwwhomepage,description"
ForEach ($Property in $($PropertiesToLoad.Split(",")))
{ $ADSearch.PropertiesToLoad.Add($Property) | Out-Null
}
$Users = $ADSearch.FindAll()
$Data = @{}
ForEach ($User in $Users)
{ #Filter out users who don't fall within the search parameters
If ($($User.Properties.distinguishedname) -notmatch $SearchRegexOU)
{ Continue
}
#Filter out users with the word 'Exclude' in the department field
If ($($User.Properties.physicaldeliveryofficename))
{ If ($($User.Properties.physicaldeliveryofficename).ToUpper() -eq "EXCLUDE")
{ Continue
}
}
#Filter out any disabled users
If ($($User.Properties.useraccountcontrol) -band 0x2)
{ Continue
}
#Retrieve the Picture
$File = "$ImagesPath\$($User.Properties.samaccountname).jpg"
If (-not (Test-Path $File))
{ If (($User.Properties.thumbnailphoto).Count)
{ Try {
$User.Properties.thumbnailphoto | Set-Content -Path $File -Encoding Byte -ErrorAction Stop
}
Catch {
Write-Error "Unable to save thumbnail to $ImagesPath, see above error. Aborting script."
Break
}
}
Else
{ $File = $null
}
}
#Now load the data
$Object = New-Object PSObject -Property @{
LastName = $($User.Properties.sn)
FirstName = $($User.Properties.givenname)
Title = $($User.Properties.title)
Department = $($User.Properties.department)
Location = $($User.Properties.physicaldeliveryofficename)
Manager = $($User.Properties.manager)
Ext = $($User.Properties.telephonenumber)
Cell = $($User.Properties.mobile)
Fax = $($User.Properties.facsimiletelephonenumber)
Email = "[email]$($User.Properties.mail)"
SamAccountName = $($User.Properties.samaccountname)
Picture = "[image]$($User.Properties.distinguishedname)"
PicturePath = $File
URL = $($User.Properties.wwwhomepage)
Link = "[link]$($User.Properties.distinguishedname)"
FNLinkPic = "[fnlinkpic]$($User.Properties.distinguishedname)"
LNLinkPic = "[lnlinkpic]$($User.Properties.distinguishedname)"
FNLink = "[fnlink]$($User.Properties.distinguishedname)"
LNLink = "[lnlink]$($User.Properties.distinguishedname)"
Description = $($User.Properties.description)
}
$Data.Add($($User.Properties.distinguishedname),$Object)
}
#Populate Manager and Default Location
ForEach ($User in $Data.Values)
{ If ($User.Manager)
{ $User.Manager = "$($Data[$User.Manager].FirstName) $($Data[$User.Manager].LastName)"
}
If ($User.Location)
{ $User.Location = $User.Location.Trim()
}
If ([string]::IsNullOrEmpty($User.Location))
{ For ($i = 0;$i -le ($SearchOU.Count - 1);$i++)
{ If ($User.Link -like "*$($SearchOU[$i])*")
{ $User.Location = $LocationDefault[$i]
Break
}
}
}
} #End ForEach
#Build the Button row
Write-Verbose "$(Get-Date): Building the HTML"
$Buttons = $Data.Values | Select $ButtonBy -Unique | Sort $ButtonBy
$ButtonHTML = @"
<TABLE id='Filterbutton'>
<TD><input id="All" value="All" onClick="filtbutton('')" type="button"/></TD>
"@
$MaxButtons = 2
ForEach ($Button in $Buttons)
{ If ($Button)
{ $MaxButtons ++
$ButtonHTML += "<TD><input id=""$($Button.$ButtonBy)"" value=""$($Button.$ButtonBy)"" onClick=""filtbutton('$($Button.$ButtonBy)')"" type=""button""/></TD>`n"
If ($MaxButtons -eq 9)
{ $MaxButtons = 1
$ButtonHTML += "</tr><tr>`n"
}
}
}
#Build the detail HTML
$GridHTML = $Data.Values | Sort $SortBy | Select $($Fields.Split(",")) | ConvertTo-Html -Fragment | Set-Grid
#Put it together and save
$HeadHTML = $HeaderHTML + $CSSHTML + $EndHeaderHTML + $JSHTML
$FullHTML = $HeadHTML + $HeadingHTML + $ButtonHTML + $SearchHTML + $GridHTML + $FooterHTML
Write-Verbose "$(Get-Date): Saving HTML: $OutputPath\EmployeeDirectory.html"
$FullHTML | Out-File $OutputPath\EmployeeDirectory.html
#& $OutputPath\EmployeeDirectory.html #Un-remark if you wish to have the page displayed automatically in your browser
Write-Verbose "$(Get-Date): Script completed"
@martin9700
Copy link

Thanks for posting this, but this should not be considered the actual code. Watch the Spiceworks link for any official updates.

@Chris20man
Copy link

Hello, hoping someone might be able to help. My employer uses this employee directory listing on our intranet. We have a number of employees with an apostrophe in their surnames, and as such it doesn't bring back their image. I've tried adding in .replace("'","") and -replace "'","" in countless different places in the code but just can't get it to work.

Through process of elimination it seems the offending line is:

Picture = "[image]$($User.Properties.distinguishedname)"

The distinguished name value is as follows:

CN=John O'Loghlen,OU=STAFF,OU=MPLAINS USERS,DC=Mplains,DC=qld,DC=gov,DC=au

which still has an apostrophe. I can't see where or how to remove the apostrophe's from this field before attempting to call it? Thanks for any help from anyone!

Cheers,
Chris

@saschatrebbin
Copy link

I haven't used this code almost as long as I have it posted here, so you'll probably have more luck on Spiceworks, where I found that code. Or maybe r/powershell on reddit. I also don't have any AD to test this against currently, so I can only guess.

From a quick glance the Set-Grid function seems to use the samaccountname for embedding the filepath. That filepath to the picture is built on line 558. So you should be able to manipulate the image retrieval by inserting your replace action directly before that.

If you really need to manipulate the distinguishedname, that should happen directly before the line 541.

That is at least the spot where that $Data hashmap is built, which the Set-Grid function uses for building the output. So if you need to alter something, this should be the place, where it needs to happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment