Форум: "Прочее";
Текущий архив: 2011.07.24;
Скачать: [xml.tar.bz2];
Внизреально ли в рантайме поменять 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;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.004 c