2009-09-16 54 views
0

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

我已经包裹起来WNetAddConnection2,等在另一个项目一个更好的课,所以我扔的代码权利英寸

我们的Web服务是根据UltiDev卡西尼号(而不是IIS)这下运行运行系统帐户。我们每次都得到“指定设备名称无效”的错误代码。我也尝试在web.config文件中模拟其他用户,结果相同。

驱动器将映射得很好,当我从一个正常的用户帐户下的控制台程序运行我的代码。

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

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

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

链接UltiDev卡西尼号:UltiDev

SOLUTION:我设置UltiDev卡西尼服务在管理员登录,一切工作正常。 ASP .Net模拟不能按计划运行。

回答

2

如果您使用本地系统帐户,那么我认为它本质上不能访问网络[foo]。我会说模仿是你唯一可行的途径。从技术上讲,你可以减少对共享的访问控制,以便任何人都可以读取/写入共享,但这会带来比解决方案更多的问题。

+0

那么为什么web.config模拟不起作用?我在我们的日志中打印了Environment.Username,并打印了管理员,但是如果我查看UltiDev进程 - 它仍在Local System下。 UltiDev能做些奇怪的事情吗? – jonathanpeppers 2009-09-16 13:42:15

+1

本地系统帐户具有网络访问权限,但它向网络资源提供匿名凭据。 – bryanbcook 2009-09-16 13:53:25

1

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

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; 
     } 

    } 
+0

我无法断开连接并重新连接,因为它不会首先连接。 – jonathanpeppers 2009-09-16 14:12:30

0

而不是一个映射的驱动器,你可以连接使用UNC共享?

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

+0

我们与之交互的第三方进程必须使用普通驱动器号,例如f:\ – jonathanpeppers 2009-09-16 13:54:27

0

我以前实际上已经做到了这一点,但它是很久以前的 - 比如1997年和Win NT 3。51用Delphi 2

我是从内存中运行,但我认为这是这样的: 您使用赢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作为用户名和密码。

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

+0

我已经实现了WNetAddConnection2。 – jonathanpeppers 2009-09-16 14:11:36

+0

@Jonathan:你在我的文章中应用了配置注释吗?它可能不适用于以本地系统运行的服务 - 您需要设置一个具有网络访问权限和访问您正在连接的共享的适当权限的域帐户。该服务必须以该帐户运行,而不是本地系统。 – JMarsch 2009-09-16 15:45:31

0

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

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

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

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

相关问题