映射要由服务使用的网络驱动器
Posted
技术标签:
【中文标题】映射要由服务使用的网络驱动器【英文标题】:Map a network drive to be used by a service 【发布时间】:2010-09-16 00:20:33 【问题描述】:假设某些 Windows 服务使用需要映射网络驱动器且没有 UNC 路径的代码。启动服务时,如何使驱动器映射可用于服务会话?以服务用户身份登录并创建持久映射不会在实际服务的上下文中建立映射。
【问题讨论】:
查看 ForcePush 的回答,他的解决方法有效。 【参考方案1】:使用此功能需您自担风险。 (我已经在 XP 和 Server 2008 x64 R2 上测试过)
对于这个 hack,你需要SysinternalsSuite by Mark Russinovich:
第一步: 打开提升的 cmd.exe 提示符(以管理员身份运行)
第二步:
使用 PSExec.exe 再次提升为 root:
导航到包含 SysinternalsSuite 的文件夹并执行以下命令
psexec -i -s cmd.exe
您现在处于nt authority\system
的提示符内,您可以通过键入whoami
来证明这一点。需要-i
,因为驱动器映射需要与用户交互
第三步:
使用以下命令将持久映射驱动器创建为 SYSTEM 帐户
net use z: \\servername\sharedfolder /persistent:yes
就这么简单!
警告:您只能从 SYSTEM 帐户中以与创建它相同的方式删除此映射。如果您需要删除它,请按照步骤 1 和 2,但将步骤 3 中的命令更改为 net use z: /delete
。
注意:新创建的映射驱动器现在将显示给该系统的所有用户,但他们会看到它显示为“断开连接的网络驱动器 (Z:)”。不要让这个名字欺骗你。它可能声称已断开连接,但它适用于所有人。这就是您可以判断 M$ 不支持此 hack 的方式。
【讨论】:
我试图使用这个解决方案并遇到了这个问题:映射的驱动器对用户(甚至管理员)显示为断开连接。有什么建议吗? 重启后映射的驱动器消失了。有什么想法吗?映射是持久的,但状态是“不可用”,所以它没有显示 我还看到重新启动后映射不可用。 要在重新启动后使其正常工作,请创建一个仅包含net use z: \\servername\sharedfolder
的脚本并将其设置为在计算机启动时运行,每 technet.microsoft.com/en-us/library/cc770556.aspx 这将作为 SYSTEM 帐户运行,因此不需要 psexec .
我想补充一点,重要的是每个人都使用子句/USER:[remotecomp]\[remoteusername] [password]
(当远程用户名前面没有远程计算机名和反斜杠时,命令有时无法正常工作。另外,如果共享受密码保护,对其他人显示为断开连接的驱动器,每个人不可以访问。该系统上的任何用户(SYSTEM 安装共享)都必须知道该共享的密码。(在 XPx64 上测试)【参考方案2】:
我找到了一个类似于使用 psexec 的解决方案,但无需其他工具并且可以在重新启动后继续运行。
只需添加一个已调度的任务,在“运行方式”字段中插入“系统”,然后使用简单的命令将任务指向一个批处理文件
net use z: \servername\sharedfolder /persistent:yes
然后选择“在系统启动时运行”(或者类似的,我没有英文版)就完成了。
【讨论】:
先从什么开始? Windows 服务或此计划任务?如果路径不可用,我们的服务会在启动时终止。如果服务最后启动,我们必须重建它。 我在 2008 R2 上试过这个,它创建了一个断开连接的映射驱动器,当我尝试打开它时,它显示“z:\ 不可访问。登录失败:未知用户名或密码错误。”但是我能够通过手动运行相同的 bat 文件成功创建映射驱动器。有什么见解吗? @Thomas 由于/persistent:yes
,只要任务至少运行一次,首先开始并不重要
为什么一定要定时任务?它是 /persistent:是的,这还不够吗?
@ScottStafford 否 /persistent:yes 在 Win7 及更高版本上是不够的。无论该开关如何,映射都会在重新启动后被删除。【参考方案3】:
您要么需要修改服务,要么将其封装在辅助进程中:除了会话/驱动器访问问题之外,持久驱动器映射仅在交互式登录时恢复,而这些服务通常不会执行。
辅助进程方法非常简单:只需创建一个映射驱动器并启动“真正”服务的新服务。唯一并非完全无关紧要的是:
帮助服务需要将所有适当的 SCM 命令(启动/停止等)传递给实际服务。如果实际服务接受自定义 SCM 命令,请记住也传递这些命令(不过,我不希望认为 UNC 路径具有异国情调的服务使用此类命令...)
在凭证方面可能会有些棘手。如果真实服务运行在普通用户帐户下,您也可以在该帐户下运行助手服务,只要该帐户对网络共享具有适当的访问权限,一切都应该没问题。如果真正的服务只有在以 LOCALSYSTEM 或类似的方式运行时才能工作,事情会变得更有趣,因为它要么根本无法“看到”网络驱动器,要么需要一些凭证才能让事情正常工作。
【讨论】:
信息量很大...我是否正确假设登录脚本也仅针对交互式登录会话而不是服务会话运行?【参考方案4】:更好的方法是通过 mklink.exe 使用符号链接。您可以在文件系统中创建任何应用程序都可以使用的链接。见http://en.wikipedia.org/wiki/NTFS_symbolic_link。
【讨论】:
如此简单,效果很好。由于它是文件系统的一部分,因此该链接可供所有帐户使用。只需确保服务作为有权访问网络资源的帐户运行(系统等可能不是这种情况)。 这绝对是问题的更好答案,非常感谢! 不幸的是,如果符号链接访问网络共享,那么你又回到了原点 这是我选择的解决方案,符号链接是网络共享。我必须注意服务开始使用允许遵循符号链接的(网络)用户。一旦涵盖了这一点,这是一个理想的解决方案。 你们能更详细地描述一下你们到底做了什么吗?【参考方案5】:这里有一个很好的答案: https://superuser.com/a/651015/299678
即您可以使用符号链接,例如
mklink /D C:\myLink \\127.0.0.1\c$
【讨论】:
如果您尝试从服务内创建目录后出现权限错误怎么办? 您应该将此离线带到聊天室,然后提供错误消息的详细信息。您可能需要以提升的权限运行命令。 @tyoc213 你得到答案了吗?【参考方案6】:您可以使用“网络使用”命令:
var p = System.Diagnostics.Process.Start("net.exe", "use K: \\\\Server\\path");
var isCompleted = p.WaitForExit(5000);
如果这在服务中不起作用,请尝试 Winapi 和 PInvoke WNetAddConnection2
编辑:显然我误解了你——你不能改变服务的源代码,对吧?在这种情况下,我会遵循mdb 的建议,但稍作改动:创建您自己的服务(我们称之为映射服务)来映射驱动器并将此映射服务添加到第一个依赖项(实际工作)服务。这样,在映射服务启动(并映射驱动器)之前,工作服务将不会启动。
【讨论】:
有了这个映射服务设置,我认为映射服务建立的驱动器映射不会在原始服务的上下文中可用,是吗? 我认为强制推送,
注意:新创建的映射驱动器现在将显示给该系统的所有用户,但他们会看到它显示为“断开连接的网络驱动器 (Z:)”。不要让这个名字欺骗你。它可能声称已断开连接,但它适用于所有人。这就是您如何判断 M$ 不支持此 hack...
这完全取决于共享权限。如果您在共享权限中拥有所有人,则其他用户将可以访问此映射驱动器。但是,如果您只有某个特定用户的凭据在您的批处理脚本中使用,并且此批处理脚本已添加到启动脚本中,则只有系统帐户才能访问该共享,甚至管理员也不能。 因此,例如,如果您使用计划的 ntbackuo 作业,则必须在“运行身份”中使用系统帐户。 如果您的服务的“登录为:本地系统帐户”,它应该可以工作。
我做了什么,我没有在我的启动脚本中映射任何驱动器号,只是在我的计划作业中使用了net use \\\server\share ...
并使用了 UNC 路径。添加了一个登录脚本(或只是将一个批处理文件添加到启动文件夹),其映射到具有某些驱动器号的同一共享:net use Z: \\\...
具有相同的凭据。现在登录的用户可以查看和访问该映射驱动器。同一个共享有 2 个连接。在这种情况下,用户不会看到烦人的“断开的网络驱动器......”。但是,如果您真的需要通过驱动器号访问该共享,而不仅仅是 UNC,请使用不同的驱动器号映射该共享,例如Y 代表系统,Z 代表用户。
【讨论】:
【参考方案8】:找到了一种授予 Windows 服务访问网络驱动器的方法。
以带有 NFS Disk 的 Windows Server 2012 为例:
第 1 步:编写要挂载的批处理文件。
编写一个批处理文件,例如:C:\mount_nfs.bat
echo %time% >> c:\mount_nfs_log.txt
net use Z: \\your ip\netdisk folder\ >> C:\mount_nfs_log.txt 2>&1
第 2 步:将磁盘挂载为 NT AUTHORITY/SYSTEM。
打开“任务计划”,新建一个任务:
-
在“系统启动”中以“SYSTEM”身份运行。
创建操作:运行“C:\mount_nfs.bat”。
经过这两个简单的步骤,我的 Windows ActiveMQ 服务在“本地系统”权限下运行,无需登录即可完美运行。
【讨论】:
【参考方案9】:当您通常从命令提示符运行可执行文件时能够访问驱动器的原因是,当您将其作为普通 exe 执行时,您是在您登录的用户帐户中运行该应用程序。该用户有权访问网络。但是,当您将可执行文件安装为服务时,默认情况下,如果您在任务管理中看到它在“系统”帐户下运行。而且您可能知道“系统”无权访问网络资源。
这个问题可以有两种解决方案。
将驱动器映射为如上所述的持久性。
还有另一种方法可以遵循。如果您通过键入“services.msc”打开服务管理器,您可以转到您的服务,在您的服务属性中有一个登录选项卡,您可以在其中将帐户指定为“系统”以外的任何其他帐户,您可以从您自己登录的用户帐户或通过“网络服务”启动服务。当你这样做时..服务可以访问任何网络组件和驱动器,即使它们也不是持久的。 要以编程方式实现这一点,您可以查看“CreateService”函数 http://msdn.microsoft.com/en-us/library/ms682450(v=vs.85).aspx 并且可以将参数“lpServiceStartName”设置为“NT AUTHORITY\NetworkService”。这将在“网络服务”帐户下启动您的服务,然后您就完成了。
您也可以尝试通过在 CreateService() 函数的 servicetype 参数标志中指定 SERVICE_INTERACTIVE_PROCESS 来使服务具有交互性,但这仅限于 XP as Vista 和 7 不支持此功能。
希望解决方案对您有所帮助。如果这对您有用,请告诉我。
【讨论】:
【参考方案10】:您可以将脚本设置为每次使用驱动器时映射/取消映射驱动器,而不是依赖永久驱动器:
net use Q: \\share.domain.com\share
forfiles /p Q:\myfolder /s /m *.txt /d -0 /c "cmd /c del @path"
net use Q: /delete
这对我有用。
【讨论】:
【参考方案11】:您既不想从“系统”更改运行服务的用户,也不想偷偷摸摸地以系统的身份运行映射。
有趣的是,这可以通过使用"at" 命令来实现,只需将您的驱动器映射安排在未来一分钟,它将在系统帐户下运行,使驱动器对您的服务可见。
【讨论】:
服务不作为“系统”运行。它设置为在特定的本地帐户下运行。即使我使用该帐户登录,创建持久网络映射,注销并重新启动服务,该映射也将无法用于该服务。【参考方案12】:我还不能发表评论(致力于声誉),但创建了一个帐户只是为了回答@Tech Jerk @spankmaster79(好名字哈哈)和@NMC 他们报告的问题,以回复“我找到了一个类似于具有 psexec 但无需其他工具即可工作并且在重新启动后仍然存在的那个。” @Larry 发布的帖子。
解决方案是从登录帐户中浏览到该文件夹,即:
\\servername\share
并让它提示登录,然后在 psexec 中输入您用于 UNC 的相同凭据。之后它开始工作。就我而言,我认为这是因为具有该服务的服务器与我要映射到的服务器不是同一域的成员。我在想 UNC 和计划任务是否都引用 IP 而不是主机名
\\123.456.789.012\share
它可以完全避免这个问题。
如果我在这里获得足够的代表点数,我会将其添加为回复。
【讨论】:
【参考方案13】:我找到了一个很简单的方法:使用powershell的“New-SmbGlobalMapping”命令,全局挂载驱动:
$User = "usernmae"
$PWord = ConvertTo-SecureString -String "password" -AsPlainText -Force
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
New-SmbGlobalMapping -RemotePath \\192.168.88.11\shares -Credential $creds -LocalPath S:
【讨论】:
以上是关于映射要由服务使用的网络驱动器的主要内容,如果未能解决你的问题,请参考以下文章