VPN 就绪前就映射驱动器?以服务器为准
登录脚本在隧道还没有路由时就映射共享。轮询一台只能经隧道访问的服务器,然后在用户会话中映射并记录结果。
登录时盘符出现了,随后却打开成空文件夹,或者显示红叉并提示网络资源不可用。权限通常没问题。真正发生的是:映射命令在 VPN 客户端已存在、但到文件服务器还没有路由的那个窗口里执行了,Windows 把这次失败记成了驱动器的状态。修法是不要再把映射当成登录时该发生的事,而是把它当成连接序列的最后一步。
为什么映射执行得太早
登录脚本在会话开始时启动。在登录过程中连接的 VPN 客户端会把自己的时间线叠加上去:进程可能已在运行,虚拟适配器可能已存在,而到办公子网的路由可能仍然缺失。这三种状态从脚本角度看几乎一样,只有一种能用。
有些环境的应对是每次登录都重复同一条失败的命令行,结果培养出一个学会点两次驱动器的用户,以及一个从未靠自己成功过的脚本。
驱动器本身让情况更糟。映射的驱动器是会话对象,一旦 Windows 把它标记为不可用,即使隧道后来恢复正常,图标也可能长期保持损坏。这就是为什么手动重新映射有效,而脚本看起来什么也没做。会话记住的是失败,而不是背后的意图。
“已连接”状态不是路径
托盘里的 VPN 图标只报告隧道是否升起,对是否存在通往某台特定服务器的路由、DNS 是否把该名称解析成隧道地址、服务器自己的防火墙是否放行,一概不说。
这是三种独立故障,可见结果却相同;以托盘图标为准,就把它们并成一个不可靠的信号。
点名你真正需要的那台服务器的就绪检查能把它们区分开,因为它会一直失败到具体路径可用为止,而不是等到某个接口自称已连接。
以服务器为准,而不是以客户端为准
挑一台只能经隧道到达的主机,先等它通,再做任何映射。下面的片段会连接已保存的 Windows VPN 条目,轮询文件服务器,然后映射驱动器。
@echo off
set server=fileserver.corp.example
rasdial "Office VPN" /disconnect
rasdial "Office VPN"
:wait
ping -n 1 -w 1000 %server% >nul || (
timeout /t 5 /nobreak >nul
goto wait
)
net use Z: \\%server%\share /persistent:no
ping 是就绪探测,不是权限测试。如果你的网络过滤了 ICMP,就改为探测你真正在用的服务:快速检查用 net view \\%server%,或者在 PowerShell 里对 445 端口做一次短 TCP 测试。两者都以真正重要的东西为准。
给尝试次数设上限。没有天花板的等待循环会把坏掉的隧道变成永远登录不完的会话,那比缺少盘符更糟。
让它可重复执行并感知会话
在用户自己的会话里运行。以 SYSTEM 运行的任务会把驱动器放进完全不同的会话,已登录用户永远看不到结果。这样你得到的是一个报告成功的脚本,和一个没有驱动器的桌面。
映射前先检查,并且只删除过期的条目。盘符未被占用时 net use Z: /delete 会返回错误,这个错误可以安全忽略,而不是放弃脚本其余部分的理由。保留 /persistent:no,以免失败的一次尝试日后变成永久的重连尝试。
也不要把密码写进文件。rasdial 可以复用为 VPN 条目保存的凭据,共享应当以已登录用户的身份认证。如果共享确实需要不同凭据,用 cmdkey 按用户注册一次,而不是把它们嵌进放在登录共享上的批处理文件。任何能读那个共享的人都能读到密码,这就把便利变成了事故。
重跑整个脚本应当是无害的,因为那正是会发生的事。用户会重连,笔记本会唤醒,同一段代码路径会以不同的初始状态再跑一遍。
记录足够的信息,证明是哪一半迟到了
把时间戳、就绪检查结果和映射的退出码写进用户配置文件下的文件。下一次收到驱动器缺失的报告时,那份日志能回答唯一重要的问题:是隧道来晚了,还是共享拒绝了?
没有它,每次复发都要从零排查,而通常的结论是一次什么也修不好的权限变更。
从冷启动测一次,从睡眠恢复再测一次。顺序最容易出问题的是唤醒:会话比网络先恢复,脚本看到的是一台已经登录了好几个小时的机器。