
本文介绍在 go 程序中探测远程 windows 计算机(如 computera)所公开的共享文件夹(smb 共享)的方法,由于标准库不支持 unc 根路径枚举,需借助系统命令(如 `net view`)并安全解析其输出。
Go 的标准库(如 os, io/ioutil(已弃用,推荐 os.ReadDir)或 net 包)无法直接枚举远程主机的共享列表。调用 os.ReadDir("\\\\ComputerA") 会失败,因为 UNC 路径 \\\\ComputerA 并非一个可遍历的“目录”,而是一个 SMB 共享命名空间入口——该操作需由 Windows 网络重定向器(RDR)配合 Server Message Block (SMB) 协议的 NetShareEnum 类底层 API 完成,而 Go 标准库未封装此功能。
因此,跨平台兼容性虽受限,但在 Windows 环境下最实用、可靠的方式是调用系统内置命令:
✅ 推荐方案:使用 net view 命令(Windows)
net view \ComputerA 可列出目标计算机发布的所有共享资源(含共享名、类型和备注)。示例输出:
Shared resources at \\ComputerA Share name Type Used as Comment ------------------------------------------------------------------------------- Source Disk Source code repository Backup Disk Daily backup volume IPC$ IPC Remote IPC The command completed successfully.
在 Go 中执行并解析:
package main
import (
"bufio"
"fmt"
"os/exec"
"strings"
)
func listShares(hostname string) ([]string, error) {
cmd := exec.Command("net", "view", "\\\\"+hostname)
output, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("failed to run net view: %w", err)
}
var shares []string
scanner := bufio.NewScanner(strings.NewReader(string(output)))
inShareSection := false
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// 跳过空行和分隔线
if line == "" || strings.HasPrefix(line, "-") || strings.Contains(line, "command completed") {
continue
}
// 找到共享表头后开始采集
if strings.Contains(line, "Share name") {
inShareSection = true
continue
}
if !inShareSection {
continue
}
// 提取第一列(共享名),跳过 IPC$ 和 admin$ 等系统共享(可选)
fields := strings.Fields(line)
if len(fields) > 0 {
shareName := fields[0]
if shareName != "IPC$" && !strings.HasSuffix(shareName, "$") {
shares = append(shares, shareName)
}
}
}
return shares, scanner.Err()
}
func main() {
shares, err := listShares("ComputerA")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Discovered shares on ComputerA: %v\n", shares)
// 示例输出: Discovered shares on ComputerA: [Source Backup]
}⚠️ 注意事项与最佳实践
- 权限与网络可达性:net view 依赖 SMB 协议通信,要求目标主机启用“网络发现”和“文件和打印机共享”,且当前用户具有访问该计算机共享枚举的权限(通常需属于同一域或配置了正确的本地账户凭据)。
- 安全性:避免拼接不可信的 hostname 字符串到命令中(防命令注入),建议对输入做白名单校验(如仅允许字母、数字、短横线、点号)。
- 错误处理:net view 在目标离线、防火墙拦截或 NetBIOS/SMB 服务未启用时会返回非零退出码,应检查 exec.ExitError 并提供清晰提示。
- 跨平台限制:Linux/macOS 无原生 net view;若需跨平台,可考虑调用 smbclient -L //ComputerA -N(需预装 Samba 工具),但需额外处理认证与输出格式差异。
- 替代方案(进阶):可通过 CGO 调用 Windows API NetShareEnum(syscall 或第三方库如 golang.org/x/sys/windows),但开发复杂度高、维护成本大,一般项目中 net view 已足够稳健。
综上,利用 exec.Command 调用 net view 是当前 Go 生态中发现 Windows 远程共享最简洁、可靠且无需外部依赖的方案。它复用了操作系统原生能力,稳定兼容各 Windows 版本,并易于集成到自动化运维或网络扫描类工具中。










