Stackoverflow调用ManagementScope.Connect();

时间:2009-10-05 11:26:57

标签: c# unmanaged

获取错误:

  

未处理的类型异常   'System.StackOverflowException'   发生在System.Management.dll

我的书帖:

  

[管理原生过渡]
  System.Management.dll!System.Management.ManagementScope.InitializeGuts(对象   o)+ 0x1a3字节

  System.Management.dll!System.Management.ManagementScope.Initialize()   + 0xa3字节
System.Management.dll!System.Management.ManagementScope.Connect()   + 0x5 bytes
Computer_Managerment.exe!Computer_Managerment.WMI.ComputerInformation.ComputerInformation(string   ComputerName =“pc357”,字符串   UserName =“”,string Password =“”)   第228行+ 0xd字节C#
  Computer_Managerment.exe!Computer_Managerment.ScanAllComputers.Workerthread()   第95行+ 0x1e字节C#
  mscorlib.dll中!System.Threading.ThreadHelper.ThreadStart_Context(对象   状态)+ 0x66字节
  mscorlib.dll中!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext   执行上下文,   System.Threading.ContextCallback   回调,对象状态)+ 0x6f   字节
  mscorlib.dll中!System.Threading.ThreadHelper.ThreadStart()   + 0x44字节

我得到stackoverflow的代码:

try
{
  gManager = new ManagementScope(ConnectStr, oConn); //\\\\" + 
  gManager.Connect(); // This is where the crash happens
}
catch (UnauthorizedAccessException)
{
  // Code removed
}

该代码基本上适用于此诉讼 1)我有一份AD(超过1k)的所有计算机列表 2)我有10个线程旋转一个while循环,从Que List中获取一个compuer 3)当他们有一个计算机名时,他们会创建一个执行gManager.Connect()的ComputerInformation类的实例;再次崩溃
我的理解是这个崩溃/堆栈溢出发生在本机代码中,但我认为我做错了。如果需要更多代码,请发布它。

Pr请求更多代码:这是工作人员居住的代码(Normaly约10名工作人员)

internal struct stWorkList
{
    public Queue<string> Work;
    public List<ComputerInformation> CompInfo;
    public int FailedComputers;
    public int FailedPingCheck;
    public int SuccessComputers;
    public int TotalComputers;
    public int FailedAuth;
    public int FailedToContactWMIServer;
}
stWorkList gWorkList;

void Workerthread()
{
    Monitor.Enter(gUserName);
    Monitor.Enter(gPassword);
    string UserName = gUserName;
    string Password = gPassword;
    Monitor.Exit(gPassword);
    Monitor.Exit(gUserName);

    while (true)
    {
    Monitor.Enter(gWorkList.Work);
    if (gWorkList.Work.Count == 0)
    {
        Monitor.Exit(gWorkList.Work);
        break;
    }

    string ComputerName = gWorkList.Work.Dequeue();
    Monitor.Exit(gWorkList.Work);

    if (ComputerName == null)
        continue;

    ComputerInformation iCI = new ComputerInformation(ComputerName, UserName, Password);

    Monitor.Enter(gWorkList.CompInfo);
    gWorkList.CompInfo.Add(iCI);

    switch (iCI.Status)
    {
        case eComputerCheckStatus.Connected:
            gWorkList.SuccessComputers++;
            break;

        case eComputerCheckStatus.FailedPingTest:
            gWorkList.FailedPingCheck++;
            gWorkList.FailedComputers++;
            break;

        case eComputerCheckStatus.UnauthorizedAccessException:
            gWorkList.FailedComputers++;
            gWorkList.FailedAuth++;
            break;

        case eComputerCheckStatus.FailedToContactWMIService:
            gWorkList.FailedToContactWMIServer++;
            gWorkList.FailedComputers++;
            break;

        case eComputerCheckStatus.UnkownFailed:
            gWorkList.FailedComputers++;
            break;
    }

    Monitor.Exit(gWorkList.CompInfo);
    iCI.Dispose();
    }
}

ComputerInformation类中的构造函数

public ComputerInformation(string ComputerName, string UserName, string Password)
{
    gComputerName = ComputerName;
    gHardDriveList = new List<stHarddiskInfo>();
    gProccessInfo = new List<stProccessInfo>();
    gCPUInfo = new List<stCPUInformation>();
    gOSInfo = new stOSInfo();
    gMemoryInfo = new List<stMemoryInfo>();
    gPreformanceMemory = new stPreformanceMemory();
    gProccessOverView = new stProccessOverview();
    gMonitorInfo = new List<stMonitorInfo>();
    gNetworkInfo = new List<stNetworkInfo>();
    netMon = new Ping();

    PingResponse response = netMon.PingHost(ComputerName, 1);
    if (response == null || response.PacketsReceived == 0)
    {
        gStatus = eComputerCheckStatus.FailedPingTest;
        gHasError = true;
        return;
    }
    gComputerIP = response.ServerEndPoint.Address.ToString();

    ConnectionOptions oConn = new ConnectionOptions();
    oConn.Timeout = new TimeSpan(0, 0, 10);

    if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(UserName))
    {
        oConn.Username = UserName;
        oConn.Password = Password;
    }

    string ConnectStr = "\\\\" + ComputerName + "\\root\\cimv2";
    try
    {
        gManager = new ManagementScope(ConnectStr, oConn); //\\\\" + 
        gManager.Connect();     // this is where it crashes
    }
    catch (UnauthorizedAccessException)
    {
        gStatus = eComputerCheckStatus.UnauthorizedAccessException;
        gHasError = true;
        return;
    }
    catch (Exception Ex)
    {
    if (Ex.Message.Contains("The RPC server is unavailable"))
    {
        gStatus = eComputerCheckStatus.FailedToContactWMIService;
    }
    else
        gStatus = eComputerCheckStatus.UnkownFailed;

    gHasError = true;
    return;
    }

    gStatus = eComputerCheckStatus.Connected;

    try
    {
        GetRunningProccessInfo();
        GetCPUInformation();
        GetHardDriveInfo();
        GetOSInfo();
        GetMemoryInfo();
        GetMonitorInfo();
        GetComputerSystem();
    }
    catch
    {
        gStatus = eComputerCheckStatus.UnkownFailed;
        gHasError = true;
    }
}

3 个答案:

答案 0 :(得分:1)

这纯粹是猜测,但如果你做错了,那么它应该在传递给gManger初始化的参数中。

接下来,如果您要发布内容,则是oConn对象实例化。可能会有一些不正确的参数导致以后出现问题。

我没有在我的编码中使用这个类,所以除了查看参数外,这一切都是......有一点需要注意:

关于ManagementScope的MSDN文章有一个关于这个库无法被部分受信任的代码使用的有趣的tid-bit。

有关详细信息,请参阅this页面的.Net Framework安全性部分。

否则,祝你好运。

编辑:只是另外一个想法。由于这发生在多个线程中,如果尝试从线程中读取/写入字符串,则可能会出现一些问题。从代码中查看更大的上下文可能会有所帮助。

对不起,我在这里没有更多的帮助,但也许我的想法会帮助你(或其他任何人)解决这个问题。

答案 1 :(得分:1)

我怀疑你会在这里得到一个吸烟枪答案,因为你没有发布足够的代码。大多数StackOverflow错误都来自循环错误。

我运行您发布的代码没有任何问题。以下是我将如何调试:

确保您没有在线程上共享任何对象!关闭所有连接,不要重复使用它们。

  1. 运行您在线程循环之外发布的代码。
  2. 在没有线程的情况下循环运行代码。
  3. 使用线程池而不是Threadstart。一个好的TP是SmartThreadPool,它比内置的更好。
  4. 尝试以上操作,如果您仍然遇到问题,请发布更多代码。

答案 2 :(得分:1)

好点开始,就是检查这段代码是否抛出异常。

        ManagementScope scope = new ManagementScope(@"\\localhost\root\cimv2");
        scope.Connect();

<强>更新
您在iCI初始化时没有Monitor.Enter / Exit块(以及现有问题异常) 检查这是否是您可以进行简单记录的问题。

  gManager = new ManagementScope(ConnectStr, oConn); 
  Debug.WriteLine("connect to "+ComputerName+" by "+UserName+"/"+Password);
  gManager.Connect();             // this is where it crashes
  Debug.WriteLine("success on "+ComputerName+" by "+UserName+"/"+Password);

如果我的建议是正确的,你会在日志中收到这样的信息:
“连接到计算机1”
“连接到计算机2”
并且不可避免地例外。