Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WMI API在提供错误凭据时挂起_C#_Wmi - Fatal编程技术网

C# WMI API在提供错误凭据时挂起

C# WMI API在提供错误凭据时挂起,c#,wmi,C#,Wmi,我找到了多个在线教程,用于使用c#建立到远程计算机的WMI连接。这些教程描述了如下过程: ConnectionOptions cOpts = new ConnectionOptions(); ManagementObjectCollection moCollection; ManagementObjectSearcher moSearcher; ManagementScope mScope; ObjectQuery oQuery; mScope = new ManagementScope(St

我找到了多个在线教程,用于使用c#建立到远程计算机的WMI连接。这些教程描述了如下过程:

ConnectionOptions cOpts = new ConnectionOptions();
ManagementObjectCollection moCollection;
ManagementObjectSearcher moSearcher;
ManagementScope mScope;
ObjectQuery oQuery;

mScope = new ManagementScope(String.Format("\\\\{0}\\{1}", host.hostname, "ROOT\\CIMV2"), cOpts);
oQuery = new ObjectQuery("Select * from Win32_OperatingSystem");
moSearcher = new ManagementObjectSearcher(mScope, oQuery);

moCollection = moSearcher.Get();
快乐路径案例-连接到本地主机,或使用正确的凭据连接到远程主机-工作正常。我正在进行一个项目,我们需要支持当前登录的帐户无法访问我们试图连接的远程主机的情况。也就是说,我们需要抓住这种情况,让用户注意到错误的凭据,并提示他们再次提供凭据

当我在ConnectionOptions对象中指定了远程计算机上没有上下文的凭据时,对moSearcher.Get()的调用(似乎)无限期挂起。类似地,对ManagementScope中Connect()函数的调用也以相同的方式挂起

<>我们在C++中有类似的逻辑来执行等效的WMI命令,并且我可以报告如果提供不正确的凭据,这些返回几乎立即返回。返回相应的“访问被拒绝”消息。我现在用于测试目的的主机与我们测试现有C++逻辑时使用的主机相同,所以我没有理由相信WMI在我们的环境中配置不正确。 我在c#中搜索了有关WMI连接的超时问题。我已经研究了ConnectionOptions和moSearcher.Options的超时属性。我还研究了可以与ManagementObjectSearcher实例关联的EnumerationOptions对象的ReturnInstant属性。这些选项对我没有预期的效果

我想我可以在一个单独的线程中执行这些WMI命令,并用监控代码包围该线程,如果该线程在合理的时间内没有返回,就会终止该线程。这似乎是c#WMI例程的所有消费者都需要完成的一项相当多的工作,我希望有一种更简单的方法。另外,我不确定通过这种方式杀死一个未完成的线程是否能够正确地清理WMI连接

ping远程主机对我没有任何好处,因为知道主机已启动并正在运行并不能告诉我所拥有的凭据是否合适(以及c#WMI调用是否将挂起)。是否有其他方法针对远程主机验证凭据


我总是有可能遗漏一个明显的标志或API,因为我认为其他人也遇到了这个问题。如有任何信息/协助,将不胜感激。感谢您阅读这篇冗长的文章。

我不知道您所有的特殊功能是什么,但这里有一个小例程可以帮助您排除故障,它应该能够将您的例程包装在一个线程中,并给它5秒钟的执行时间:

void Fake() {
  bool ok = false;
  ConnectionOptions cOpts = new ConnectionOptions();
  ManagementObjectCollection moCollection;
  ManagementObjectSearcher moSearcher;
  ManagementScope mScope;
  ObjectQuery oQuery;
  if (cOpts != null) {
    mScope = new ManagementScope(String.Format("\\\\{0}\\{1}", host.hostname, "ROOT\\CIMV2"), cOpts);
    if (mScope != null) {
      oQuery = new ObjectQuery("Select * from Win32_OperatingSystem");
      if (oQuery != null) {
        moSearcher = new ManagementObjectSearcher(mScope, oQuery);
        if (moSearcher != null) {
          ManualResetEvent mre = new ManualResetEvent(false);
          Thread thread1 = new Thread(() => {
            moCollection = moSearcher.Get();
            mre.Set();
          };
          thread1.Start();
          ok = mre.WaitOne(5000); // wait 5 seconds
        } else {
          Console.WriteLine("ManagementObjectSearcher failed");
        }
      } else {
        Console.WriteLine("ObjectQuery failed");
      }
    } else {
      Console.WriteLine("ManagementScope failed");
    }
  } else {
    Console.WriteLine("ConnectionOptions failed");
  }
}

希望这能对您有所帮助或提供一些想法。

我接受了jp的建议,将WMI API调用放在一个单独的线程中,如果它们超过超时时间,则可能会被终止。测试时,独立线程引发System.UnauthorizedAccessException类型的异常。我删除了线程逻辑并添加了catch语句来处理此异常类型。果不其然,调用ManagementObjectSearcher.Get()后几乎立即捕获异常

(请注意,System.Runtime.InteropServices.COMException catch语句已存在于我的代码中)


我不知道为什么这个异常在作为父线程的一部分执行时不会抛出(或者至少不会通过VS2010 IDE引起用户的注意)。在任何情况下,这正是我所寻找的,并且与C++中WMI连接例程的行为相一致。

谢谢JP的快速响应。单独的线程代码是一个选项。让我感觉更好的是发现其他人在以我的方式使用这些API时也遇到了同样的问题。还要注意的是,错误检查一直在通知开发人员您出了问题。如果您的代码一直通过错误检查步骤到达行
moCollection=moSearcher.Get()
,那么您可能需要查找
Get()
函数,查看它是否有任何重载或提供的错误代码。希望对您有所帮助。例如,在这种情况下,此链接>>错误检查无法保存我。也就是说,在构造函数之后,没有一个对象是空的。看来我得走另一条线了。希望其他遇到这个问题的人能从这篇文章中受益并节省时间。谢谢你的投入。
try
{
    moCollection = moSearcher.Get();
}

catch (System.UnauthorizedAccessException)
{
    return Program.ERROR_FUNCTION_FAILED;
}

catch (System.Runtime.InteropServices.COMException)
{
    MessageBox.Show("Error, caught COMException.");
    return Program.ERROR_FUNCTION_FAILED;
}