2009-09-16 19 views
0

Nous travaillons sur un service Web qui doit exécuter un processus tiers qui interagit avec un lecteur réseau mappé. Nous devons donc mapper ce lecteur par programme depuis le service Web.C# - Mapper un lecteur réseau à partir du service Web

Je l'ai déjà enveloppé WNetAddConnection2, etc., dans une plus belle classe pour un autre projet, donc je jeté le bon code dans.

Notre service web fonctionne UltiDev Cassini (au lieu de IIS) qui fonctionne sous la Compte système Nous obtenons le code d'erreur pour: "le nom du périphérique spécifié est invalide" à chaque fois. J'ai également essayé d'usurper l'identité d'autres utilisateurs dans le fichier web.config, avec les mêmes résultats.

Le lecteur mappera très bien lorsque j'exécuter mon code à partir d'un programme de console sous un compte utilisateur normal.

J'ai également essayé d'exécuter la commande "net use" équivalente de C# avec exactement les mêmes résultats que WNetAddConnection.

Est-ce que quelqu'un sait pourquoi un service Windows ou un utilisateur du système ne serait pas en mesure de mapper des lecteurs réseau?

Est-ce que quelqu'un sait une solution de contournement? Le simple mappage du lecteur au démarrage du système serait une solution, mais comment le système/l'utilisateur emprunté pourrait-il y accéder?

Link pour Cassini UltiDev: UltiDev

SOLUTION: je me mis à l'ouverture de session sous Administrateur et tout fonctionne le service Cassini UltiDev. L'emprunt d'identité ASP .Net ne doit pas fonctionner comme prévu.

Répondre

2

Si vous utilisez le compte Système local, je crois qu'il est intrinsèquement incapable d'accéder au réseau [foo]. Je dirais que l'usurpation d'identité est votre seul chemin viable. Techniquement, vous pouvez réduire les contrôles d'accès sur le partage au point que n'importe qui peut lire/écrire sur le partage, mais cela pose plus de problèmes que de solutions.

+0

Alors pourquoi l'usurpation d'identité web.config ne fonctionne-t-elle pas? J'ai imprimé Environment.Username dans notre journal, et il imprime l'administrateur, mais si je regarde le processus d'UltiDev - il est toujours sous le système local. UltiDev pourrait-il faire quelque chose d'étrange? – jonathanpeppers

+1

Le compte Système local dispose d'un accès réseau, mais il présente des informations d'identification anonymes aux ressources réseau. – bryanbcook

1

Nous avons eu le même problème. Le problème se produit en raison du compte sous lequel le code s'exécute. Vous pouvez contourner cela comme nous l'avons fait en utilisant la classe suivante. Vous devez mapper le lecteur dans le même code que vous utilisez pour accéder/copier des fichiers. Le motif que nous utilisons est toujours de vérifier t voir si le lecteur est connecté en premier. Si c'est le cas, nous le déconnecterons, puis le reconnecterons. sinon, nous nous connectons simplement. Cela semble éclaircir le problème que vous décrivez.

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

Je ne peux pas me déconnecter et me reconnecter car il ne se connectera pas en premier lieu. – jonathanpeppers

0

Au lieu d'un lecteur mappé, pourriez-vous vous connecter en utilisant le partage UNC?

Je continuerais d'emprunter l'identité d'un utilisateur ayant accès au partage.

+0

Notre processus tiers avec lequel nous interagissons doit fonctionner avec une lettre de lecteur simple telle que f: \ – jonathanpeppers

0

Je l'ai déjà fait, mais c'était il y a très longtemps - comme 1997, et Win NT 3.51 avec Delphi 2

Je suis en de la mémoire, mais je pense qu'il ressemble à ceci: Vous utilisez l'API Win:

WNetAddConnection2()

Infos sur l'appel: http://msdn.microsoft.com/en-us/library/aa385413(VS.85).aspx

vous pouvez obtenir la signature C# de pInvoke.net: http://www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html

note sur la configuration: Je pense que vous aurez besoin de configurer un compte de domaine pour le service, et exécutez le service avec l'identité de ce compte au lieu du système local. Je pense que vous passez null comme le nom d'utilisateur et mot de passe. Être capable d'exécuter le service lorsque le système local transmet le nom d'utilisateur et le mot de passe d'un compte de domaine - Je ne sais pas si le compte système est autorisé à accéder au réseau.

+0

J'ai déjà implémenté WNetAddConnection2. – jonathanpeppers

+0

@Jonathan: Avez-vous appliqué les notes de configuration dans mon message? Il ne fonctionnera probablement pas avec un service qui s'exécute en tant que système local - vous devrez configurer un compte de domaine qui a un accès réseau et les autorisations appropriées pour accéder au partage que vous connectez. Le service devra fonctionner comme ce compte, et non comme système local. – JMarsch

0

Le concept général à garder à l'esprit est que les «lettres de lecteurs mappés» sont un concept utilisateur et non un concept système. Ainsi, lorsque Joe se connecte à l'ordinateur Windows, les lecteurs mappés sont attachés au compte d'utilisateur Joe. Lorsqu'un service Windows est en cours d'exécution, il s'exécute généralement sous le compte d'utilisateur LOCAL_SYSTEM, ce qui signifie que LOCAL_SYSTEM ne connaît pas les lettres de lecteur mappées de Joe. Par conséquent, l'accès UNC aux partages réseau est la voie à suivre lorsque vous essayez d'accéder à une ressource distante à partir d'un service Windows. Notez que vous pouvez exécuter le service Windows dans le contexte du compte d'utilisateur 'Joe', ou créer un compte AD factice appelé quelque chose comme 'MyServiceAccount' et donner à ce compte des droits sur l'UNC, ou utiliser Impersonation et avoir le Le service Windows se connecte au poste de travail local à l'aide de la fonction NetLogon() avec un handle d'emprunt d'identité, puis accède à l'UNC à partir de là.

Il existe de nombreuses façons de le faire, mais tous les comptes utilisateur sont associés aux lecteurs mappés et à l'accès UNC.

Bonne chance, espérons que cette information aide!