Stackoverflow вызывает ManagementScope.Connect (); - PullRequest
4 голосов
/ 05 октября 2009

Ошибка при получении:

Необработанное исключение типа '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 байт
Computer_Managerment.exe! Computer_Managerment.WMI.ComputerInformation.ComputerInformation (строка ComputerName = "pc357", строка UserName = "", строка 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 ExecutionContext, System.Threading.ContextCallback обратный вызов, состояние объекта) + 0x6f байт
mscorlib.dll! System.Threading.ThreadHelper.ThreadStart () + 0x44 байта

Код, где я получаю переполнение стека:

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

Код в основном работает в этой части
1) У меня есть список всех компьютеров в AD (более 1k)
2) У меня есть 10 потоков, которые крутят цикл while, получая компьютер из списка очередей.
3) Когда у них есть имя компьютера, они создают экземпляр класса ComputerInformation, который выполняет gManager.Connect (); это снова терпит крах.

Это мое понимание того, что этот сбой / стекопотока происходит внутри собственного кода, но я предполагаю, что я делаю что-то не так. Если вам понадобится еще какой-нибудь код, пожалуйста, напишите его.

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

Ответы [ 3 ]

1 голос
/ 15 октября 2009

Я сомневаюсь, что вы получите ответ о курении пистолета, так как вы не ввели достаточно кода. Большинство ошибок StackOverflow происходят из-за ошибки зацикливания.

Я без проблем запустил отправленный вами код. Вот как бы я отлаживал:

Убедитесь, что вы не делитесь никакими объектами в потоках !!! Закройте все соединения и не используйте их повторно.

  1. Запустите код, который вы разместили вне цикла потока.
  2. Выполнить код в цикле без многопоточности.
  3. Используйте пул потоков вместо Threadstart. Хороший TP - SmartThreadPool , который имеет преимущества перед встроенным.

Попробуйте описанное выше, и если у вас все еще есть проблема, напишите больше кода.

1 голос
/ 15 октября 2009

Хорошее начало, чтобы проверить, вызывает ли этот код исключение.

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

Обновление
У вас нет блока Monitor.Enter / Exit при инициализации iCI (и там, где существует исключение проблемы).
чтобы проверить, если это проблема, вы можете сделать простой журнал.

  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"
и безотлагательно исключение.

1 голос
/ 14 октября 2009

Это чисто предположение, но если вы что-то делаете неправильно, то это должно быть в параметрах, которые передаются при инициализации gManger.

Следующая вещь, если вы хотите что-то опубликовать, это создание объекта oConn. Возможно, там есть некоторые неправильные параметры, которые позже вызывают проблемы.

Я не использовал этот класс в своем коде, так что, помимо просмотра параметров, это все ... с одной оговоркой:

В статье MSDN по ManagementScope содержался интересный комментарий о том, что эта библиотека не может использоваться частично доверенным кодом.

Дополнительные сведения см. В разделе «Безопасность .Net Framework» на этой странице.

В противном случае, удачи.

РЕДАКТИРОВАТЬ: Просто дополнительная мысль. Поскольку это происходит с несколькими потоками, могут возникнуть некоторые проблемы, если строка пытается быть прочитана из / записана из разных потоков. Может быть полезно увидеть более широкий контекст из вашего кода.

Извините, я не помогу вам больше, но, возможно, мои мысли помогут вам (или кому-либо еще) решить эту проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...