Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как узнать HANDLE окна по его PID? Create/OpenProcess. 
V
    Опции темы
MuForum
  Дата 25.2.2008, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



доброе время суток.
- Программа пишется на 'C++ Builder 6.0'. (Знаю, стоит руки оторвать, но сказали писать именно на Borland) =(
- Интересует следующий вопрос.

# Задача: Нужно узнать 'HANDLE' окна, не зная его 'class' и 'caption'. (Но, данную программу запускает моя программа).

P.S. -> Я решил пойти через Open/CreateProcess.

Код

AnsiString Path = ExtractFilePath(Application->ExeName);
AnsiString MainPath = Path + "main.exe /connect /u" + IP + " /p" + String(Port);

PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.wShowWindow = SW_SHOWNORMAL;

CreateProcess(0, MainPath.c_str(), 0, 0, FALSE, 0, 0, Path.c_str(), &si, &pi);
OpenProcess(PROCESS_ALL_ACCESS, false, pi.dwProcessId);
DWORD cpid = pi.dwProcessId;



- Далее я понимаю, что нужно как-то обратится к процессу по PID и уже извлечь HANDLE. Пробовал следующее:
Код

Process* localById = Process::GetProcessById(cpid);

-  Ошибки о использование неизвестных переменных. (Хотя нужные классы вроде подключил)

Это сообщение отредактировал(а) MuForum - 26.2.2008, 19:18


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
anwe
Дата 25.2.2008, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 1
Всего: 23



MuForum, да по PID'у можно узнать хэндл, но только ПРОЦЕССАPID - это идентификатор процесса, а не окна - process identifier.

Это сообщение отредактировал(а) anwe - 25.2.2008, 23:15
PM MAIL   Вверх
586
Дата 25.2.2008, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 39
Всего: 146



Перечисляешь окна функцией EnumWindows, узнаёшь идентификатор процесса с помощью GetWindowThreadProcessId и сравниваешь идентификаторы. Если совпали, то ты нашёл свое окно.

Добавлено через 1 минуту и 38 секунд
окон может быть найдено несколько
PM   Вверх
MuForum
Дата 25.2.2008, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Цитата(anwe @ 25.2.2008,  23:14)
MuForum, да по PID'у можно узнать хэндл, но только ПРОЦЕССАPID - это идентификатор процесса, а не окна - process identifier.

Это мне понятно, и не только мне, но и ежу... (Я немного некорректно выразился, мне минус...)
- Просто в C# я делал следующим образом:
Код

Process newProcess = new Process();
newProcess.StartInfo.FileName = FileList[j].FileName;
newProcess.StartInfo.Arguments = FileList[j].Parameters;
newProcess.StartInfo.WorkingDirectory = FileList[j].ShortPath;
newProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

try
{
    if(newProcess.Start())
    {
        if (newProcess.WaitForInputIdle())
        {
            newProcess.Refresh();
            FileList[j].Handle = newProcess.MainWindowHandle; // Вот Handle MainWindow...
            FileList[j].PID = newProcess.Id;
        }
        else
        {
            ...
        }
    }
    else
    {
        ...
    }
}
catch(Exception ex) {...};


# Вот функция, в которой идёт обращение к процессу по PID.
Код

        private void pstatus_visible_Click(object sender, EventArgs e)
        {
            int index = dgv_main.CurrentCell.RowIndex;
            try
            {
                System.Diagnostics.Process ProId = System.Diagnostics.Process.GetProcessById(FileList[index].PID);
                if (ProId.MainWindowHandle != IntPtr.Zero) FileList[index].Handle = ProId.MainWindowHandle;
                if (((ToolStripMenuItem)this.cms_dgv.Items[1]).DropDownItems[0].Text == "Show")
                {
                    SW.ShowWindow(FileList[index].Handle, SW.SW_SHOW);
                    ((ToolStripMenuItem)this.cms_dgv.Items[1]).DropDownItems[0].Text = "Hide";
                }
                else
                {
                    SW.ShowWindow(FileList[index].Handle, SW.SW_HIDE);
                    ((ToolStripMenuItem)this.cms_dgv.Items[1]).DropDownItems[0].Text = "Show";
                }
                    ...
            }
            catch (Exception ex) { .... };
        }



P.S. -> Спора нет, я понимаю, что это C# и тут много возможностей и многое облегченно для работы, но, по сути, если у тебя есть PID процесса, то ты непосредственно можешь обращается к процессу, а следовательно и к свойствам его, а следовательно как-то ты должен выходить именно на MainWindow.
- Если я не прав, но рассталкуйте...

Это сообщение отредактировал(а) MuForum - 25.2.2008, 23:46


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
MuForum
Дата 26.2.2008, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



# for all - Может кому пригодится...


# Вопрос: Как узнать 'Handle' окна, зная только PID процесса?

# Способ №1:
Код

HANDLE hWnd = ::GetTopWindow(0);
HANDLE WindowHandle = NULL;
while(hWnd)
{
    DWORD pid;
    DWORD dwTheardId = ::GetWindowThreadProcessId(hWnd, &pid);

    if(pid == cpid) // your process id;
    {
        WindowHandle = hWnd;
        break;
    }
    Sleep(100);
    hWnd = ::GetNextWindow(hWnd, GW_HWNDNEXT);
}



# Способ №2:
Код

int is_found = 0;
HANDLE WindowHandle = NULL;
...
        while(is_found == 0)
        {
                EnumWindows(WNDENUMPROC(EnumWindowsProc), NULL);
                Sleep(100);
        }
...
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
        if(IsWindow(hWnd) && is_found == 0)
        {
                DWORD pid;
                DWORD dwTheardId = ::GetWindowThreadProcessId(hWnd, &pid);
                if(pid == cpid)
                {
                        WindowHandle = hWnd;
                        SetWindowText(WindowHandle, "WoW - I find Window Handle :)");
                        is_found = 1;
                }
        }
        return 1;
}



Это сообщение отредактировал(а) MuForum - 26.2.2008, 19:14


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
MuForum
  Дата 22.4.2008, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Цитата(586)

Перечисляешь окна функцией EnumWindows, узнаёшь идентификатор процесса с помощью GetWindowThreadProcessId и сравниваешь идентификаторы. Если совпали, то ты нашёл свое окно.

Добавлено @ 23:21
окон может быть найдено несколько


Вот я сейчас как раз столкнулся...

- Ищу Handle окна по PID.
- И мне находит несколько окон...

# Вопрос: Как найти Handle главного окна?
- И вообще как их можно разобрать, чтобы было ясно, какое окно?

Это сообщение отредактировал(а) MuForum - 22.4.2008, 23:45


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
anwe
Дата 22.4.2008, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 1
Всего: 23



Цитата(MuForum @  22.4.2008,  22:43 Найти цитируемый пост)
# Вопрос: Как найти Handle главного окна?

MuForum, сам же привел два способа.
PM MAIL   Вверх
586
Дата 23.4.2008, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 39
Всего: 146



Определить стиль окна. У главного окна наверняка есть системное меню и заголовок, нету стиля WS_CHILD, и нету родителя GetParent(hWnd) == NULL
http://forum.vingrad.ru/index.php?showtopi...t&p=1430830
PM   Вверх
xvr
Дата 23.4.2008, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(586 @ 23.4.2008,  00:01)
Определить стиль окна. У главного окна наверняка есть системное меню и заголовок, нету стиля WS_CHILD, и нету родителя GetParent(hWnd) == NULL
http://forum.vingrad.ru/index.php?showtopi...t&p=1430830

Если это программа писанная на BCB, то это не так - BCB создает невидимое окно (оно соотвествует переменной Application), а главная форма является его потомком.

PM MAIL   Вверх
586
Дата 23.4.2008, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 39
Всего: 146



Цитата(xvr @  23.4.2008,  16:59 Найти цитируемый пост)
Если это программа писанная на BCB, то это не так - BCB создает невидимое окно (оно соотвествует переменной Application), а главная форма является его потомком.

В WinAPI нету понятия главного окна. Это понятие действует внутри приложения (внутри VCL - библиотеки визуальных компонентов). Если будет несколько форм, то снаружи невозможно узнать, главная ли эта форма, ли нет, не обращаясь к классу формы или VCL. Все окна создаются одинаково - через CreateWindowEx.
Можно попробовать искать видимое окно со стилем WS_CAPTION, но бывают же главные окна без заголовка.
Можно предположить, что главные окна отображаются на панели задач, а у таких окон нету родительского окна и стиля WS_CHILD.
PM   Вверх
xvr
Дата 23.4.2008, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(586 @ 23.4.2008,  20:09)
Цитата(xvr @  23.4.2008,  16:59 Найти цитируемый пост)
Если это программа писанная на BCB, то это не так - BCB создает невидимое окно (оно соотвествует переменной Application), а главная форма является его потомком.

В WinAPI нету понятия главного окна. Это понятие действует внутри приложения (внутри VCL - библиотеки визуальных компонентов). 

Да, но пользователь в таких тонкостях не разбирается  smile Для него главное окно то, которое появилось первым (и обычно единственным, конечно до явных действий пользователя)
Цитата

Если будет несколько форм, то снаружи невозможно узнать, главная ли эта форма, ли нет, не обращаясь к классу формы или VCL. Все окна создаются одинаково - через CreateWindowEx.
Да.
Цитата

Можно попробовать искать видимое окно со стилем WS_CAPTION, но бывают же главные окна без заголовка.
Можно предположить, что главные окна отображаются на панели задач, а у таких окон нету родительского окна и стиля WS_CHILD.
Для VCL это не так. Окно без родительского окна у него невидимо, но отображается на панели задач. Главное окно (первая созданная VCL форма) равно как и все остальные, имеют родителем это невидимое окно.
Именно это я и хотел подчеркнуть своим предыдущим постом.
PM MAIL   Вверх
MuForum
Дата 24.4.2008, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



# for all - В моём случае проверка на 'WS_CHILD' и 'WS_CAPTION' не помогла...

- Решить проблему удалось следующим образом:
Код

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
    if(HandleStatus)
    {
        GetWindowThreadProcessId(hWnd, &_cPID);
        if(_cPID == MU_PID)
        {
            long style = GetWindowLong(hWnd, GWL_STYLE);
            if(!(style & WS_THICKFRAME) && (style & WS_SYSMENU))
            {
                g_hWnd = hWnd;
                HandleStatus = false;
                return 0;
            }
        }
    }
    return 1;
}


Это сообщение отредактировал(а) MuForum - 24.4.2008, 16:57


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
586
Дата 24.4.2008, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 39
Всего: 146



MuForum,  а не проще было FindWindow воспользоваться?
PM   Вверх
MuForum
  Дата 24.4.2008, 18:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Цитата(586 @ 24.4.2008,  18:18)
MuForum,  а не проще было FindWindow воспользоваться?

Для частичной защиты игры от читов, было сделано динамическое создание текста 'class', Чтобы нельзя было находить окно при помощи WinApi функции: 'FindWindows()'.

P.S. -> То есть при каждом новом запуске игры, у окна будет другой 'class' и 'caption'.

Это сообщение отредактировал(а) MuForum - 24.4.2008, 18:23


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1230 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.