【问题标题】:Network Authentication when running exe from WMI从 WMI 运行 exe 时的网络身份验证
【发布时间】:2011-01-25 12:43:01
【问题描述】:

我有一个需要使用 WMI 运行并访问网络共享的 C# exe。但是,当我访问共享时,我得到了 UnauthorizedAccessException。如果我直接运行 exe,则可以访问共享。在这两种情况下,我都使用相同的用户帐户。

我的应用程序有两个部分,一个在本地 PC 上运行的 GUI 客户端和一个在远程 PC 上运行的后端进程。当客户端需要连接到后端时,它首先使用 WMI 启动远程进程(代码复制如下)。远程进程会做很多事情,包括使用 Directory.GetDirectories() 访问网络共享并向客户端报告。

当客户端使用 WMI 自动启动远程进程时,它无法访问网络共享。但是,如果我使用远程桌面连接到远程计算机并手动启动后端进程,则可以成功访问网络共享。

WMI 调用中指定的用户和登录远程桌面会话的用户相同,所以权限应该相同,不是吗?

我在 Directory.Exists() 的 MSDN 条目中看到它声明“Exists 方法不执行网络身份验证。如果您在未经过预身份验证的情况下查询现有网络共享,Exists 方法将返回 false。”我认为这是相关的?如何确保用户在 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);
}

【问题讨论】:

  • 谢谢,我的搜索没有显示出来。我会读一读,看看是否有帮助。
  • 我已经添加了用户并给予了完整的权限,但它没有任何区别:(
  • 有没有不依赖(需要部署)第三方程序如 PsExec 的解决方案?

标签: c# .net wmi windows-authentication unc


【解决方案1】:

按照上面 Isalamon 建议的链接(谢谢)我遵循了 Jestro 的建议并使用 psexec.exe(可以从 http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx 下载)而不是 WMI 进行了重写。这样做感觉有点笨拙,但似乎奏效了。

为遇到类似问题的人提供新代码:

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();

【讨论】:

    【解决方案2】:

    WMI 仅在执行远程进程时使用模拟,这不会为您提供网络访问权限。如果您可以在托管代码之外使用,您可以使用您想要的任何凭据在 WMI 启动的远程进程中映射一个 UNC 路径。然后,您就拥有了所需的网络访问权限。我使用 netapi32.dll 中的 NetUseAdd 和 NetUseDel 来映射 UNC 路径。有关使用 API 的详细信息,请参阅http://pinvoke.net/

    【讨论】:

      【解决方案3】:

      我知道您已经使用 PSEXEC 对其进行了排序,这是一个很棒的程序,但是如果您确实想返回 WMI,您是否尝试过在 ConnectionOptions 中启用以下功能:

      • EnablePrivileges 标志
      • 将模拟设置为 ImpersonationLevel.Impersonate

      执行以下操作:

      获取或设置一个值,该值指示是否需要授予用户权限 启用连接操作。这个属性应该只 当执行的操作需要一定的用户权限时使用 启用(例如,机器重新启动)。

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


      获取或设置用于此连接中的操作的 COM 模拟级别。

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

      我认为他们应该告诉您的 WMI 实际上允许程序拥有正确的凭据,从而访问您的网络共享

      【讨论】:

      • 我刚刚在我编写的用于访问网络上的数据库的应用程序中进行了测试,如果我使用 WMI 和那些连接选项远程启动它,它就无法访问它,但如果我启动它就可以了应用程序直接登录到远程机器。你会认为它会提供访问权限。
      【解决方案4】:

      您可以将所有命令写入批处理文件到远程机器,其中包括网络使用(无需使用驱动器号)进行身份验证。那样工作得很好。我仍在研究替代方案。

      【讨论】:

      • 其实如果你做这样的事情也可以,我只是测试了一下:
      • OOps 这里是:inParams["CommandLine"] = "cmd /c \"" + "net use \\\\server\\c$ password /user:domain\\username && " + "\">c:\\temp\\r_output.txt";我记录它以便稍后在我的代码中检索输出。在这种情况下,它会记录运行批处理文件而不是其中的命令。
      猜你喜欢
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多