Форум » GUI » Как предотвратить второй запуск программы в МиниГуи ? » Ответить

Как предотвратить второй запуск программы в МиниГуи ?

Andrey: Делаю программу на МиниГуи, типа меню запуска других программ. Хочу вызывать свои доп. ЕХЕ-ники (терминалки на хХарборе) из главного меню программы на МиниГуи. Вызовом ShellExecute(). Как сделать, чтоб повторно нельзя было запускать уже запущенную программу ? Я пока знаю 2 варианте: 1) Можно было бы писать файл-семафора что запущена программа, а при завершении терминалки удалять этот файл. Но это как-то не солидно... И при случайном сбое, нельзя будет запустить программу. 2) Поискать в памяти запущенный процесс (окно с именем). Но это ТОРМОЗА - я уже наталкивался на эти грабли. По России уже наблюдал 3 случая "тормозов" при проверке повторного запуска программы (я писал об этом в другой ветке, здесь на форуме). Какие еще варианты можно использовать ?

Ответов - 27, стр: 1 2 All

petr707: Вариант с монопольно открытым файлом - достаточно прост и надежен. При запуске - создаете в рабочей папке, где запускаете приложение - дополнительный файл -вроде [имя exe].run Каждая следующая попытка запуска приложения "имя exe" предварительно проверяет - отсутствие файла [имя exe].run или возможность его удаления. Если файл есть и его не удалось удалить - нельзя делать запуск.

Andrey: petr707 пишет: Если файл есть и его не удалось удалить - нельзя делать запуск. Это не факт. Натыкался на случаи (и не раз) сбоя на ХР, при вылете программы по ошибке, файл-семафора остается блокированным и запустить заново терминалку НЕЛЬЗЯ ! Помогает только перезагрузка компа ! ! ! Но это же не дело...

petr707: На практике - непонятую (непонятную) блокировку файла наблюдал только на компах, где установлен Google Desktop или работает Window Search на NTFS, который проводит индексацию файлов в фоновом режиме. При конфигурации(инсталляции) прикладного ПО - снимите в свойствах папки, где exe, "Индексировать папку для быстрого поиска"


fil: можно через FindWindow(), можно чнрез TaskBar

Andrey: petr707 пишет: При конфигурации(инсталляции) прикладного ПО - снимите в свойствах папки, где exe, "Индексировать папку для быстрого поиска" Не подключены компы к Инету. И службу индексации - всегда выключаю. Все равно эпизодически были такие ошибки. fil пишет: можно через FindWindow(), можно чнрез TaskBar А чуть подробней можно ? Как код будет выглядеть ?

fil: FindWindow(Заголовок главного окна приложения) - на форуме мелькало. Если нет в Минигуи, API прицепи TaskBar - Наверняка в Минигуи есть возможность получить список задач

PSP: Существует механизм мьютексов. http://ru.wikipedia.org/wiki/%CC%FC%FE%F2%E5%EA%F1 Харбор умеет с ними работать.

petr707: Мьютекс отработает при запуске из одной операционной среды - локальный комп или терминал-сервер. При выполнении задачи в одной сетевой папке - но с разных компов, с мьютексом не получится, isn'it ? Неплохо бы уточнить, что такое "повторный запуск". Миллионы( а может и больше) юзеров "повторно" запускают IE ( не реклама)

Andrey: petr707 пишет: Неплохо бы уточнить, что такое "повторный запуск". Подразумевалось локальный комп (папка программы) или терминал-сервер.

Andrey: PSP пишет: Существует механизм мьютексов. http://ru.wikipedia.org/wiki/%CC%FC%FE%F2%E5%EA%F1 Харбор умеет с ними работать. А примеры есть ? Кто нибудь работал с этим на Харборе ?

ММК: Andrey пишет: А примеры есть ? Кто нибудь работал с этим на Харборе ? Ну например можно сделать что-то типа : if IsExeRunning( cFileName( "mors" ) ) MsgStop( "Программа уже работает ! ", "Внимание ..." ) return( NIL ) endif Вместо возврата можно активировать окно. А сама IsExeRunning может быть , к примеру ,такой- #ifdef __FLAT__ HB_FUNC( ISEXERUNNING ) // ( cExeNameCaseSensitive ) --> lResult { HANDLE hMutex = CreateMutex( NULL, TRUE, ( LPTSTR ) hb_parc( 1 ) ); hb_retl( GetLastError() == ERROR_ALREADY_EXISTS ); ReleaseMutex( hMutex ); } #endif Это FWH :)

gfilatov2002: ММК пишет: Ну например можно сделать что-то типа ... Вместо возврата можно активировать окно. Andrey Посмотри штатный пример из поставки Минигуи: [pre]/* * MINIGUI - Harbour Win32 GUI library Demo * * Copyright 2002-05 Roberto Lopez <harbourminigui@gmail.com> * http://harbourminigui.googlepages.com/ * * Copyright 2006 Grigory Filatov <gfilatov@inbox.ru> */ #include "minigui.ch" #define APP_TITLE 'Main Window' #define MsgAlert( c ) MsgEXCLAMATION( c, "Warning", , .f. ) FUNCTION Main() Local hWnd IF IsExeRunning( cFileNoPath( HB_ArgV( 0 ) ) ) MsgAlert( "The " + APP_TITLE + " is already running!" ) hWnd := FindWindow( APP_TITLE ) IF hWnd > 0 IF IsIconic( hWnd ) Restore( hWnd ) ELSE SetForeGroundWindow( hWnd ) ENDIF ELSE MsgStop( "Cannot find application window!", "Error", , .f. ) ENDIF ELSE DEFINE WINDOW Form_Main ; AT 0,0 ; WIDTH 640 HEIGHT 480 ; TITLE APP_TITLE ; MAIN END WINDOW CENTER WINDOW Form_Main ACTIVATE WINDOW Form_Main ENDIF RETURN NIL #pragma BEGINDUMP #define HB_OS_WIN_USED #define _WIN32_WINNT 0x0400 #include <windows.h> #include "hbapi.h" #include "hbapiitm.h" HB_FUNC( ISICONIC ) { hb_retl( IsIconic( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC ( FINDWINDOW ) { hb_retnl( ( LONG ) FindWindow( 0, hb_parc( 1 ) ) ); } #pragma ENDDUMP[/pre] У меня работает нормально

SergKis: Andrey пишет: Делаю программу на МиниГуи, типа меню запуска других программ. Хочу вызывать свои доп. ЕХЕ-ники (терминалки на хХарборе) из главного меню программы на МиниГуи. Вот и у тебя появилось много ЕХЕ-ников, а значит и окон. Значит перед тобой встанет задача управлять ими (из терминалки на хХарборе воздействовать на программу МиниГуи и наоборот, переключать фокус окон и т.д. и т.п.). Меня выручил AutoIt3 скриптовый язык (можно получать ЕХЕ). В нем много отлаженных функций по управлению поведением окон, нажатию на пункты меню, кнопки и др. полезных штук. Прост в использовании. Есть русский help. Это не реклама. Сам наступал на такие грабли. Если интересно могу кинуть русский help для начала.

Andrey: gfilatov2002 пишет: Посмотри штатный пример из поставки Минигуи: Да он и у меня работает нормально. Вопрос в другом - как сделать в программе на МиниГуи что бы внешняя программа (терминалка на хХарборе) запускалась ТОЛЬКО ОДИН раз ?

petr707: То есть непонятно, что для каждой запускаемой внешней проги нужно сделать свой мьютекс и потом проверять его присутствие? Функция ISEXERUNNING позволяет задавать параметр [имя мьютекса=имя проги(внешний exe) + еще что угодно] и использовать эту функцию не только для проверки повторного запуска программы на Минигуи, а для проверки запуска других программ, и вообще - для любого события, к которому привяжете и оставите в системе мьютекс. Например , запускает свою прогу , запускаете некий Ваш отчет и если получите результат = 4, то создаете мьютекс с именем - Was_report_4 далее - пока не выключите комп, можете проверять следующий факт - был ли сегодня на этом компе от последнего включения создан отчет с результатом 4 ( а реально - был ли создан мьютекс) (хотя проверку именно такого событие можно и проще реализовать) При обнаружении мьютекса запущенного внешнего exe - не обязательно искать окно приложения и переключать на него фокус, достаточно сообщить юзеру о невозможности повторного запуска внешнего exe

SergKis: Вот примеры на AutoIt: ; AutoIt3 Примеры: ;--------------------------------------- 1 ; Проверка наличия указанного процесса и запуск если нет #NoTrayIcon If ProcessExists("notepad.exe") Then MsgBox(0, "Привет !", "Notepad is running.") Else Run("Notepad.exe") EndIf ;--------------------------------------- 2 ; Проверка наличия указанного окна по части заголовка и запуск если нет #NoTrayIcon If WinExists("Untitled -") Then MsgBox(0, "Привет !", "Notepad is running.") Else Run("Notepad.exe") EndIf ;--------------------------------------- 3 ; Нажать пункт меню окна notepad #NoTrayIcon If WinExists("Untitled -") Then WinMenuSelectItem("Untitled - ", "", "&File", "Page Set&up..." ) EndIf ;--------------------------------------- 4 ; Активизировать окно, то есть отобразить его на переднем плане экрана #NoTrayIcon If WinExists("Untitled -") Then WinActivate("Untitled - Notepad", "") EndIf ;----------------------------------------- Из программы на МиниГуи запускаешь AutoIt3.exe <имя скрипта>

Andrey: Спасибо SergKis за примеры. Но честное слово не хочется связываться с внешними программами. Если я сопровождал бы одну свою систему, то можно было бы. gfilatov2002 пишет: Посмотри штатный пример из поставки Минигуи: Посмотрел. Я на базе нкго для хХарбора делал проверку запуска второй копии программы. Здесь на форуме писал об этом. Вопрос по функциям этого примера: 1) Функция cFileNoPath() - понятно что делает, а где описание по ней ? В каком руководстве искать такие функции ? 2) Функция Restore() - аналогично ? 3) Функция SetForeGroundWindow() - аналогично ? 4) FindWindow() - понятно что делает. Может в ней описание из 2-х строчек дать ? 5) IsIconic() - не понял что эта функция делает ?

gfilatov2002: Andrey пишет: Вопрос по функциям этого примера 1) главное руководство для программиста - это исходники библиотеки (см. файл h_controlmisc.prg) 2) см. файл c_windows.c 3) Это харбор-переходник для стандартной winapi-функции (см. MSDN) - выводит заданное окно на передний план 4) аналогично п.4 5) аналогично п.4 - эта функция определяет, минимизировано ли заданное окно (см. MSDN снова) Понимаю, что это сложно (все знать ), но недаром этот пример находится в папке Advanced

Andrey: gfilatov2002 пишет: Понимаю, что это сложно (все знать ), но недаром этот пример находится в папке Advanced Спасибо большое за разъяснения ! Сделай пожалуйста к этому примеру комментарии в этих функциях... Очень было бы полезно и для других тоже. Типа: харбор-переходник для стандартной winapi-функции (см. MSDN) - выводит заданное окно на передний план !

gfilatov2002: Andrey пишет: Сделай пожалуйста к этому примеру комментарии в этих функциях По типу такого Функция SetForegroundWindow переводит поток, который создал определяемое окно в приоритетный режим и активизирует окно. Ввод с клавиатуры направлен в окно, а различные визуальные ориентиры изменяются для пользователя. Синтаксис BOOL SetForegroundWindow ( HWND hWnd // дескриптор окна, которое переводится в приоритетный режим ); Параметры hWnd Идентифицирует окно, которое должно быть активизировано и переведено в приоритетный режим. Возвращаемые значения Если функция завершилась успешно, возвращается значение отличное от нуля. Если функция потерпела неудачу, возвращаемое значение - ноль. Чтобы получить дополнительную информацию об ошибке, вызовите GetLastError. Замечания Приоритетное окно - окно наверху Z-последовательности. Это - окно, с которым пользователь работает. В среде приоритетной многозадачности, Вы должны вообще дать возможность управления пользователю, окно которого является приоритетным окном. Однако прикладная программа может вызывать SetForegroundWindow, если требуется перевести себя в активный режим, чтобы отобразить критическую ошибку или информацию, которая требует непосредственного внимания пользователя. Хороший пример - это отладчик, когда он обнаруживает контрольную точку останова программы. Система назначает немного более высокий приоритет потоку, который создал приоритетное окно, чем она делает это по отношению к другим потокам. Но тогда скоро потребуется повторить весь MSDN



полная версия страницы