PowerShell

Active Directory: List all Network Shares from all Windows Servers

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.

3 replies »

  1. 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.

    Like

  2. 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

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.