Форум: "Система";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];
ВнизOneInstance, но не простой... Найти похожие ветки
← →
LordOfSilence (2002-11-18 13:56) [0]Коллеги, подскажите, пожалуйста, а то что-то ничего
путного в голову не идет.
Описываю ситуацию:
В свою время мой шеф поставил мне задачу по написанию
небольшой проги-утилитки. Если кому интересно - сбор
данных с COM-порта и ведение логов. Сейчас эта прога
мирно сидит в систрее нашего сервера и тихонько ведет
свою работу в фоновом режиме. По сути задачи посчитал
необходимым реализовать OneInstance. Сделал это через
Mutex. Если будет необходимо - выложу кусок исходного
кода. До этого момента все было в порядке и проблем не
возникало. Но!...
Мой шеф - весьма продвинутый малый и любит лезть на
сервер через терминальный доступ, для чего использует
Citrix. Так вот, когда он коннектится к серверу, то
моя программа стартует (в его терминальной сессии),
так как ярлык прописан в папке автозагрузки, и...
НЕ НАХОДИТ первый экземпляр, который уже сидит в систрее,
при этом ругается на то, что COM-порт уже занят, после
чего главное окно приложения пропадает, но само приложение
остается висеть в списке процессов сервера, в чем мы
убедились, просмотрев список этих процессов на самом сервере.
То есть, как я понимаю, в этом случае запускаемые задачи разносятся по разным "пространствам" и Mutex не ловится.
Как посоветуете решать эту нестыковку? Проверять при старте
состояние COM-порта (хоть убей, но почему-то этот способ
мне не кажется "изящным") или тупо создавать некий внешний
файл "блокировки", который будет создаваться при старте
первого экземпляра и уничтожаться соответственно только
при его завершении, а во втором проверять его существование?
А может быть существует другой оригинальный способ,
о котором я и не подозреваю?
Помогите, пожалуйста, разрулить эту ситуацию, а то у меня
сегодня "синий понедельник"...
← →
sndanil (2002-11-18 14:26) [1]а про сервис ты не думал?
← →
han_malign (2002-11-18 14:29) [2]Mutex - именованный?
← →
LordOfSilence (2002-11-18 14:33) [3]Про сервис думал. Но это переписывать надо.
Не все, конечно, но пальчикам придется попорхать :)
Хотел отделаться "легким испугом".
program ComLog;
uses
Forms,
Windows,
SysUtils,
main in "main.pas" {frmMain},
setup in "setup.pas" {frmSetup},
engine in "engine.pas";
var
Mutex : THandle;
IsPrevInst : boolean;
PrevInst : hWnd;
{$R *.res}
begin
Mutex := CreateMutex( nil, False, "ComLogMutex" );
if Mutex <> 0 then begin
if GetLastError = ERROR_ALREADY_EXISTS then begin
IsPrevInst := True;
CloseHandle( Mutex );
end
else IsPrevInst := False;
end
else IsPrevInst := False;
if not IsPrevInst then begin
Application.Initialize;
Application.Title := "Утилита ведения логов COM-порта";
Application.CreateForm(TfrmMain, frmMain);
Application.CreateForm(TfrmSetup, frmSetup);
Application.Run;
end
else begin
PrevInst := FindWindow( ClassName, AppTitle );
if PrevInst <> 0 then PostMessage( PrevInst, UM_APPRESTORE, 0, 0 )
end
end.
← →
han_malign (2002-11-18 14:46) [4]If lpName matches the name of an existing event, semaphore, waitable timer, job, or file-mapping object, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space.
Ни где то же имя не иcпользуется?
← →
LordOfSilence (2002-11-18 14:56) [5]To han_malign © (18.11.02 14:46)
Извините, что-то не догоняю Вашу мысль.
Нельзя ли по-подробнее ее раскрыть.
Говорю же - туповатый сегодня какой-то...
← →
Ketmar (2002-11-18 15:08) [6]да. только что проверил: похоже, что для разных логонов разные NameSpaces. по крайней мере, мютексовые. отлично оба раза сказала, что все оки-доки, и создала мьютексы. %-(
лень проверять, но: а как с глобальными атомами (это не дело, однако - а вдруг получится? хотя с атомами глюки другого рода: ваша программа может помереть, забыв убить атом, и он до перезагрузки останется в системе. сами понимаете, чем это чревато).
еще можно проверить pipes и mapped files. хоть что-то да должно заработать! %-) я полагаю, что и пайпы, и named files будут. однако, честно говоря, я то же самое и про мьютексы думал %-( %-)
Satanas Nobiscum! 18-Nov-XXXVII A.S.
← →
Игорь Шевченко (2002-11-18 15:12) [7]Файл - лучше всего. Создать при старте и удалять при завершении. Mutex"ы они могут быть свои для каждого терминального сеанса (не уверен).
← →
han_malign (2002-11-18 15:16) [8]PrevInst := FindWindow( ClassName, AppTitle );
if PrevInst <> 0 then PostMessage( PrevInst, UM_APPRESTORE, 0, 0 )
уже есть проверка, чаще всего так и делается.
← →
LordOfSilence (2002-11-18 15:34) [9]To Ketmar © (18.11.02 15:08)
Да и я как-то всегда полагал, что Mutex"ы понадежнее
атомов будут :)
To Игорь Шевченко © (18.11.02 15:12)
Угу... я уже начинаю склоняться к этой же мысли.
Как говорил Лёлик, "зато дешево и практично" :)
Кстати, только-что шеф озвучил мысль, что сервис
все равно писать придется. Ибо если уже его шеф
(наш финансовый директор) удаленно из дому залезет
на сервер и вдруг его (сервер) "нечаянно" свалит,
то после перезагрузки, блин, сервака надо, чтобы
запись логов стартовала до того, как он полностью
загрузится независимо от того, знает юзер пароль
к сервачине или нет.
Тьфу... Короче, ребята, у меня гемморой на ровном
месте. А все потому, что всяким продвинутым товарищам
руки дома некуда приложить.
To han_malign © (18.11.02 15:16)
Не, все-таки вариант с Mutex"ами как-то понадежнее и
стабильнее, ИМХО. Да и все-равно в моем случае это
не поможет. Как я найду заголовок окна из другой сессии?
← →
Ketmar (2002-11-18 16:02) [10]с файлами та же фигня, что и с атомами - а кто его убьет, ежели программа забыла/не смогла (ну упала, болезная. вместе с виндой %-)?
2han_malign:
FindWindow - криво и потенциально зависабельно (читаем Рихтера).
Satanas Nobiscum! 18-Nov-XXXVII A.S.
← →
LordOfSilence (2002-11-18 16:17) [11]To Ketmar © (18.11.02 16:02)
Полностью согласен, но, с другой стороны, если моя
программа "забыла/не смогла" убить лок-файл, то я,
по крайней мере, могу своему шефу всегда сказать
какой файл надо убивать ручками, чтобы эта дрянь
все же запустилась... :(((
P.S. Видать и вправду, Сатана сегодня со мной :)
← →
LordOfSilence (2002-11-18 16:30) [12]Кстати, только что промелькнула такая идея:
1. При старте создаю файл и открываю его
с экслюзивными правами.
2. При завершении приложения соответственно его убиваю.
3. При старте второго терминального экземпляра
пытаюсь этот файл убить. Если удается - гружусь,
если нет - стало быть первый экземпляр еще жив
вместе с Виндой.
Как полагаете, а?
P.S. Я, наверное, уже задолбал вас всех сегодня
своими заморочками...
← →
Ketmar (2002-11-18 17:03) [13]тоже вариант. а может, все же, попробовать pipes/mmaped files? %-)
Satanas Nobiscum! 18-Nov-XXXVII A.S.
← →
LordOfSilence (2002-11-18 17:11) [14]Может... Надо подумать.
А может лучше начальникам "дать гвоздей"?
А еще лучше самому становиться начальником! :)
← →
Игорь Шевченко (2002-11-19 13:51) [15]Ketmar © (18.11.02 17:03)
А зачем делать сложно, когда можно сделать просто ? :-)
С уважением,
← →
Александр Павлов (2002-11-20 11:20) [16]Вот что по этому поводу думает дюдя Джеффри Рихтер(Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows, Глава 3):
Пространства имен Terminal Server
На машине с Terminal Server существует множество пространств имен для объектов ядра. Объекты, которые должны быть доступны всем клиентам, используют одно глобальное пространство имен. (Такие объекты, как правило, связаны с сервисами, предоставляемыми клиентским программам.) В каждом клиентском сеансе формируется свое пространство имен, чтобы исключить конфликты между несколькими сеансами, в которых запускается одно и то же приложение Ни из какого сеанса нельзя получить доступ к объектам другого сеанса, даже если у их объектов идентичные имена.
Именованные объекты ядра, относящиеся к какому-либо сервису, всегда находятся в глобальном пространстве имен, а аналогичный объект, связанный с приложением, Terminal Server по умолчанию помещает в пространство имен киентского сеанca. Однако и его можно перевести в глобальное пространство имен, поставив перед именем объекта префикс "Global\", как в примере ниже.
HANDLE h = CreateEvenL(NULL, FALSE, FALSE, "Global\\MyName");
Если Вы хотите явно указать, что объект ядра должен находиться в пространстве имен клиентского сеанса, используйте префикс "Local\":
HANDLE h = CreateEvent(NULL, FALSE, FALSE, "Local\\MyName");
Microsoft рассматривает префиксы Global и Local как зарезервированные ключевые слова, которые не должны встречаться в самих именах объектов. К числу таких слов Microsoft относит и Session, хотя на сегодняшний день оно не связано ни с какой функциональностью. Также обратите внимание на две вещи, все эти ключевые слова чувствительны к регистру букв и игнорируются, если компьютер работает без Terminal Server.
← →
LordOfSilence (2002-11-20 11:47) [17]Большое спасибо за пищу для размышлений.
Уже не ожидал, что кто-то еще поднимет эту ветку...
Надо будет поэкспериментировать!
← →
Александр Павлов (2002-11-20 12:32) [18]Как говорят америкосы - you wellcome... :)
← →
LordOfSilence (2002-11-21 12:08) [19]To Александр Павлов © (20.11.02 11:20)
Метод, предложенный Вами оказался действенным!
Простого изменения вышеуказанного вызова создания мьютекса
на следующий оказалось достаточно для решения моей проблемы:
Mutex := CreateMutex( nil, False, "Global\ComLogMutex" );
От лица самого себя выражаю Вам огромную благодарность! :)
← →
paul_shmakov (2002-11-21 17:00) [20]я уже давно предлагал в на странице форума "winapi" и "система" сделать что-то типа "Читайте Рихтера!!! Экономьте нервы и здоровье" и ссылку дать ;)
← →
Antonius (2002-11-21 21:46) [21]А где ссылка то ? :)
← →
paul_shmakov (2002-11-22 13:01) [22]2 Antonius:
Джеффри Рихтер. Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows
электронная версия:
http://www.podgoretsky.com/
Прочее\Языки программирования\Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows
бумажная версия
http://www.books.ru/shop/books/8283
← →
Antonius (2002-11-22 15:43) [23]Вот спасибо!
Страницы: 1 вся ветка
Форум: "Система";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.011 c