【问题标题】:Using Get-Childitem at root of UNC Path \\SERVERNAME在 UNC 路径 \\SERVERNAME 的根目录使用 Get-Childitem
【发布时间】:2017-07-13 19:35:51
【问题描述】:

我们正在尝试将 PowerShell 用作文件复制工具,但遇到了问题。

源服务器是一个基于 Linux 的封闭式操作系统,用户通过 GUI 创建多个网络共享,然后可以通过 UNC 路径 \\SERVERNAME\NETWORKSHARE 访问这些网络共享。当然,在 OS 中,NETWORKSHARE 实际上位于比 root 更深的多个级别。

我们已经与操作系统的开发人员进行了交谈,他们不能/不会启用对存储所有 NETWORKSHARE 文件夹的文件夹根目录的访问权限。

我已经求助于 PowerShell 来尝试寻找方法。我最初的想法是发送Get-ChildItem -Directory 到\\SERVERNAME 以获取所有网络共享,然后通过管道将其发送到Copy-Item/Robocopy,但它不起作用。

我知道服务器需要自己的本地(非 AD)凭据。

有没有办法做我想做却没看到的事情?

提前致谢!

【问题讨论】:

    标签: powershell get-childitem network-shares


    【解决方案1】:

    带有 IP 的 net view 命令将枚举可访问的 SMB/Samba 共享。
    此 PowerShell 脚本解析输出并返回具有 Server 和 Share 属性的 [PSCustomObject]。

    ## 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
    

    示例输出:

    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
    

    【讨论】:

    • 是的!这几乎正​​是我所需要的。结果很完美,但缺少的一件事是我需要这个脚本以远程服务器上的本地用户身份访问远程服务器,我该怎么做呢?
    • 好吧,您可以使用 net use 对服务器进行身份验证,但这需要共享 net use \\server\share /user:test testpassword
    • 是的,我知道这一点,因此我的问题。如果服务器,我甚至需要使用远程服务器凭据来访问根目录。
    • Welp,别在意这个问题。无法将凭据传递给 Net View,但是,我能够手动将凭据添加到凭据管理器,现在似乎一切正常。稍后只需要在另一个 VM 上进行最后一次尝试。感谢您的帮助,它将在我们的服务器备份期间为我们节省大量时间!
    【解决方案2】:

    解析new view 的输出有点笨拙。这是一种直接从 PowerShell 调用 NetShareEnum Win32 API 并将结果作为对象输出的方法:

    # 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))
    }
    

    您可以通过以下方式获取远程计算机的磁盘共享:

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

    【讨论】:

    • 这将是完美的,但源操作系统是基于 Linux 的,而不是基于 Windows 的,所以在另一端没有 WMI 可以回答:P
    • @AlexPilon - 查看我更新的 PowerShell 答案,它直接调用 Windows API(不解析net view 的输出)。
    猜你喜欢
    • 2013-11-15
    • 2020-06-16
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多