2010-03-09 5 views
10

J'ai un C# exe qui doit être exécuté à l'aide de WMI et accéder à un partage réseau. Cependant, lorsque j'accède au partage, j'obtiens une exception UnauthorizedAccessException. Si je cours directement l'exe, le partage est accessible. J'utilise le même compte d'utilisateur dans les deux cas.Authentification réseau lors de l'exécution d'exe à partir de WMI

Il y a deux parties dans mon application, un client GUI qui s'exécute sur un PC local et un processus dorsal qui s'exécute sur un PC distant. Lorsque le client a besoin de se connecter au backend, il lance d'abord le processus distant en utilisant WMI (code reproduit ci-dessous). Le processus distant effectue un certain nombre de choses, y compris l'accès à un partage réseau à l'aide de Directory.GetDirectories() et rend compte au client.

Lorsque le processus distant est lancé automatiquement par le client à l'aide de WMI, il ne peut pas accéder au partage réseau. Toutefois, si je me connecte à la machine distante à l'aide du Bureau à distance et lance manuellement le processus backend, l'accès au partage réseau réussit.

L'utilisateur spécifié dans l'appel WMI et l'utilisateur connecté pour la session Bureau à distance sont identiques, les autorisations doivent donc être les mêmes, n'est-ce pas?

Je vois dans l'entrée MSDN pour Directory.Exists() que "La méthode Exists n'effectue pas d'authentification réseau Si vous interrogez un partage réseau existant sans être pré-authentifié, la méthode Exists retournera false." Je suppose que c'est lié? Comment puis-je m'assurer que l'utilisateur est correctement authentifié dans une session WMI?

ConnectionOptions opts = new ConnectionOptions(); 

opts.Username = username; 
opts.Password = password; 

ManagementPath path = new ManagementPath(string.Format("\\\\{0}\\root\\cimv2:Win32_Process", remoteHost)); 

ManagementScope scope = new ManagementScope(path, opts); 

scope.Connect(); 

ObjectGetOptions getOpts = new ObjectGetOptions(); 
using (ManagementClass mngClass = new ManagementClass(scope, path, getOpts)) 
{ 
    ManagementBaseObject inParams = mngClass.GetMethodParameters("Create"); 
    inParams["CommandLine"] = commandLine; 
    ManagementBaseObject outParams = mngClass.InvokeMethod("Create", inParams, null); 
} 
+1

problème similaire http://stackoverflow.com/questions/2291921/c-wmi-runs-an-exe-on-a-remote-computer-that-then-runs-another-exe-on-the- same-co/2291991 # 2291991 – lsalamon

+0

Merci, ma recherche n'avait pas montré cela. Je vais lire et voir si ça aide. – Andy

+0

J'ai ajouté l'utilisateur et donné toutes les perms, mais cela ne fait aucune différence :( – Andy

Répondre

2

Après avoir suivi le lien proposé par Isalamon ci-dessus (merci) J'ai suivi les conseils de Jestro et ont réécrite en utilisant psexec.exe (qui peut être téléchargé à partir http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) au lieu de WMI. C'est comme si c'était un peu bizarre de le faire de cette façon, mais cela semble fonctionner.

Nouveau code pour toute personne qui connaît des problèmes similaires:

Process proc = new Process(); 
proc.StartInfo.FileName = "PsExec.exe"; 
proc.StartInfo.Arguments = string.Format("\\\\{0} -d -u {1}\\{2} -p {3} {4}", 
             remoteHost, 
             domain, 
             username, 
             password, 
             commandLine); 
proc.StartInfo.CreateNoWindow = true; 
proc.StartInfo.UseShellExecute = false; 
proc.Start(); 
1

WMI utilise simplement l'usurpation d'identité lors de l'exécution du processus à distance, ce qui ne vous donne pas accès au réseau. Si vous allez bien au-delà du code managé, vous pouvez simplement mapper un chemin UNC dans le processus distant. WMI a commencé à utiliser les informations d'identification de votre choix. Ensuite, vous avez l'accès au réseau que vous voulez. J'utilise NetUseAdd et NetUseDel de netapi32.dll pour mapper le chemin UNC. Voir http://pinvoke.net/ pour plus de détails sur l'utilisation des API.

0

Vous pouvez écrire toutes vos commandes dans un fichier batch sur l'ordinateur distant, ce qui inclut l'utilisation du réseau (inutile d'utiliser une lettre de lecteur) pour effectuer une authentification. Fonctionne bien comme ça. Je travaille toujours sur une alternative.

+0

En fait, si vous faites quelque chose comme ça ça marchera aussi, je viens de le tester: – Will

+0

OOps ici c'est: inParams ["CommandLine"] = "cmd/c \" "+" net use \\\\ serveur \\ c $ mot de passe/utilisateur: domaine \\ nom d'utilisateur && <\\ serveur \ partage \ quel.bat> "+" \ "> c: \\ temp \\ r_output.txt"; Je l'enregistre pour récupérer la sortie plus tard dans mon code. il se connecte en exécutant le fichier batch et non les commandes qu'il contient. – Will

1

Je sais ce que vous avez trié à l'aide PSEXEC, qui est un programme fantastique, mais si vous ne voulez revenir à WMI, avez-vous essayé permettant ce qui suit dans votre ConnectionOptions:

  • Le drapeau EnablePrivileges
  • Définition de l'emprunt d'identité sur ImpersonationLevel.Emprunter l'identité

qui effectue les opérations suivantes:

http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.impersonation.aspx

http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.enableprivileges.aspx

Je pense qu'ils devraient dire à votre WMI pour permettre effectivement le programme d'avoir les informations d'identification correctes et ainsi accéder à votre partage réseau

Questions connexes