为了将程序安装到 Windows 10 中的映射网络驱动器里

映射网络驱动器就是将网络上的共享文件夹添加到系统中作为一个(网络)磁盘分区的操作。如果网络好,比如局域网,正常情况下应该可以像访问本地硬盘分区一样方便快捷。但是到 Windows 10,特别是 1803 版本之后,就出现了各种坑。网络上有很多相关的求助信息。

映射驱动器还是挺常用的一个功能的,并不局限于企业用户。个人也可以将网络上提供的免费存储空间,比如 DriveHQ 的免费 WebDAV 驱动器,映射为本地磁盘分区。而且,就算不用 Samba(可运行在 Windows 或者 Linux 上),而是使用 XAMPP 也是很容易就可以在 Windows 电脑上搭建个简易的 WebDAV 服务器来用的。

普通的映射驱动器用来存取文件是没啥问题的。这里要说的是运行存储在映射驱动器上的可执行文件,比如软件安装包,甚至直接将某些软件安装到映射驱动器上,在不同的电脑上映射到同一个驱动器来运行,等等。

问题描述

具体的情况就是,按照微软只是库中的方法挂载的网络驱动器,我们没法从中运行程序(例如应用程序的安装文件),也没法将一些特殊的程序安装到网络驱动器中。甚至在安装的时候选择自定义程序安装路径的时候并不能在列表中看到映射的网络驱动器。这是因为登录 Windows 的用户跟运行程序的用户在 Windows 10 中使用了不同的运行权限。普通用户挂载的网络驱动器对管理员不可见,即使这个普通用户本身也属于管理员用户组;该用户以管理员身份挂载的网络驱动器可以用于运行/安装程序,但是又对该用户的普通身份——登录到桌面来使用电脑的那个身份——不可见。这样当然可以提高安全性,可是却没有给用户绕开这种设定的设置。对于这种问题,微软支持网站有较为详细的解释,但是目前还并没有完美的解决方案。这种问题并不完全同于在 Windows 10 1809 中出现的映射网络驱动器的问题

明明看到挂载了网络驱动器,可是运行程序就会有错误提示。错误信息如,

Windows cannot access
\\192.168.122.1\Common\InstallFiles\Setup.exe

You do not have permissions to access \\192.168.122.1\Common\InstallFiles\Setup.exe. Contact your network administrator to request access.

对于这样的矛盾问题,一般直觉想到的解决方法就是,我就以普通身份和管理员身份各挂载一次网络映射驱动器吧。按理说是这样,可是现实很骨干,会遇到诸如「句柄无效」或者「另一个程序正在访问该位置,暂时无法访问」这样的错误。

网上流传的解决方法

这样的问题让很多人头大。如果是公司用户,有域控制器,使用 GPO 组策略管理器来配置,那就不存在障碍。这种情况下,系统需要连接到一个 Windows Active Directory 才会有这样的管理单元。或者说,得使用服务器版本的 Windows 才能见到这些工具 (Group Policy Preference)(参考这里)。但是普通用户就没招了。微软似乎无意于解决这样的问题。所以网上流传的解决方法也是满天飞。我都挨个儿试了试。

下面的配置可以一项一项地顺次执行,直到测试发现客户机中可以运行挂载的网络映射驱动器中的程序为止。因为我做了这么多尝试,并不是顺序的,有些配置修改后就没有再还原回去,所以我也不确定是这些配置综合作用的结果还是其中某一项或者两项配置的效果。但是又懒得再去试一边了。

可能方法 1 (修改 Linux 主机上运行的 Samba 服务配置)

这个是针对 Linux 主机上运行的 Windows 10 客户机来配置的。其中的可执行权限可以作为参考。参考了 wiki.samba.orgstackexchange 1 以及 stackexchange 2。修改 Linux 主机中的 Samba 配置文件,在通用配置的基础上,为需要在客户机中运行可执行文件的共享增加下面的配置,

[global]
workgroup = WORKGROUP
dns proxy = No
security = user
server string = Samba Server %v
min protocol = SMB2
ntlm auth = yes
[kvm_share]
comment = Samba Shared Directory for Win10 in KVM
path = /path/to/kvm_share
valid users = SambaUserA
force user = NormalLinuxUser
guest ok = No
read only = No
writable = Yes
browsable = Yes
create mask = 0700
directory mask = 0700
force create mode = 0700
force directory mode = 0700
acl allow execute always = Yes

其中 NormalLinuxUser 替换成 Linux 中具有相应权限的用户,比如使用这个 Windows 虚拟机的那个用户。一般不会是 root,因为我们并不希望虚拟机中的系统能够修改 Linux 普通用户都不能修改的文件。Linux 在进行 Samba 共享的时候,系统里的权限是比 Samba 中配置的权限优先级高的,所以即使给了 0700,如果那个 NormalLinuxUser 实际上权限是 0644,那么实际共享出去的权限就是 0600。像上面的 [kvm_share] 的共享声明还可以添加多个,下面的配置参数差不多,改改共享名 kvm_share 和路径 path 就可以了。

前面那个 valid users 后面的 SambaUserA 是控制在 Windows 中远程访问这个 Samba 共享的时候使用的用户名,下面还需要给这个 Samba 用户设置相应的密码来控制访问,

# smbpasswd -a SambaUserA
# smbpasswd -e SambaUserA

需要注意就是,这个 SambaUserA 必须首先是 Linux 主机中的用户。所以为了省事当然也可以直接用前面那个 NormalLinuxUser

当然,在 Samba 共享中一般不建议使用 force user 这样的设定,因为有安全隐患。但是这里是共享给自己使用,如果仅仅有这一个用户,那么就不存在安全问题。

可能方法 2 (修改 Windows 10 客户机注册表以启用EnableLinkedConnections

需要首先说明的是,这个方法实际上是在 Windows 10 之前的解决办法。到了 Win 10,微软官方已经不推荐使用这个方法了。但是没有说明原因。

在注册表中创建 enableLinkedConnections修改(也可能是虚拟机中运行的)Windows 10 系统的注册表。方法是,

  • 打开运行(Win+R)窗口,输入 regedit(也可以直接在开始菜单中输入 regedit 就会看到自动搜索过滤出来的运行注册表编辑器那条结果);
  • 在注册表的左侧栏依次展开,HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System 下面,创建一个新的 DWORD 条目,名称为 EnableLinkedConnections,值为 1。(参考 spiceworks

注:至少在 Windows 10 企业版 LTSC 1809 (17763.1790)中,该设置可以让管理员用户贡献映射驱动器,即在直接 net use 之后在管理员权限打开的命令提示符下也能看到挂载的网络驱动器。但是似乎会导致运行安装在网络驱动器中的程序时响应异常缓慢。

可能方法 3 (修改 Windows 10 中的组策略)

这个似乎只能用在 Windows 10 专业版/旗舰版/企业版 等版本中。

修改虚拟机中 Windows 系统的组策略。方法是,

  • 打开运行(Win+R)窗口,输入 gpedit.msc(也可以直接在开始菜单中输入 group policy(或者中文应该输入「组策略」 就会看到自动搜索过滤出来的 edit group policy 或者「本地组策略管理器」那条结果);
  • 在组策略编辑器中依次展开左侧边栏中的「计算机配置」=》「管理模板」=》「系统」=》「网络登录」,修改「设置 SYSVOL 共享兼容性」为启用。

参考了 spicework 社区讨论

可能方法 4 (修改注册表 LocalAccountTokenFilterPolicy)

还是修改注册表。改变系统对本地帐户的令牌的过滤策略。参考自 spicework 社区讨论。将 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system 下的 LocalAccountTokenFilterPolicy 的值改为 1

可能方法 5 (将 UAC 调至最低)(update: 事实证明这个可能并没有影响

参考微软官方的说明。将用户帐户控制(UAC)的安全级别调到最低。

可能方法 6(修改注册表 autodisconnect)

这个应该是用来解决那个映射的网络驱动器可能会断开,盘符上出现红色的叉叉的问题的,微软社区有说明。默认情况下,Windows 会在 15 分钟后关闭不活动的连接。这个同样需要修改注册表。将 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters下面的 autodisconnect,双击并修改其值为 ffffffff(8个 f)。如果没有这个条目,可以自己新建一个 DWORD 类型的条目。

经过水景一页的观察,不建议这样修改。因为如果不出什么状况的话,映射的网络驱动器是不会消失的,随时都可以访问到,所以不需要修改这个。而如果出状况了,则需要查错或是重新映射。这个时候这种类似于永不过期的设置反而是个妨碍,因为此时我们希望它赶紧失效然后我们好做新的设定。水景一页自己甚至将该值改成了 15。也就是将默认值调整为 15s(应该是吧,不确定单位是不是秒,因为我忘记修改成 8 个 f 之前的数值了)。但是如果不是要同时在管理员身份下也映射一遍的话,这个设置并不会影响映射驱动器的存取。

可能方法 7 (使用 Launchapp.wsf)

嗯,忘记是参考自哪里了。但是我看到那个推荐的 Launchapp.wsf 居然是 2012 年的,我就不想尝试了。

结果

总之,经过不断地失败和尝试,现在终于可以在虚拟机里的 Windows 上将一些软件安装到从主机里使用 Samba 共享给虚拟机的网络映射驱动器了。安装的时候更改安装位置,在弹出的对话框中展开「电脑」,就能看到列在它下面的网络驱动器了。运行软件更是没有问题。但是探索的过程真的很难。而且目前也只是采用了临时的方法,并不是一劳永逸的解决方案。

在 Windows 中映射网络驱动器有好几个途径,

  • 像微软官方文档说的那样通过文件管理器菜单添加。这种添加方式,如果勾选了「下次自动重新连接」的话,登录凭据会保存在「凭据管理器」中。当然有需要的话也可以打开 Credential Manager 来删除系统记录的凭据。
  • 在 Windows 自带的命令行终端工具里使用 net use 命令添加。
      • 打开命令行工具,开始 =》所有程序 =》Windows 系统 =》命令行工具。
      • 指令格式,
        C:\Windows\system32> net use Z: \\ostp\kvm_share * /user:SambaUserA /persistent:yes

        其中,Z: 是我们要挂载到的驱动器空闲盘符;\\ostp\kvm_share 是共享文件夹的网络路径,其中 ostp 也可以是域名或者 IP 地址;* 是告诉他询问密码;/user:SambaUserA 是告诉他网络共享文件夹的登录用户名为 SambaUserA/persistent:yes 是让他记住密码,然后下次登录系统的时候自动挂载这个映射驱动器。
        其实也可以简化成,

        C:\Windows\system32> net use Z: \\ostp\kvm_share /user:SambaUserA mypassword /persistent:yes

        其中 mypassword 就是 SambaUserA 的明文密码。
        要删除一个映射驱动器,可以这样,

        C:\Windows\system32> net use Z: /delete

        删除后也会同时清除 /persistent:yes 标记。也就是下次就不会自动映射了。

  • 将上面的指令写成批处理文件,然后通过,
      • 任务计划程序(开始=》所有程序 =》Windows 管理工具 =》任务计划程序)来添加计划任务以运行;
      • 创建启动项来自动运行(要打开启动文件夹,可以 Win+R 然后输入 shell:Startup并回车来打开当前用户的启动菜单文件夹,也可以输入 shell:common startup来打开该电脑公共的的启动文件夹);
      • 组策略=》用户配置=》Windows 设置=》脚本(登录/注销)=》登录=》添加脚本到该任务中即可在用户登录系统后自动运行。

    其中前面两种方法在微软的这篇说明文档中有详细介绍。后面的组策略对普通的家庭版 Windows 无效。

其实上面介绍的任意一个方法都是可行的。但是批处理文件的话似乎不如微软介绍的这个脚本好,因为微软提供的这个脚本还可以保证「在标准用户安全性上下文中执行所有解决方法」。也就是说,只要注意不要同时用几个帐户挂载,甚至不能用一个属于管理员的用户同时用普通身份和管理员身份做映射,那就不会有问题。否则两边都挂载的话会导致使用文件管理器访问的时候出现「有程序正在使用」或者「句柄错误」这样的错误提示。

目前水景一页采用的是登录后手动执行映射驱动器的批处理文件一次。并且批处理中的 net use 指令最后使用了 /persistent:no 选项。当然正在考虑改用微软介绍的那个脚本放到计划任务里自动执行。只是有点疲惫了,暂时不想去碰这个好不容易可以正常使用的东西。

经过上面的折腾,水景一页将前面列出的网上流传的解决方法中的前 5 个修改都保留了。也不想再去测试它们了。现在至少可以运行映射驱动器上的可执行程序,比如安装包,甚至也可以运行已经安装到网络文件夹中的应用程序,包括微信电脑版之类的都没有问题。

那么如何解决安装程序到映射驱动器中的问题呢?安装程序肯定需要管理员权限。这个时候,就在打开命令行工具的时候(见上面的「在 Windows 自带的命令行终端工具里使用 net use 命令」),不直接左键点击打开,而是右键单击后选择「更多=》以管理员身份运行」,然后直接使用 net use 指令挂载需要的那个驱动器。安装完成后就直接再使用 /delete 选项将这个映射删除。以管理员身份删除并不会删除普通身份挂载那个。这是因为 Windows 中,即使使用管理用户登录,其通常的桌面环境也是用过滤了的权限来执行的,包括文件管理器 File Explorer。使用 File Explorer 添加的映射网络驱动器是没有跟管理员共享的,所以管理员不知道(看不见),那么安装程序肯定需要管理员来执行,他就无法安装到映射的网络驱动器中。相反也是类似的道理。参考 123

最后补充一点。为了不让系统总是在打开文件或者运行程序的时候提示说该文件来自网络或共享位置,有风险,还需要修改组策略, User Configuration > Administrative Templates > Windows Components > Attachment Manager,将其中的「Do not preserve zone information in file attachments」 改为「启用」状态。该设置即时生效。参见 minitool 上的文章。(也许这样也没法去掉这个警告。)

还需要补充一点。有时候我们会发现,即使按照上面的配置折腾一圈了,也保证了只是用当前的桌面用户挂载了网络驱动器,还是可能会在访问该驱动器的时候遭遇前面提到的错误。这多半是因为 Windows 的索引功能(用于建立桌面搜索使用的数据库)在后台访问这些驱动器导致的。可以在「索引选项 Indexing Options」(位于「控制面板 Control Panel」中) 里面将映射的驱动器排除。我是通过「组策略」(计算机配置 > 管理模板 > Windows 组件 > 搜索)将该功能禁用了。当然组策略里面也有排除一些索引路径的配置可以利用。我只是想彻底一点,并且搜索功能对我来说是可有可无的。

再补充一点。Windows Defender 自带的病毒实时防护(Real time protection)如果开启的话,运行网络映射驱动器上的程序会特别慢,甚至无法运行。可是微软不知道怎么突然不想让大家可以永久关闭这个实时防护了,甚至修改了组策略这个实时防护还是会在系统重启之后自己跑回来。还好已经有人找到了彻底关闭它的方法。参考这里:先在「设置」里手动关闭实时防护,然后下载并以管理员身份运行来自微软的小工具 Autoruns for Windows,切换到「Services」 标签页,从工具栏的「查看」里面取消勾选「隐藏 Windows 条目」,然后往下翻找到「WinDenfend」条目并取消勾选该条目。©

本文发表于水景一页。永久链接:<http://cnzhx.net/blog/install-app-into-mapped-network-drive-in-windows-10/>。转载请保留此信息及相应链接。

1 条关于 “为了将程序安装到 Windows 10 中的映射网络驱动器里” 的评论

  1. 引用通告: 上手 Linux 原生的虚拟机工具 QEMU/KVM | 水景一页

时间过去太久,评论已关闭。
如果您有话要说,请到讨论区留言并给出此文章链接。
谢谢您的理解 :-)