In today’s blog post I show how to retrieve all network shares from all servers in an Active Directory domain to get a nice list in the output. This script is used to document your Active Directory environment. Let’s get started.
Retrieve all Server by Name
First of all, we need to retrieve the server names.
# Retrieve Server Names
$server = Get-ADComputer -Filter 'operatingsystem -like "*server*"' | Select-Object -ExpandProperty Name
Short review.
Great!
Retrieving all Share Names of all Servers
Now the party begins. Since we have all the server names, we can use Invoke-Command and Get-SmbShare to retrieve all the shares.
# Collection Point
$result = @()
# Show all Shares of all Servers
foreach ($s in $server) {
$shares = Invoke-Command -ComputerName $s -ScriptBlock {Get-SmbShare | Select-Object PSComputerName,Name,Path}
$result += New-Object PSObject -Property ([ordered]@{
ServerName = $s
Shares = $shares.Name -join "`n"
Path = $shares.Path -join "`n"
})
}
Write-Output $result | Format-Table -AutoSize -Wrap
Hope this was helpful. Have a nice day.
Categories: PowerShell, Windows Server
You might want to add an online check. Something like $online = Test-Connection -ComputerName $server -Count 1 -Quiet
In a bigger enviroment there are for sure some computer objects that are not online and the script will take forever.
LikeLike
Hi Patrick,
You wrote ” $result += New-Object PSObject ….”
As a trainer, you should totally forget this way because it’s the slowest way. At each turn, $Result ( it’s an array) is recreated and this process is long.
– Use Array but outside the foreach loop
$Result = foreach (….} { @[Ordered]{ ….} …. }
$Result will be always an Array. $Result will be created once only.
-Better Use ArrayList
$Result = New-Object -TypeName ‘System.Collections.ArrayList’ # or faster [System.Collections.ArrayList]::new()
foreach (…..} { $Obj = @[Ordered]{ ….} …. $Result.add($Obj) …}
We use the method .add() of an ArrayList
– The Best use GenericList (ArrayList are deprecated (sse : https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-6.0#remarks)
$result = New-Object -TypeName ‘System.Collections.genericLilst[PSObject]’ # or faster [System.Collections.GenericList[PSObject]::new()
foreach (…..} { $Obj = @[Ordered]{ ….} …. $Result.add($Obj) …}
We use the method .add() of a GenericList.
If you have only few turn in the loop, there is no real performance difference. But, when there are many turn, it’s not the same. Array defined inside the loop are definitivly the slowest way.
sample :
Measure-Command -Expression {
for ($i = 1; $i -lt 100000; $i++)
{
$result +=$i
}
} # 3 min
Measure-Command -Expression {
$Result = for ($i = 1; $i -lt 100000; $i++)
{
$i
}
} # 0.124 sec
I’m thinking it’s important to provide good practices to beginners from the start.
Regards
LikeLike
Thank you for this performance tip! Will try it out with ArrayLists …
LikeLike