Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/40: Рейтинг темы: голосов - 40, средняя оценка - 4.70
4 / 4 / 1
Регистрация: 06.01.2012
Сообщений: 54
1

Получить id процесса родителя, если исходный id процесса дочерний

17.12.2013, 00:04. Показов 7600. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. У меня есть вот такой код на C#, который должен позволить получить id процесса родителя, если исходный id процесса дочерний:
C#
1
2
3
4
5
6
7
8
9
10
   Process[] procs = Process.GetProcesses();
            foreach (Process proc in procs)
            {
                int parentId = 0;
                using (obj = new ManagementObject("win32_process.handle=" + proc.Id.ToString()))
                {
                     obj.Get();
                     parentId = Convert.ToInt32(obj["ParentProcessId"]);
                }
            }
...объект obj создается и к win32_process.handle добавляется id процесса, однако obj.Get() выдает исключение "Не найден указанный модуль. (Исключение из HRESULT: 0x8007007E)" — что это может обозначать? Я уж подумал, может, дело в том, что у меня Windows 8, хотя в принципе при чем тут это? Кто знает, почему не происходит привязки к управляющему объекту сведений о процессе? Не могу из-за этого решить задачу...

Добавлено через 1 час 12 минут
Проверил в Windows XP и Windows 7 — все отлично работает, а вот под восьмеркой отказывается находить модуль...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.12.2013, 00:04
Ответы с готовыми решениями:

В чем сходство процесса-родителя и процесса-ребенка?
В чем состоит сходство процесса родителя и процесса ребенка?

Получить ID процесса если известно его хэндл, название окна или название процесса
а как получить ID процесса если известно его хэндл, название окна или название процесса?

Передача указателя из родительского процесса в дочерний
Здравствуйте! Стоит следующая задача. Есть процесс, который перехватывает пакеты из сети и...

Узнать id родителя процесса
Как узнать id родителя процесса? Нашел информацию что можно вывести из структуры PROCESSENTRY32....

8
Администратор
Эксперт .NET
9610 / 4752 / 761
Регистрация: 17.04.2012
Сообщений: 9,606
Записей в блоге: 14
17.12.2013, 18:52 2
Цитата Сообщение от lesha1980 Посмотреть сообщение
Исключение из HRESULT: 0x8007007E
Этот код возвращается, когда программа не может найти библиотеку. Вставьте проверку на наличие библиотек.
Также: DllNotFoundException with HRESULT 0x8007007E when loading 64-bit dll
1
4 / 4 / 1
Регистрация: 06.01.2012
Сообщений: 54
18.12.2013, 01:03  [ТС] 3
Цитата Сообщение от tezaurismosis Посмотреть сообщение
Этот код возвращается, когда программа не может найти библиотеку. Вставьте проверку на наличие библиотек.
Также: DllNotFoundException with HRESULT 0x8007007E when loading 64-bit dll
Это интересно, но в восьмерке отсутствует куча псевдонимов, связанных с классами WMI... Process, к примеру, связанный с Win32_Process. Пытаюсь вручную подключиться на root/cimv2 через wbemtest выдает, что отсутствует модуль win32... Можно ли его установить? К примеру, в восьмерке напрочь отсутствовал .net framework более ранних версий до 3.5... пришлось устанавливать из дистрибутива восьмерки. Не может ли в этом случае быть что-либо подобное?

Добавлено через 1 час 15 минут
Встретил статью на support.microsoft.com, о том, что в Windows 8, Windows Server 2012 и Windows RT есть баг в работе WMI, который исправляется с помощью обновления, но ни одно из указанных обновлений не подходит к моему компьютеру...

В общем тогда поменяю вопрос.


Как можно по-другому получить id родительского процесса из id дочернего процесса не прибегая к ManagementObject и к WMI?
0
Администратор
Эксперт .NET
9610 / 4752 / 761
Регистрация: 17.04.2012
Сообщений: 9,606
Записей в блоге: 14
18.12.2013, 11:42 4
Лучший ответ Сообщение было отмечено tezaurismosis как решение

Решение

lesha1980, у меня о WMI сложилось ощущение как о не самой лучшей технологии из-за регулярных глюков и я стараюсь её всеми силами избегать.
С трудом нашёл код на VB, который завершает дерево процессов с помощью WinAPI и только. Возможно вам удастся его адаптировать
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Private Declare Function CreateToolhelp32Snapshot Lib
"KERNEL32.DLL" _
(ByVal dwFlags As Integer, ByVal th32ProcessID As Integer) As
Integer
Private Declare Function Process32First Lib "KERNEL32.DLL" _
(ByVal hSnapshot As Integer, ByVal PE As Byte()) As Integer
Private Declare Function Process32Next Lib "KERNEL32.DLL" _
(ByVal hSnapshot As Integer, ByVal PE As Byte()) As Integer
Private Declare Function CloseHandle Lib "KERNEL32.DLL" _
(ByVal hObject As Integer) As Integer
 
Private Sub KillAllAssociatedProcesses(ByVal track As String)
Dim localAll As Process() = Process.GetProcesses()
For Each i As Process In localAll
Dim ParentProcessID As Integer
ParentProcessID = GetParentProcessID(i.Id)
If ParentProcessID = ClientTracks(Track).Process.Id Then
Process.GetProcessById(i.Id).Kill()
End If
Next
End Sub
 
Function GetParentProcessID(ByVal id As Integer) As Integer
Dim b(564 - 1) As Byte
'write the size into the structure
BitConverter.GetBytes(SIZEOF_PROCESSENTRY32).CopyT o(b,
SIZE_OFFSET)
Dim h As Integer =
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
Try
Dim rv As Integer = Process32First(h, b)
If rv <1 Then
Throw New Exception("Could not enumerte processes.")
End If
While rv = 1
Dim pid As Integer = BitConverter.ToInt32(b,
PROCESS_OFFSET)
Dim parent As Integer = BitConverter.ToInt32(b,
PARENT_OFFSET)
If pid = id Then
Return parent
End If
rv = Process32Next(h, b)
End While
Finally
CloseHandle(h)
End Try
 
Return -1
 
End Function
1
4 / 4 / 1
Регистрация: 06.01.2012
Сообщений: 54
18.12.2013, 23:06  [ТС] 5
tezaurismosis,
Когда гуглил, то я его видел и подумал, что это будет один из вариантов. В принципе у меня два варианта, включая этот без использования ManagmentObject. В данном случае функция GetParentProcessId, как я понял, осуществляет обход процессов (ProcessFirst32 и ProcessNext32) и запись данных о процессе в структуру PROCESSENTRY32. Конечно же, в VB я совсем не силен, но в принципе разобрать можно — "интуитивно понятный интерфейс" у программки. Ок. Все равно спасибо.

Добавлено через 10 часов 4 минуты
Обнаружил очень хороший ресурс в сети, где описывается вызов системных функций и структур Win Api в приложениях создаваемых для платформы .net. Кому будет интересно: http://www.pinvoke.net/. Попытаюсь с его помощью реализовать получение id через системные функции...

Добавлено через 1 минуту
К слову там есть и реализация PROCESSENTRY32 и тех функций, что указаны в коде постом выше...

Добавлено через 53 минуты
На этом же сайте обнаружил кажется и ответ на свой вопрос. Привожу код (Это пример со страницы с реализацией в .net функции createtoolhelp32snapshot):

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
static class myProcessEx
{   
    //inner enum used only internally
    [Flags]
    private enum SnapshotFlags : uint
    {
    HeapList = 0x00000001,
    Process = 0x00000002,
    Thread = 0x00000004,
    Module = 0x00000008,
    Module32 = 0x00000010,
    Inherit = 0x80000000,
    All = 0x0000001F,
    NoHeaps = 0x40000000
    }
    //inner struct used only internally
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct PROCESSENTRY32
    {
    const int MAX_PATH = 260;
    internal UInt32 dwSize;
    internal UInt32 cntUsage;
    internal UInt32 th32ProcessID;
    internal IntPtr th32DefaultHeapID;
    internal UInt32 th32ModuleID;
    internal UInt32 cntThreads;
    internal UInt32 th32ParentProcessID;
    internal Int32 pcPriClassBase;
    internal UInt32 dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
    internal string szExeFile;
    }
 
    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern IntPtr CreateToolhelp32Snapshot([In]UInt32 dwFlags, [In]UInt32 th32ProcessID);
 
    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32First([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
 
    [DllImport("kernel32", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    static extern bool Process32Next([In]IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
 
    [DllImport("kernel32", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle([In] IntPtr hObject);
 
    // get the parent process given a pid
    public static Process GetParentProcess(int pid)
    {
    Process parentProc = null;
    IntPtr handleToSnapshot = IntPtr.Zero;
    try
    {
        PROCESSENTRY32 procEntry = new PROCESSENTRY32();
        procEntry.dwSize = (UInt32)Marshal.SizeOf(typeof(PROCESSENTRY32));
        handleToSnapshot = CreateToolhelp32Snapshot((uint)SnapshotFlags.Process, 0);
        if (Process32First(handleToSnapshot, ref procEntry))
        {
        do
        {
            if (pid == procEntry.th32ProcessID)
            {
            parentProc = Process.GetProcessById((int)procEntry.th32ParentProcessID);
            break;
            }
        } while (Process32Next(handleToSnapshot, ref procEntry));
        }
        else
        {
        throw new ApplicationException(string.Format("Failed with win32 error code {0}", Marshal.GetLastWin32Error()));
        }
    }
    catch (Exception ex)
    {
        throw new ApplicationException("Can't get the process.", ex);
    }
    finally
    {
        // Must clean up the snapshot object!
        CloseHandle(handleToSnapshot);
    }
    return parentProc;
    }
 
    // get the specific parent process
    public static Process CurrentParentProcess
    {
    get
    {
        return GetParentProcess(Process.GetCurrentProcess().Id);
    }
    }
 
    static void Main()
    {
    Process pr = CurrentParentProcess;
 
    Console.WriteLine("Parent Proc. ID: {0}, Parent Proc. name: {1}", pr.Id, pr.ProcessName);
    }
}
1
Почетный модератор
Эксперт .NET
8722 / 3674 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
19.12.2013, 01:21 6
Лучший ответ Сообщение было отмечено tezaurismosis как решение

Решение

Вариант попроще: Узнать родительский процесс
1
4 / 4 / 1
Регистрация: 06.01.2012
Сообщений: 54
19.12.2013, 13:11  [ТС] 7
Да... интересно... и, очевидно, просто лучше. Но в отношении NtQueryInformationProcess есть такая информация:

Retrieves information about the specified process. This function is available in Windows 2000 and Windows XP, but it may be altered or unavailable in subsequent versions.

В машинном переводе это выглядит так: Получает информацию об указанном процессе. Эта функция доступна в Windows 2000 и Windows XP, но это может быть изменено или недоступны в последующих версиях.

Это на том же сайте, что я указал...

И на msdn:

[NtQueryInformationProcess may be altered or unavailable in future versions of Windows. Applications should use the alternate functions listed in this topic.]
Retrieves information about the specified process.

Машинный перевод:

[NtQueryInformationProcess могут быть изменены или недоступны в будущих версиях Windows. Приложения должны использовать альтернативные функции, перечисленные в этом разделе.]
Получает информацию об указанном процессе.

Т.е. данная функция может оказаться недоступной в следующих после 2000 и ХР версиях операционки Windows. А так бесспорно вариант очень хорош и прост в исполнении без внутренних многоходовок цикла по нахождению выбранного процесса, чтобы получить о нем информацию. Минус, конечно, что примененные системные функция и структура недокументированы. Если, к примеру, последнее поле в структуре PROCESS_BASIC_INFORMATION в варианте с загрузкой для .NET платформы описывается как: public IntPtr InheritedFromUniqueProcessId —
то на msdn это поле указывается как зарезервированное за операционной системой. И кроме того, при первом рассмотрении не возникнет ли проблем с размером буфера для получаемой информации? Мне кажется, что этот способ хоть и лучше, но рискованней...В смысле может и сработать, а может и нет, исходя из выше изложенной инфы...
0
Почетный модератор
Эксперт .NET
8722 / 3674 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
19.12.2013, 14:19 8
Цитата Сообщение от lesha1980 Посмотреть сообщение
Т.е. данная функция может оказаться недоступной в следующих после 2000 и ХР версиях операционки Windows
Не беспокойтесь, это один из основных сервисов в Windows для получения информации о состоянии процессов, в ближайших версиях он никуда не исчезнет. PROCESS_BASIC_INFORMATION не менялась со времен её появления. Хотя в Win 8 и начались подвижки в направления скрытия информации о ядерных структурах для запросов из ring3, в этой структуре никакой подобной информации нет, т.е. шанс что она будет менятся стремится к 0.
1
4 / 4 / 1
Регистрация: 06.01.2012
Сообщений: 54
19.12.2013, 22:59  [ТС] 9
Цитата Сообщение от NickoTin Посмотреть сообщение
Не беспокойтесь, это один из основных сервисов в Windows для получения информации о состоянии процессов, в ближайших версиях он никуда не исчезнет. PROCESS_BASIC_INFORMATION не менялась со времен её появления. Хотя в Win 8 и начались подвижки в направления скрытия информации о ядерных структурах для запросов из ring3, в этой структуре никакой подобной информации нет, т.е. шанс что она будет менятся стремится к 0.
Ну что ж отлично... Спасибо вам большое. Вариант действительно хорош.

Добавлено через 7 часов 2 минуты
Работает отлично и очень просто...
0
19.12.2013, 22:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.12.2013, 22:59
Помогаю со студенческими работами здесь

Как узнать родителя процесса?
Подскажите, как узнать родителя какого-либо процесса?

Определение потомка и родителя процесса
Здравствуйте! Возник вопрос, как определить потомка и родителя процесса. В терминале ввожу ps -aux...

Сохранение дочерного процесса при завершении родителя
запускаю сторонее приложение из под моего (создаю дочерный процесс, не создавая новое окно)...

Через память передавать координаты и размер окружности с родительского процесса в дочерний
Написать программу, в которой задаются координаты и размер окружности, а в дочернем процессе в...

Родительский и дочерний процесс: почему запуск начинается сразу с дочернего процесса?
Родительский процесс должен считать содержимое текстового файла и передать его дочернему процессу....

Чтение памяти другого процесса по таймеру: нужно ли закрывать хэндл процесса?
В моём варианте работает так: По таймеру (0,1 сек) определяю ID процесса по ехе-шнику, получаю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru