Greetings, Venerable Ones,
Lots of organizations use Global Security Groups. I have been working on a script that gets a list of users, lists all of their groups, and then creates a matrix in excel to display which groups each of the user objects is a member of. It is quite handy when trying to decipher how objects differ from one another. I am running into an issue though that I was hoping you might be able to help me with. After the script completes creating the matrix, (because I am too lazy to do it via the gui), I want Powershell to autosum both the Columns and Rows so that when my downline techs run the script, they can see how many users are members of each group, and how many groups each user is a member of.
I think the problem that I am running into is that in trying to variable-ize the excel range, the ":" character is not recognized as a delimiter, but rather as part of the variable ( as in $env:username ), and I am not "gettin' jiggy" with VBA vs. Powershell. Could you shine a light on this, and help me with the xlSum function? The state in which it is in right now only handles the logic for one axis, and I admit, ashamedly, that it does not work... Perhaps you could reveal some magical way to do all of this in only 14 lines that would make me feel way totally inadequate too? Powershell Gurus, can you help me land this plane???
#CompareUserGroupMembershipsFromList.ps1#[string](0..9|%{[char][int](32+("45737569004673677976").substring(($_*2),2))})-replace "\s{1}\b"
# save list.txt file in same directory as script with LogonNames (one per line) example follows:
#CarlHungus
#nio
#morpheus
#spock
cls
$erroractionpreference = "SilentlyContinue"
Import-Module ActiveDirectory
$currentfolder = split-path $myinvocation.mycommand.path
$groups = ""
$userlist = GC $currentfolder\list.txt | sort
if (test-path $currentfolder\temp.txt) {remove-item $currentfolder\temp.txt}
if (test-path $currentfolder\MasterGroupList.txt) {remove-item $currentfolder\MasterGroupList.txt}
if (test-path $currentfolder\UserCNs.txt) {remove-item "$currentfolder\UserCNs.txt"}
Foreach ($user in $userlist)
{
$array = @()
$array2 = @()
$groups = Get-AdUser -Identity $user -property "MemberOf"
$sortedGroups = $groups.memberof | Sort | Get-Unique
Foreach($group in $sortedGroups)
{$array +=$group}
$number = $array.count
foreach ($item in $array)
{
$1 = $item -replace "CN\=",""
$2 = $1 -replace "^*,OU\=.*$",""
$3 = $2 -replace "^*,Users.*$",""
$4 = $3 -replace "^*,Builtin.*$",""
add-content $currentfolder\temp.txt $4
}
}
$MasterGroupList = gc $currentfolder\temp.txt | sort | Get-Unique
remove-item $currentfolder\temp.txt
foreach ($schlub in $MasterGroupList)
{add-content $currentfolder\MasterGroupList.txt $schlub}
# some Excel Constants
# line styles
$xlLineStyleNone = -4142
$xlContinuous = 1
$xlDash = -4115
$a = New-Object -comobject Excel.Application
$a.Visible = $true
$functions = $a.WorkSheetfunction
$b = $a.Workbooks.Add()
$WS=$a.ActiveSheet
$cells = $WS.Cells
$date = Get-Date
#define some variables to control navigation
$row=1
$col=2
$WS.UsedRange.Borders.LineStyle = $xlContinuous
$blue = 255
$green= 0
$red = 0
$a = 1
$WS.UsedRange.Borders.Color = $a
$WS.UsedRange.Borders.Weight = $xlThin
$WS.Application.ActiveWindow.SplitColumn = 1
$WS.Application.ActiveWindow.SplitRow = 1
$WS.Application.ActiveWindow.FreezePanes=$true
#insert column headings
GC $currentfolder\MasterGroupList.txt | foreach {
$cells.item($row,$col)=$_
$cells.item($row,$col).font.bold=$False
$cells.item($row,$col).Orientation = 90
$cells.EntireColumn.AutoFit() | Out-Null
$WS.UsedRange.Borders.LineStyle = $xlContinuous
$col++
}
$row=2
$col=1
$blarb = Get-Content ("$currentfolder\list.txt") | Sort #
foreach ($slarb in $blarb)
{
$CN = Get-AdUser -filter 'SamAccountName -eq $slarb'
Add-Content "$currentfolder\UserCNs.txt" $CN
}
$GroupList = @{}
Function IsMember ($ADObject, $GroupName)
{
If ($GroupList.ContainsKey($ADObject.sAMAccountName.ToString() + "\") -eq $False)
{
$GroupList.Add($ADObject.sAMAccountName.ToString() + "\", $True)
$ADObject.psbase.RefreshCache("tokenGroups")
$SIDs = $ADObject.psbase.Properties.Item("tokenGroups")
ForEach ($Value In $SIDs)
{
$SID = New-Object System.Security.Principal.SecurityIdentifier $Value, 0
$Group = $SID.Translate([System.Security.Principal.NTAccount])
$GroupList.Add($ADObject.sAMAccountName.ToString() + "\" + $Group.Value.Split("\")[1], $True)
}
}
If ($GroupList.ContainsKey($ADObject.sAMAccountName.ToString() + "\" + $GroupName)) {Return $True}
Else {Return $False }
}
$UserCNs = Get-Content("$currentfolder\UserCNs.txt")
foreach ($item in $UserCNs)
{
$User = [ADSI]"LDAP://$item"
$3 = $item -replace "CN\=",""
$4 = $3 -replace "^*,OU\=.*$",""
$x=1
$y=2
foreach ($habba in Get-content $currentfolder\MasterGroupList.txt)
{
If (IsMember $User $habba -eq $True)
{ write-host Yes,$habba,$User.sAMAccountName -Foregroundcolor green
$cells.item($row,$col)=$4
$cells.EntireColumn.AutoFit() | Out-Null
$cells.item($row,$col).font.bold=$True
$WS.Cells.Item($row,$y).Value() =1;$WS.Cells.Item($row,$y).Interior.ColorIndex = 34#;$WS.Cells.Item($row,$y).HorizontalAlignment = -4108
}
Else
{
write-host No,$habba,$Computer.sAMAccountName -Foregroundcolor red
}
$y++
$WS.UsedRange.Borders.LineStyle = $xlContinuous
}
$Row++
}
if (test-path $currentfolder\MasterGroupList.txt) {remove-item $currentfolder\MasterGroupList.txt}
if (test-path $currentfolder\UserCNs.txt) {remove-item "$currentfolder\UserCNs.txt"}
Function Convert-NumberToA1
{
Param([parameter(Mandatory=$true)]
[int]$number)
$a1Value = $null
While ($number -gt 0) {
$multiplier = [int][system.math]::Floor(($number / 26))
$charNumber = $number - ($multiplier * 26)
If ($charNumber -eq 0) { $multiplier-- ; $charNumber = 26 }
$a1Value = [char]($charNumber + 64) + $a1Value
$number = $multiplier
}
Return $a1Value
}
#
Function xlSum
{
$range = $WS.usedRange
$rows = $range.rows.count # Takes you to the last used row
$cols = $range.columns.count # Takes you to the last used column
$Sumrow = $rows + 1
$Sumcol = $cols + 1
write-host row summary $Sumrow
write-host column summary $Sumcol
$Q=2
do
{
write-host $Q
$Y=2
$p = Convert-NumberToA1 ($Q)
$grid1 = "$p$Y".ToString()
$grid2 = "$p$rows".ToString()
$r = $WS.Range("'$grid1':'$grid2'")
$WS.cells.item($p,$Sumrow) = $functions.sum($r)
[void]$range.entireColumn.Autofit()
$Q++
}
while ($Q -lt $rows)
} # End Function
xlSum
#End Script