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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> создать скрытое окно консоли, AllocConsole(). Как создать скрытое окно 
V
    Опции темы
-Kp0T-
Дата 15.4.2007, 04:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



 Доброго времени суток.
Задача: создать скрытое окно консоли (не создать а потом скрыть - от этого мелькание).
Условия: GUI приложение вызывает AllocConsole(). Надо сразу получить скрытое окно. Отловить HWND окна и SW_HIDE-ить без мелькания не удается.

Тщательней прогуглив пришел выводу что запуск скрытой консоли - довольно острая проблема. Добрался. Гуру здесь:
http://readlist.com/lists/cygwin.com/cygwin/0/2440.html (здесь код)   с ссылкой на
http://cygwin.com/ml/cygwin/2006-05/msg00471.html

Если чесно, то меня VS7 C++ одолел, я так и не смог грамотно портировать код. Ругается то на указатели, то на параметры ввода функции то на анахронизм (я не шучу. Ошибка 4229: modifiers on data are ignored).
Ппомогите кто чем может. Хотя бы ссылку на исчерпывающую (с примерами) литературу про Run-Time Dynamic Linking.

Это сообщение отредактировал(а) -Kp0T- - 15.4.2007, 08:29
PM MAIL   Вверх
GremlinProg
Дата 15.4.2007, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



это API вариант: http://msdn2.microsoft.com/en-us/library/ms682499.aspx
это сишный: http://msdn2.microsoft.com/en-us/library/9...s4b(VS.80).aspx

оба, по сути, делают одно и то же: запускают скрытый дочерний процесс с возможностью анализа его std-вывода.

Апи'шный вариант дает больше свободы: позволяет не только открыть пайп на одну передачу, но и поддерживать диалог в течении длительного времени.

Выбирай то, что по-душе...


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
-Kp0T-
Дата 17.4.2007, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



2GremlingProg::thx,но это немного не то.
Создать консоль с GUI программы и установить вывод на stdout можно и так:
Код

#include <fcntl.h>
#include <io.h>
 ...
 int hCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
 *stdout = *(::_fdopen(hCrt, "w"));
 ::setvbuf(stdout, NULL, _IONBF, 0);
 *stderr = *(::_fdopen(hCrt, "w"));
 ::setvbuf(stderr, NULL, _IONBF, 0);
 ...

Ну да ладна не об этом речь.

Как всегда приходиться копаться самому...
Если кому то интересно выкладываю решение проблемы (правда немного непрограммерсками методами, но все же).
 
 Немного помониторив консоль узнал что в win2000,winXP,win2003 ( если у кого VISTA просьба проверить и выложить результаты ) хранят параметры консоли в ключе "WindowPosition" типа REG_DWORD, секции HKCU\Console\pathdrive:_pathfolder1_pathfolder2_filename.exe
 То есть для любой программы (например, pathdrive:\pathfolder1\pathfolder2\filename.exe) создается вышеупомянутый ключ и переменная WindowsPosition. Тип ее DWORD. В regedit отображены в hex формате. биты 0-15 отвечают за X координату, 16-31 за Y на мониторе. То есть если значение WindowsPosition установить 0x7FFF7FFF в режиме 1152x864 получаем предельные координаты XY(1148,860) - и это присваивается верхнему левому углу консольного окна (напомню, последние биты каждого слова - знаковые, т.е. 0xFFFFFFFF дает точку XY(-1,-1) ). То есть получаем что до выполнения ShowWindow(hCons,SW_HIDE) консольного окна не видно!

Замечание: Вы наверное задались вопросом какую координату для верхнего левого угла даст 0x7FFF7FFF если разрешение экрана 1600x1200. А на деле получаем точку (1596,1196). То есть от разрешения коодрината не зависит. Интересно что будет с расширенным рабочим столом на 2-й монитор (если есть возможность, пожалуйста, протестируйте, пока у мня нет оного).

Из вышесказанного следует что перед созданием окна консоли надо создать переменную WindowsPosition со значением 0x7FFF7FFF по вышеупомянутой секции в реестре:

Код

...
 DWORD dwWPos=0x7FFF7FFF;
 char *pCmd, *ptCmd;
 ptCmd=pCmd=GetCommandLine();
 while((*ptCmd++)!='\0')
     if((*ptCmd)=='\\')(*ptCmd='_');
 char subKey[MAX_PATH]; //путь к файлу не больше MAX_PATH
 strcpy(subKey,"Console\\\\");
 strncat(subKey,pCmd+0x01,(strlen(pCmd)-2) );// cmdLine возвращает строку в кавычках и пробелом в конце
...
 DWORD lpdwDk=REG_CREATED_NEW_KEY;
 RegCreateKeyEx(HKEY_CURRENT_USER,subKey,0,NULL,0,KEY_ALL_ACCESS,NULL,&pKey,&lpdwDk);
 RegSetValueEx(pKey,"WindowPosition",0,REG_DWORD,(LPBYTE)&dwWPos,sizeof(DWORD));
 RegCloseKey(pKey);
...
 AllocConsole();
...


В 9x-винь, дела обстоят несколько иначе. Настройки храняться в .pif файлах.
PM MAIL   Вверх
GremlinProg
Дата 17.4.2007, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



А смысл, создавать окно консоли, когда это окно показывать не планируется?
Цитата(-Kp0T- @  17.4.2007,  02:21 Найти цитируемый пост)
Создать консоль с GUI программы и установить вывод на stdout можно и так...

Видимо, все таки, не хочешь разбираться.
Пайп - это не консоль, в обычном понимании, ресурсы GUI на пайп не выделяются(ни какого окна с пайпом не идет). Это полностью скрытая диалоговая система, совершенно корректно эмулирующая консольный ввод-вывод. Например: можно написать несколько консольных простых программ и одну - целевую, которая, по мере надобности, будет запускать каждую из них. Сами программы будут работать, даже не подозревая, что у них нет консоли. Так, например работает отладчик Visual Studio: если прикрепить Post-Build или Pre-Link события, в которых запускать консольные програмы, то весь вывод от них будет идти в окно Output среды, естественно, ни какого консольного окна создано не будет.

Основной смысл в том, что у пайпа нет издержек на манипуляции с самим окном консоли, т.е. не будет производиться лишних операций в момент отправки-приема текста на сам ввод-вывод в GUI-окно (black-screen), потому что все данные пишутся непосредственно из/в приемные-отправные буфера.

Это становится весомым, когда пакет полностью разработан на консольных подпрограммах типа 1С или Xilinx ISE Project Navigator.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
-Kp0T-
Дата 17.4.2007, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



 2GremlinProg : Респект 

Относительно разобрался, тру!.
Испытал на любимом cmd.exe 
К примеру ввод через пайп "far.exe\n" приводит к тому что выпадает окно FAR-a из ниоткуда. Или старая добрая досовская прога с псевдографикой выпадает в окне cmd.exe (окно видать, если все-таки процесс с SW_SHOW).

Как получить отрисовку FAR-a или DOS-appl ( command.exe )? - Пока не понял, разбираюсь...
PM MAIL   Вверх
-Kp0T-
Дата 20.4.2007, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Проблема решена.
На случай если кто то столкнеться с проблемой, привожу метод решения.

Вся суть в перезапуске приложения с помощью CreateProcess()  (можно и по-другому, к примеру с помошью ShellExecute() ) с установкой флагов STARTUPINFO структуры  si.wShowWindow=SW_HIDE и si.dwFlags |=STARTF_USESHOWWINDOW

Для ясности приведу код программы testConsole:
Код

...
STARTUPINFO si
    si.cb=sizeof(si);
    si.cbReserved2 =0;
    si.lpDesktop =NULL;
    si.lpTitle =&TEXT("Hide_Console_Example_By_-Kp0T-");
    si.dwX = STARTF_USEPOSITION;
    si.dwY = STARTF_USEPOSITION;
    si.dwXSize = STARTF_USEPOSITION;
    si.dwYSize = STARTF_USEPOSITION;
    si.dwXCountChars = STARTF_USECOUNTCHARS;
    si.dwYCountChars = STARTF_USECOUNTCHARS;
    si.dwFillAttribute = STARTF_USEFILLATTRIBUTE;
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.lpReserved =NULL;
    si.wShowWindow = SW_HIDE;
    si.lpReserved2 =NULL;

    PROCESS_INFORMATION pi;

    HANDLE hMutex=CreateMutex(NULL,TRUE,"MY_MUTEX");
    DWORD err=GetLastError();
    if(err!=ERROR_ALREADY_EXISTS)
    {
        if(CreateProcess(NULL,"testConsole.exe",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)==0)
        MessageBox(0,"Err CreaProcess","err",0);
        Sleep(500); /*Задержка перед выходом нужна только чтобы Mutex не успел развалиться, 
иначе упадем в рекурсивный перезапуск программы. Корректнее дождаться старта второй копии 
этого же процесса. Упрощенный вариант aka "easy way" */

        ExitProcess(0);
    }
    else if(err==ERROR_ALREADY_EXISTS)
    {
        SetConsoleTitle("OnlyForFindHWND");
        HWND hwCons=FindWindow(NULL,"OnlyForFindHWND");
        FreeConsole();//На всякий случай...
        if(!AllocConsole())return false; //Наша цель - скрытая консоль
        int hCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
        *stdout = *(::_fdopen(hCrt, "w"));
        ::setvbuf(stdout, NULL, _IONBF, 0);
        *stderr = *(::_fdopen(hCrt, "w"));
        ::setvbuf(stderr, NULL, _IONBF, 0);
        HANDLE hCons=GetStdHandle(STD_OUTPUT_HANDLE);
    }
    else
    {
        MessageBox(0,"CreateMutex Function Fail","Еrror",0);
    }
...


Это вся суть. При этом мы получаем и HWND и HANDLE с базовыми возможностями. (В вариант с пайпами неудасться по HANDLE прямо записать на консоль посредством WriteConsole().., да и вообще, еще много чего нельзя...:-)
Я так полагаю что http://cygwin.com/ml/cygwin/2006-05/msg00471.html делает то же самое только без перезапуска приложения. 
P.S. Понимаю, что можно было вместо строк 34-35 использовать GetConsoleWindow(), но я старался сохранить совместимость с 98/NT
Тему можно закрывать

Это сообщение отредактировал(а) -Kp0T- - 20.4.2007, 10:27
PM MAIL   Вверх
GremlinProg
Дата 20.4.2007, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



STARTF_xxx - это флаги только для члена dwFlags, поэтому si.dwX = STARTF_USEPOSITION и т.п. - лишнее. А вобщем, молодец, +1!


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

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


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

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


 




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


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

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