Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.07.24;
Скачать: CL | DM;

Вниз

реально ли в рантайме поменять classname формы или я делаю не так   Найти похожие ветки 

 
Jan   (2011-04-06 14:43) [0]

в общем делаю редактор для специального формата. есть задача - запретить запуск второй копии приложения той же версии. понятно, что ищем через findwindow и если находим то программу не запускаем, а активируем предыдущее приложение, но менять для каждой версии classname руками, имхо, бред. вот и возникла злая мысль в рантайме менять classname на уникальный, зависящий от версии приложения, что бы я мог его корректно искать через findwindow (через кэпшн не подходит - он меняется)


 
Ega23 ©   (2011-04-06 14:45) [1]


> понятно, что ищем через findwindow


Вообще-то умные люди ставят мьютекс, а не занимаются извратами с изменением class-name


 
TUser ©   (2011-04-06 14:46) [2]

Посылать найденному окну сообщение, и пусть оно возвращает номер версии, не?


 
Jan   (2011-04-06 14:47) [3]

Мютекс ничего не решит, искать запущенное приложение нужной версии все-равно нужно будет


 
Kerk ©   (2011-04-06 14:48) [4]

http://forum.chertenok.ru/TStringList_i_TThread-t8280-v2


 
Jan   (2011-04-06 14:48) [5]

TUser, можно, но как-то кривовато, если честно:)


 
Kerk ©   (2011-04-06 14:48) [6]


> Jan   (06.04.11 14:47) [3]
>
> Мютекс ничего не решит, искать запущенное приложение нужной
> версии все-равно нужно будет

А для чего ты его ищешь? Нужно передать какие-то данные?


 
asail ©   (2011-04-06 14:49) [7]


> понятно, что ищем через findwindow и если находим то программу
> не запускаем

Нифига не понятно! Так делать не стоит... Лучше посмотри на Mutex.


 
Jan   (2011-04-06 14:50) [8]

Kerk, спасибо, это знаю. Вопрос не только в запрете


 
Ega23 ©   (2011-04-06 14:52) [9]


> Мютекс ничего не решит, искать запущенное приложение нужной
> версии все-равно нужно будет


Мьютекс решит проблему повторного запуска приложения. А вот если он установлен - ищи свой className и активизируй его. Только className у тебя один будет.


 
Jan   (2011-04-06 14:56) [10]

> А для чего ты его ищешь? Нужно передать какие-то данные?
ага. файлы связаны ассоциацией с программой. то бишь передаются через параметры коммандой строки. программа запускается я смотрю - не запущено ли мое приложение уже (это уже есть, сделал через Атом - там в тексте уникальное имя с номером версии). если определяю, что запущено, ищу свое приложение той же версии (тут пока не знаю как красиво сделать), далее ему передаю то что было в параметрах коммандной строки у текущего запущенного приложения (пока думаю как лучше передать), закрываю и активирую найденной окно. ну лучше всего обьяснить на примере текстовых редакторов - когда вы два раза запускаете разные файлы они открываются в одном приложении. но у меня еще момент - должны открываться в одном приложении одной версии


 
Германн ©   (2011-04-06 14:57) [11]


> Jan   (06.04.11 14:47) [3]
>
> Мютекс ничего не решит, искать запущенное приложение нужной
> версии все-равно нужно будет
>

А кто мешает записать номер версии в имя мьютекса?


 
Jan   (2011-04-06 14:58) [12]

> Мьютекс решит проблему повторного запуска приложения
это уже решил:)
>А вот если он установлен - ищи свой className и активизируй его. Только
>className у тебя один будет
вооот!:) как сделать класс нэйм уникальным для каждой версии? руками все время менять - изврат


 
Ega23 ©   (2011-04-06 15:00) [13]


> вооот!:) как сделать класс нэйм уникальным для каждой версии?
>  руками все время менять - изврат

Зачем Class Name менять? Меняй мьютекс


 
Kerk ©   (2011-04-06 15:01) [14]


> Jan   (06.04.11 14:56) [10]

Так и думал :)
Можно попробовать использовать TEvent, а данные передавать через memory-mapped file. И первому и второму можно уникальное имя задать, привязанное к версии, если это так важно.


 
Jan   (2011-04-06 15:05) [15]

>Зачем Class Name менять? Меняй мьютекс
если запущенно два приложения разных версий, то нужно найти именно определенной версии. так задача стоит :-/ поэтому через класснейм искать не получится, а через кэпшн окна тоже - он меняется. TUser посоветовал опрашивать номер версии через сообщение - может так и сделаю. но кривовато как-то. ребят, подскажите, а можно ли найти перебрать все окна с нужным класснеймом и по хенду окна найти где лежит exe? тогда я через GetFileVersionInfoSize, GetFileVersionInfo, VerQueryValue найду версию сразу в exe? Или бред?:)


 
Jan   (2011-04-06 15:06) [16]

Kerk, спасибо


 
Kerk ©   (2011-04-06 15:09) [17]

Понадобится отдельный поток, который будет ждать Event. Когда приложение запускается повторно и видит, что оно является дубликатом, то все нужное кладется в MMF и устанавливается Event, который принимается первым приложением и обрабатывается. Как-то так оно мне видится.


 
Jan   (2011-04-06 15:17) [18]

Kerk, точно, отличная мысль. Спасибо


 
Jan   (2011-04-06 15:24) [19]

"Когда приложение запускается повторно и видит, что оно является дубликатом"
хотя тут момент. если приложение ненормально, через диспетчер и не вызывался ReleaseMutex (или освобождение Атома, как у меня), то могут быть нюансы. Ну ладно, буду смотреть:)


 
Jan   (2011-04-06 15:25) [20]

"если приложение ненормально"
хотел написать завершилось ненормально


 
oxffff ©   (2011-04-06 15:30) [21]

TForm5 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 procedure CreateParams(var Params: TCreateParams); override;
 end;

var
 Form5: TForm5;

implementation

{$R *.dfm}

procedure TForm5.Button1Click(Sender: TObject);
var buf:array[1..100] of char;
begin
GetClassName(Handle,@buf,100);
showmessage(buf);
end;

procedure TForm5.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName:="В рот Вам ноги";
end;


 
Jan   (2011-04-06 15:36) [22]

oxffff, спасибо!


 
Eraser ©   (2011-04-06 15:36) [23]

> [0] Jan   (06.04.11 14:43)

а если вторая копия в другой терминальной сессии?


 
sniknik ©   (2011-04-06 15:39) [24]

> сделал через Атом - там в тексте уникальное имя с номером версии
не особо хорошо... мьютекс сам отвалится если приложение глюкнет/повиснет/просто снимут через таск менеджер, в общем он привязан к процессу, а атом нет.
т.е. в нестандартной ситуации запуск может блокироваться "пустым местом".


 
Jan   (2011-04-06 15:50) [25]

> не особо хорошо... мьютекс сам отвалится если приложение
> глюкнет/повиснет/просто снимут через таск менеджер
знаю. но чем не нравятся мютексы, они не сразу освобождаются, а делать на старте что-то вроде
if WaitForSingleObject(Mutex,10000) = WAIT_TIMEOUT <...>
не хотелось бы. ну в общем тут уже кучу вариантов предложили :) буду пробовать. отличный сайт!


 
Игорь Шевченко ©   (2011-04-06 15:54) [26]


>  но чем не нравятся мютексы, они не сразу освобождаются


??????????????????


 
Jan   (2011-04-06 16:00) [27]

Игорь Шевченко, я имею ввиду, что если повисло приложение


 
asail ©   (2011-04-06 16:14) [28]


> Jan   (06.04.11 16:00) [27]
> Игорь Шевченко, я имею ввиду, что если повисло приложение

Повисшее приложение <> закрытому приложению...
Т.е. если повисло, то мьютекс не даст запустить вторую копию, что пральна весьма...
А вот, ежели убить процесс, то мьютекс освободится, и можно запустить заного. В чем проблема?


 
asail ©   (2011-04-06 16:15) [29]


> asail ©   (06.04.11 16:14) [28]

"Заного", читать как заново...


 
Ega23 ©   (2011-04-06 16:31) [30]

что-то мне напоминает
http://www.gunsmoker.ru/2008/10/x-y-z.html


 
sniknik ©   (2011-04-06 16:37) [31]

> они не сразу освобождаются
как раз наоборот, это если атом явно не освободить то он будет висеть до перезагрузки, что ни делай.
т.что твоя нелюбовь не по адресу.


 
Jan   (2011-04-08 14:07) [32]

> asail
>Т.е. если повисло, то мьютекс не даст запустить вторую копию, что пральна весьма
тут правильно будет опросить приложение и если видим, что висит, то запускать вторую копию
несмотря на мютекс
> Ega23
> что-то мне напоминает
искренне за вас рад:)

Kerk, спасибо за наводку!:) возник такой вот шаблон

в dpr

program test;

uses
 checkprogramrun in "checkprogrammrun.pas" // модуль проверки первым в списке, что бы не ждать инициализации остальных модулей
...

модуль

unit checkprogramrun;

interface

var
 WorkExist: boolean;
 BusyExist: boolean;
 SignaledExist: boolean;
 ProgramExist: boolean;
 MutexProgramRun: THandle;
 EventWork: THandle;
 EventBusy: THandle;
 EventSignaled: THandle;
 Timeout: integer;

implementation

uses Windows, xconst;

initialization
 // проверка запущенной программы
 MutexProgramRun := CreateMutex(nil, False, _EventClassName+_EventProgramRun);
 if MutexProgramRun = 0 then halt;
 ProgramExist := GetLastError = ERROR_ALREADY_EXISTS;

 EventSignaled := CreateEvent(nil, True, False, _EventClassName+_EventSignaled); // состояние сбрасываем руками
 if EventSignaled = 0 then halt;
 SignaledExist := GetLastError = ERROR_ALREADY_EXISTS;

 EventBusy := CreateEvent(nil, True, False, _EventClassName+_EventBusy);
 if EventBusy = 0 then halt;
 BusyExist := GetLastError = ERROR_ALREADY_EXISTS;

 EventWork := CreateEvent(nil, True, False, _EventClassName+_EventWork);
 if EventWork = 0 then halt;
 WorkExist := GetLastError = ERROR_ALREADY_EXISTS;

 Timeout := 0;
 if ProgramExist then
 begin
   // если запущенная программа без сигнального мютекса, то сбой
   if not(SignaledExist) or not(BusyExist) or not(WorkExist) then halt;
   // установим сигнальный эвент
   SetEvent(EventSignaled);
   // ждем 10 секунд пока основная программа не сбросит эвент
   while Timeout < 1000 do
   begin
     if WaitForSingleObject(EventSignaled,0) = WAIT_TIMEOUT then break; // основная программа отвечает
     Sleep(10);
     Inc(Timeout);
   end;
   if Timeout < 1000 then // если нет таймаута передаем данные в программу, иначе запуск в аварийном режиме
   begin
     Timeout := 0;
     while Timeout < 1000 do
     begin
       if WaitForSingleObject(EventBusy,0) = WAIT_TIMEOUT then // основная программа не обрабатывает данные
       begin
        SetEvent(EventBusy); // начали обработку
        break;
       end;
       Sleep(10);
       Inc(Timeout);
     end;
     if Timeout < 1000 then
     begin
       // работа с mmf
       //...
       SetEvent(EventWork); // запускаем обработку
       halt;
     end;
   end;
 end;

finalization
 if MutexProgramRun <> 0 then CloseHandle(MutexProgramRun);
 if EventSignaled <> 0 then CloseHandle(EventSignaled);
 if EventBusy <> 0 then CloseHandle(EventBusy);
 if EventWork <> 0 then CloseHandle(EventWork);
end.

главная форма

const
wm_ParamStr = WM_APP+2;
wm_AfterShow = WM_APP+1;

type
 TfmMain = class(TForm)
 private
   procedure WmParamStr(var Msg: TMessage); message wm_ParamStr;
   procedure WmAfterShow(var Msg: TMessage); message wm_AfterShow;
...

type
 TSyncThread = class(TThread)
 private
   FHandle: THandle;
 protected
   procedure Execute; override;
 public
   constructor Create(CreateSuspended: boolean; handle: THandle);
 end;

...

constructor TSyncThread.Create(CreateSuspended: boolean; handle: THandle);
begin
 inherited Create(CreateSuspended);
 FHandle := handle;
end;

procedure TSyncThread.Execute;
begin
 while true do
 begin
   if WaitForSingleObject(EventSignaled,0) = WAIT_OBJECT_0 then // кто-то опрашивает программу
     ResetEvent(EventSignaled); // ответил
   if WaitForSingleObject(EventWork,0) = WAIT_OBJECT_0 then // запускаем обработку
   begin
     ResetEvent(EventWork);
     PostMessage(FHandle, wm_ParamStr, 0, 0); // именно пост, чтобы не ждать обработки
   end;
   Sleep(1);
end;
end;

procedure TfmMain.FormCreate(Sender: TObject);
begin
 // именно пост, что бы стал в конец стека сообщений
 PostMessage(Handle, wm_AfterShow, 0, 0);
end;

procedure TfmMain.WmAfterShow(var Msg: TMessage);
var SyncThread: TSyncThread;
begin
 inherited;
 SyncThread := TSyncThread.Create(True,Handle);
 SyncThread.FreeOnTerminate := True;
 SyncThread.Priority := tpLower;
 SyncThread.Resume;
end;

procedure TfmMain.WmParamStr(var Msg: TMessage);
begin
 // работа с mmf
 //...
 Application.Restore;
 Application.BringToFront;
 ResetEvent(EventBusy); // закончили обработку
end;



Страницы: 1 вся ветка

Текущий архив: 2011.07.24;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.007 c
2-1303453604
alex_old
2011-04-22 10:26
2011.07.24
Как прописать в Delphi 7 заголовочные файлы


15-1302248344
Dennis I. Komarov
2011-04-08 11:39
2011.07.24
Для настроения - пятница


15-1302270628
Galera
2011-04-08 17:50
2011.07.24
Медленный поиск у RxMemoryData


2-1302772191
Учусь
2011-04-14 13:09
2011.07.24
Inno Setup и папки юзера


15-1302368658
Димка На
2011-04-09 21:04
2011.07.24
ИЕ 9