Using Get-Childitem at root of UNC Path \\SERVERNAME

3.1k Views Asked by At

We're trying to use PowerShell as a file-replication tool, but having an issue.

The source server is a Linux-based closed OS, where users, through a GUI, create multiple network shares, which are then accessible by the UNC path \\SERVERNAME\NETWORKSHARE. In the OS, of course, the NETWORKSHARE is actually located multiple levels deeper than the root.

We've talked to the developer of the OS, and they cannot/will not enable access to the root of the folder where all the NETWORKSHARE folders are stored.

I've turned to PowerShell to try and find a way. My initial thinking was to send a Get-ChildItem -Directory to \\SERVERNAME to grab all the NETWORKSHARES, and then pipe that to Copy-Item/Robocopy, but it doesn't work.

I know the server needs their own local (non-AD) credentials.

Is there a way to do what I want to do that I'm just not seeing ?

Thanks in advance!

2

There are 2 best solutions below

4
AudioBubble On BEST ANSWER

The net view command with an IP will enumerate accessible SMB/Samba shares.
This PowerShell script parses the output and returns a [PSCustomObject] with Server and Share properties.

## Enum-SambaShares.ps1
$ServerList = ('192.168.133.67','192.168.133.46','192.168.133.76','192.168.133.28')
$ServerShares = ForEach ($Server in $ServerList) {
    net view "\\$Server" 2>$Null | Select-String '^([^ ]+)\s+(Disk|Platte)' | 
        ForEach-Object {
            [PSCustomObject]@{
                Server = $Server
                Share  = $_.matches.groups[1].Value
            }
        }
}
$ServerShares

Sample output:

Server        Share
------        -----
192.168.133.67 Backup
192.168.133.67 Daten
192.168.133.67 Video-Unc
192.168.133.46 SambaShare
192.168.133.46 UserName
192.168.133.76 C
192.168.133.28 McDaten
192.168.133.28 Music
192.168.133.28 UserName
2
Bill_Stewart On

Parsing the output of new view is a bit clumsy. Here's an approach that calls the NetShareEnum Win32 API directly from PowerShell and outputs the results as an object:

# Get-NetShare.ps1

#requires -version 2

param(
  [String] $ComputerName = "."
)

Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHARE_INFO_1
{
  [MarshalAs(UnmanagedType.LPWStr)]
  public string shi1_netname;
  public uint shi1_type;
  [MarshalAs(UnmanagedType.LPWStr)]
  public string shi1_remark;
}
public static class NetApi32
{
  [DllImport("netapi32.dll", SetLastError = true)]
  public static extern int NetApiBufferFree(IntPtr Buffer);
  [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
  public static extern int NetShareEnum(
    StringBuilder servername,
    int level,
    ref IntPtr bufptr,
    uint prefmaxlen,
    ref int entriesread,
    ref int totalentries,
    ref int resume_handle);
}
"@

$pBuffer = [IntPtr]::Zero
$entriesRead = $totalEntries = $resumeHandle = 0
$result = [NetApi32]::NetShareEnum(
  $ComputerName,        # servername
  1,                    # level
  [Ref] $pBuffer,       # bufptr
  [UInt32]::MaxValue,   # prefmaxlen
  [Ref] $entriesRead,   # entriesread
  [Ref] $totalEntries,  # totalentries
  [Ref] $resumeHandle   # resumehandle
)
if ( ($result -eq 0) -and ($pBuffer -ne [IntPtr]::Zero) -and ($entriesRead -eq $totalEntries) ) {
  $offset = $pBuffer.ToInt64()
  for ( $i = 0; $i -lt $totalEntries; $i++ ) {
    $pEntry = New-Object IntPtr($offset)
    $shareInfo = [Runtime.InteropServices.Marshal]::PtrToStructure($pEntry, [Type] [SHARE_INFO_1])
    $shareInfo
    $offset += [Runtime.InteropServices.Marshal]::SizeOf($shareInfo)
  }
  [Void] [NetApi32]::NetApiBufferFree($pBuffer)
}
if ( $result -ne 0 ) {
  Write-Error -Exception (New-Object ComponentModel.Win32Exception($result))
}

You can get disk shares of a remote computer thus:

Get-NetShare sambaservername | Where-Object { $_.shi1_type -eq 0 }