【问题标题】:C# - Map Network drive from Web ServiceC# - 从 Web 服务映射网络驱动器
【发布时间】:2010-11-28 19:27:12
【问题描述】:

我们正在开发一项 Web 服务,该服务必须运行与映射的网络驱动器交互的第 3 方进程。所以我们必须通过网络服务以编程方式映射这个驱动器。

我已经为另一个项目将 WNetAddConnection2 等封装在一个更好的类中,所以我把代码直接扔进去了。

我们的 Web 服务在 UltiDev Cassini(而不是 IIS)下运行,它在 System 帐户下运行。我们每次都得到错误代码:“指定的设备名称无效”。我还尝试在 web.config 文件中模拟其他用户,结果相同。

当我在普通用户帐户下从控制台程序运行我的代码时,驱动器将正常映射。

我还尝试从 C# 运行等效的“net use”命令,结果与 WNetAddConnection 完全相同。

有谁知道为什么 Windows 服务或系统用户无法映射网络驱动器?

有人知道解决方法吗?简单地在系统启动时映射驱动器将是一个解决方案,但系统/模拟用户如何访问它?

UltiDev Cassini 的链接:UltiDev

解决方案:我将 UltiDev Cassini 服务设置为在管理员下登录,一切正常。 ASP .Net 模拟不得按计划工作。

【问题讨论】:

    标签: c# .net windows-services shared-directory mapped-drive


    【解决方案1】:

    LOCAL_SYSTEM 帐户显示匿名credentials on the network。您可以使用 UNC 网络共享来访问此信息,前提是匿名(每个人)都可以访问该共享。

    您也可以install Cassini as a windows service,您可以将其配置为在不同的用户下运行。

    【讨论】:

      【解决方案2】:

      如果您使用的是本地系统帐户,那么我相信它天生就无法访问网络 [foo]。我会说模仿是你唯一可行的途径。从技术上讲,您可以将共享的访问控制减少到任何人都可以读取/写入共享的程度,但这带来的问题多于解决方案。

      【讨论】:

      • 那么为什么 web.config 模拟不起作用?我在我们的日志中打印了 Environment.Username,它打印了管理员,但是如果我查看 UltiDev 进程,它仍然在本地系统下。 UltiDev 会不会做一些奇怪的事情?
      • 本地系统帐户确实具有网络访问权限,但它向网络资源提供匿名凭据。
      【解决方案3】:

      我们遇到了同样的问题。问题的发生是因为代码运行的帐户。您可以通过使用以下类来解决这个问题。您必须在用于访问/复制文件的相同代码中映射驱动器。我们使用的模式是始终检查驱动器是否首先连接。如果是这样,我们断开它,然后重新连接它。如果没有,我们只是连接它。这似乎解决了您所描述的问题。

      public static class NetworkDrives
          {
              public static bool  MapDrive(string DriveLetter, string Path, string Username, string Password)
              {
      
                  bool ReturnValue = false;
      
                  if(System.IO.Directory.Exists(DriveLetter + ":\\"))
                  {
                      DisconnectDrive(DriveLetter);
                  }
                  System.Diagnostics.Process p = new System.Diagnostics.Process();
                  p.StartInfo.UseShellExecute = false;
                  p.StartInfo.CreateNoWindow = true;
                  p.StartInfo.RedirectStandardError = true;
                  p.StartInfo.RedirectStandardOutput = true;
      
                  p.StartInfo.FileName = "net.exe";
                  p.StartInfo.Arguments = " use " + DriveLetter + ": " + '"' + Path + '"' + " " + Password + " /user:" + Username;
                  p.Start();
                  p.WaitForExit();
      
                  string ErrorMessage = p.StandardError.ReadToEnd();
                  string OuputMessage = p.StandardOutput.ReadToEnd();
                  if (ErrorMessage.Length > 0)
                  {
                      throw new Exception("Error:" + ErrorMessage);
                  }
                  else
                  {
                      ReturnValue = true;
                  }
                  return ReturnValue;
              }
              public static bool DisconnectDrive(string DriveLetter)
              {
                  bool ReturnValue = false;
                  System.Diagnostics.Process p = new System.Diagnostics.Process();
                  p.StartInfo.UseShellExecute = false;
                  p.StartInfo.CreateNoWindow = true;
                  p.StartInfo.RedirectStandardError = true;
                  p.StartInfo.RedirectStandardOutput = true;
      
                  p.StartInfo.FileName = "net.exe";
                  p.StartInfo.Arguments = " use " + DriveLetter + ": /DELETE";
                  p.Start();
                  p.WaitForExit();
      
                  string ErrorMessage = p.StandardError.ReadToEnd();
                  string OuputMessage = p.StandardOutput.ReadToEnd();
                  if (ErrorMessage.Length > 0)
                  {
                      throw new Exception("Error:" + ErrorMessage);
                  }
                  else
                  {
                      ReturnValue = true;
                  }
                  return ReturnValue;
              }
      
          }
      

      【讨论】:

      • 我无法断开连接并重新连接,因为它一开始就无法连接。
      【解决方案4】:

      您可以使用 UNC 共享连接而不是映射驱动器吗?

      我仍然会冒充有权访问共享的用户。

      【讨论】:

      • 我们与之交互的第 3 方进程必须使用普通驱动器号,例如 f:\
      【解决方案5】:

      实际上我以前也这样做过,但那是很久以前的事了——比如 1997 年,Win NT 3.51 和 Delphi 2

      我从内存中运行,但我认为它是这样的: 您使用 Win API:

      WNetAddConnection2()

      通话信息:http://msdn.microsoft.com/en-us/library/aa385413(VS.85).aspx

      您可以从 pInvoke.net 获取 c# 签名:http://www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html

      配置注意事项: 我认为您需要为该服务设置一个域帐户,并使用该帐户而不是本地系统的身份运行该服务。我认为您将 null 作为用户名和密码传递。

      可能能够在本地系统传递域帐户的用户名和密码时运行该服务——我不知道系统帐户是否允许任何网络访问。

      【讨论】:

      • @Jonathan:你在我的帖子中应用了配置说明吗?它可能不适用于作为本地系统运行的服务——您需要设置一个具有网络访问权限和适当权限的域帐户才能访问您正在连接的共享。该服务必须作为该帐户运行,而不是作为本地系统。
      【解决方案6】:

      要记住的一般概念是“映射驱动器号”是用户概念,而不是系统概念。因此,当 Joe 登录到 Windows 计算机时,映射的驱动器将附加到 Joe 用户帐户。当 Windows 服务运行时,它通常在 LOCAL_SYSTEM“用户帐户”下运行,这意味着 LOCAL_SYSTEM 不知道 Joe 的映射驱动器号。

      因此,当尝试从 Windows 服务中访问任何远程资源时,UNC 访问网络共享是一种方法。请注意,您可以在“Joe”用户帐户的上下文中运行 Windows 服务,或者您可以创建一个名为“MyServiceAccount”的虚拟 AD 帐户并将该帐户权限授予 UNC,或者您可以使用 Impersonation 并拥有Windows 服务使用带有模拟句柄的 NetLogon() 函数登录到本地工作站,然后从那里访问 UNC。

      有很多方法可以做到这一点,但归根结底都是用户帐户与映射驱动器和 UNC 访问相关联。

      祝你好运,希望这些信息对你有帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-19
        • 2010-09-16
        • 1970-01-01
        相关资源
        最近更新 更多