Stackoverflow 调用 ManagementScope.Connect();

发布于 2024-08-07 04:19:56 字数 5640 浏览 2 评论 0原文

我收到错误:

未处理的类型异常 '系统.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 字节
Computer_Managerment.exe!Computer_Managerment.WMI.ComputerInformation.ComputerInformation(字符串 计算机名 = "pc357", 字符串 用户名=“”,字符串密码=“”) 第 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
}

该代码基本上可以在这个 fastion 中工作
1)我有 AD 中所有计算机的列表(超过 1k)
2) 我有 10 个线程旋转 while 循环,将计算机从 Que 列表中取出。
3) 当他们拥有计算机名称时,他们会创建一个执行 gManager.Connect() 的 ComputerInformation 类的实例;再次崩溃。

据我了解,此崩溃/堆栈溢出发生在本机代码内部,但我认为我做错了什么。如果需要更多代码,我很高兴发布它。

Pr 请求更多代码:这是工作人员居住的代码(通常大约 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;
    }
}

Error im getting:

An unhandled exception of type
'System.StackOverflowException'
occurred in System.Management.dll

My callstack:

[Managed to Native Transition]
System.Management.dll!System.Management.ManagementScope.InitializeGuts(object
o) + 0x1a3 bytes

System.Management.dll!System.Management.ManagementScope.Initialize()
+ 0xa3 bytes
System.Management.dll!System.Management.ManagementScope.Connect()
+ 0x5 bytes
Computer_Managerment.exe!Computer_Managerment.WMI.ComputerInformation.ComputerInformation(string
ComputerName = "pc357", string
UserName = "", string Password = "")
Line 228 + 0xd bytes C#
Computer_Managerment.exe!Computer_Managerment.ScanAllComputers.Workerthread()
Line 95 + 0x1e bytes C#
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object
state) + 0x66 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext
executionContext,
System.Threading.ContextCallback
callback, object state) + 0x6f
bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()
+ 0x44 bytes

Code where i get the stackoverflow:

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

The code basicly works in this fastion
1) I have a list of all the computers in AD ( Over 1k )
2) I have 10 threads spinning a while loop getting a compuer out of the Que List.
3) When they have a computer name they make a instance of the ComputerInformation class that does the gManager.Connect(); that again crashes.

Its my understanding that this crash/stackoverflow is happening inside native code, but i assume im doing something wrong. If any more code is required il happely post it.

Pr request more code: This is the code that the workers live in ( Normaly around 10 workers )

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

Constructor in the ComputerInformation class

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

这样的小城市 2024-08-14 04:19:56

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

        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”
并立即例外。

good point to start, is to check if this code is throwing exception.

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

Update
You doesnt have Monitor.Enter/Exit block on iCI initialization (and where existing problem exception).
to check if this is the problem you can make simple log.

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

if my suggestion is right, you will receive in log, something like this:
"connect to computer1"
"connect to computer2"
and immidiately exception.

避讳 2024-08-14 04:19:56

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

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

我在编码中没有使用过这个类,所以除了查看参数之外,这就是全部......但有一个警告:

关于 ManagementScope 的 MSDN 文章有一个有趣的花絮,关于这个库无法被其他人使用部分受信任的代码。

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

否则,祝你好运。

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

很抱歉,我在这里无法提供更多帮助,但也许我的想法会帮助您(或其他任何人)解决这个问题。

This is purely speculation, but if it is something you are doing wrong, then it should be in the parameters that are being passed to the initialization of gManger.

The next thing, if you were to post something, is the oConn object instantiation. Possibly there are some incorrect parameters there that are causing problems later on.

I haven't used this class in my coding, so beyond just looking at the parameters, this is all... with one caveat:

the MSDN article on ManagementScope had an interesting tid-bit about this library not being able to be used by partially trusted code.

For more information see .Net Framework Security section of this page.

Otherwise, good luck.

EDIT: Just an additional thought. Since this is happening with multiple threads, there may be some issues if a string is trying to be read from/written to from across threads. It might be helpful to see a larger context from your code.

I'm sorry I'm not of more help here, but maybe my thoughts will help you (or anyone else) resolve this.

紫﹏色ふ单纯 2024-08-14 04:19:56

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

我运行了你发布的代码,没有遇到任何问题。以下是我的调试方法:

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

  1. 运行您在线程循环之外发布的代码。
  2. 在循环中运行代码,无需线程。
  3. 使用线程池代替Threadstart。一个好的 TP 是 SmartThreadPool,它比内置的有优势。

尝试上述方法,如果仍然有问题,请发布更多代码。

I doubt you will get a smoking gun answer here as you have not posted enough code. Most StackOverflow errors come from a looping error.

I ran the code you posted with no trouble. Here is how I would debug:

Make sure you are not sharing any object on the threads!!! Close all connections and do not reuse them.

  1. Run the code you posted outside of the thread loop.
  2. Run the code in a loop without threading.
  3. Use the thread pool instead of Threadstart. A good TP one is SmartThreadPool which has advantages over the built in one.

Try the above and if you still have a problem post more code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文