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

Вниз

Ограничение числа экземпляров   Найти похожие ветки 

 
TStas ©   (2006-03-20 14:51) [0]

Читал сегодня статью с форума на эту тему, много это обсуждалось. ОДно мне непонятно: чем вариант с инишкой плох. СПециально только что провери - все отлично работает.
Вот файл проекта:
program Project1;

uses
 Forms,
 Unit1 in "Unit1.pas", {Form1}
 IniFiles, SysUtils;
{$R *.res}

var
 ini: TINiFile;
 b: Boolean;
begin

 ini:=TINiFile.Create(ExtractFilePath(Application.ExeName)+"Run.ini");
 B:=Ini.ReadBool("Runned", "Already", false);
 Ini.WriteBool("Runned", "Already", true);
 if b then
   begin
   Ini.Free;
   Halt;
   end;
 Ini.Free;

 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;

end. //В нем -то и чииается инишка
А вот файл формы, в нем инишка ставится на место
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs;

type
 TForm1 = class(TForm)
   procedure FormDestroy(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation
uses IniFiles;
{$R *.dfm}

procedure TForm1.FormDestroy(Sender: TObject);
var
 ini: TIniFile;
begin
ini:=TINiFile.Create(ExtractFilePath(Application.ExeName)+"Run.ini");
Ini.WriteBool("Runned", "Already", false);
Ini.Free;
end;

end.
ВСе работает. МОжет, в каких-то сложных случаях что-то не так?


 
Кашперук Иван   (2006-03-20 15:00) [1]

ну а вдруг вашу ini - шку кто-то решит удалить, другой процесс, или вы сами ненароком.
И файл лишний на винте


 
Плохиш ©   (2006-03-20 15:05) [2]


> МОжет, в каких-то сложных случаях что-то не так?

Программа зависла и её убили через диспетчер задач, свет выключили...


 
TStas ©   (2006-03-20 15:07) [3]

>Плохиш Вот и ответ про сложный случай. Спасибо. Просто в статье прямого ответа тоже нет, написано, что много путей и все с недостатками.


 
Ihor Osov'yak ©   (2006-03-20 23:57) [4]

>  написано, что много путей и все с недостатками.

статьи не читал, искать влом..
но навскидку на ум экспромтом приходит как минимум два варианта решения

1. использование именнованых семафоров, при запуске - попытка овладеть.. Игра на том, что можно указать при создании семафора количество максимально допустимых "овладений"... Подводных камней не вижу, так как при нештатном завершении процесса система все же счетчик семафора уменшит на единицу.

2. Если система Win2K и више - процессы объеденить в задание, для задания назначить квоту на количество процессов.  Вообще-то может ткое понятие как задание существовало и в NT4 - не уверен, а документацию сейчас смотреть влом.


 
ANB ©   (2006-03-21 01:44) [5]

Семафоры, мьютексы, файлы, отображаемые в память, просто тупой FindWindow - способов куча.
ЗЫ. Нашим программистам за такие шутки мы уже все руки поотрывали. Ограничение убрали.


 
Piter ©   (2006-03-21 01:53) [6]

ANB ©   (21.03.06 1:44) [5]
просто тупой FindWindow


а вот здесь нет. Процесс может быть уже запущен, но до функции создания окна дело не дошло, на этом этапе FindWindow ничего не найдет и запустится второй процесс.

Не такая уж и невероятная ситуация, например, на долго инициализирующихся приложениях, при тормозящем компьютере...

Я самолично открывал два окна одного Dial-up соединения :)


 
Джо ©   (2006-03-21 02:11) [7]

> [5] ANB ©   (21.03.06 01:44)
> ЗЫ. Нашим программистам за такие шутки мы уже все руки поотрывали.
> Ограничение убрали.

И как же они без рук теперь пишут? 8()


 
Германн ©   (2006-03-21 02:35) [8]


> Джо ©   (21.03.06 02:11) [7]
>
> > [5] ANB ©   (21.03.06 01:44)
> > ЗЫ. Нашим программистам за такие шутки мы уже все руки
> поотрывали.
> > Ограничение убрали.
>
> И как же они без рук теперь пишут? 8()

Наверно, они уже не пишут! :) Или пишут, но не программы, а "исковые заявки". :-)


> ANB ©   (21.03.06 01:44) [5]
>
>  Ограничение убрали.

А вот с этого места, пожалуйста подробнее. Что "убрали" и по какой причине? :-)


 
ANB ©   (2006-03-21 04:06) [9]


> А вот с этого места, пожалуйста подробнее. Что "убрали"
> и по какой причине? :-)

Да взяли наши программисты и присобачили ограничение, которое не позволяет запускать более одного экземпляра приложения на компе (если точнее, то их даже установить несколько проблематично было). А для тестирования их надо штук 15 запускать. Исправили, когда клиенту понадобилось запускать 2 копии.


 
Leonid Troyanovsky ©   (2006-03-21 08:40) [10]


> Piter ©   (21.03.06 01:53) [6]

> а вот здесь нет. Процесс может быть уже запущен, но до функции
> создания окна дело не дошло, на этом этапе FindWindow ничего
> не найдет и запустится второй процесс.


Именованный объект создают до инициализации приложения,
а закрывают - после его Run (или не закрывают).
Ищут же окно при GetLastError = ERROR_ALREADY_EXISTS.
Остается одна тонкость - объект существует, а окна еще нет.
Тогда, можно повторить все после небольшой паузы.

--
Regards, LVT.


 
Гаврила ©   (2006-03-21 10:21) [11]


>  а вот здесь нет. Процесс может быть уже запущен, но
>до функции
> > создания окна дело не дошло, на этом этапе
>FindWindow ничего
> > не найдет и запустится второй процесс.

Аналогично может случиться, что процесс запущен, но до создания семафора дело еще не дошло. Или до создания файла в памяти.
Тут разница то где?


 
TStas ©   (2006-03-21 10:52) [12]

>ANB А за что? Ну нечаянно дважды щелкнул по значку и что хорошего? Два экземплята и будет.
У меня была собственная идея: сделать чобы программа создавала что-то ненужное, у этого ненежного будет handle Его не задушишь, не убъешь, при выключении света тоже исчезнет. Вот его-то и проверять. Только я очень плохо понимаю, как винды работают.


 
Piter ©   (2006-03-21 19:27) [13]

Leonid Troyanovsky ©   (21.03.06 8:40) [10]
Остается одна тонкость - объект существует, а окна еще нет.
Тогда, можно повторить все после небольшой паузы


а вот эта пауза может быть значительна.

В общем, к чему спор, FindWindow может дать неверный результат, это факт.

А вот мьютекс нет...

Гаврила ©   (21.03.06 10:21) [11]
Аналогично может случиться, что процесс запущен, но до создания семафора дело еще не дошло. Или до создания файла в памяти.
Тут разница то где?


а ты подумай, в чем разница :)


 
Leonid Troyanovsky ©   (2006-03-21 19:49) [14]


> Piter ©   (21.03.06 19:27) [13]


> В общем, к чему спор, FindWindow может дать неверный результат,
>  это факт.

> А вот мьютекс нет...

А почему, собс-но, " А вот мьютекс".
Он чего, разве не именованный объект? :)

FindWindow же всегда даст верный результат, например, 0
означает, что окно не нашлось (To get extended error information, call
GetLastError).

"Повторить все" это значит, что после некоторой паузы,
процесс повторяют сначала, т.е., если угодно, с мьютекса.

Если же хочется большей определенности можно взять memory
mapped file и писать туда что-то полезное для идентификации
первой копии.

--
Regards, LVT.


 
Sergey Masloff   (2006-03-21 19:57) [15]

Ihor Osov"yak ©   (20.03.06 23:57) [4]
> Вообще-то может ткое понятие как задание существовало и в NT4 - не уверен, а документацию сейчас смотреть влом.

Нет не существовало


 
Piter ©   (2006-03-21 20:27) [16]

Leonid Troyanovsky ©   (21.03.06 19:49) [14]
FindWindow же всегда даст верный результат, например, 0
означает, что окно не нашлось


я понимаю. Ладно, сейчас сформулирую.

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

Отсюда всегда возможны коллизии (хоть и не особо вероятны).

То есть, например ты вызываешь FindForm... ничего. После чего ты создаешь свое окно, но в этом промежутке времени может сработать и другой процесс, провести проверку и создать свое окно - в результате две копии запущенного приложения.

Повторная проверка? Отлично, но может случится ситуация, что каждая из копий создала окно и проводит повторную проверку... Обнаруживает уже запущенную копию и... ? Оба приложения закрываются, в результате ни одного запущенного процесса :)))

Конечно, чем больше таких повторных проверок и т.д. - тем шансы ошибки все больше стремятся к нулю.

В случае же мьютекста ты одной коммандой и проверяешь наличие мьютекса такого, и тут же его создаешь! Причем, Windows гарантирует, что ошибки не будет. Что если создать в разных процессах мьютексы с одним имененм - один из процессов СТО ПРОЦЕНТОВ получит ERROR_ALREADY_EXISTS.

Комбинация же FindForm, CreateForm такого не гарантирует нифига.


 
Piter ©   (2006-03-21 20:28) [17]

Piter ©   (21.03.06 20:27) [16]
у тебя элементарно нету функции, которая может проверить наличие окна и создать новое


* у тебя элементарно нету ОДНОЙ функции, которая может проверить наличие окна и создать новое


 
Piter ©   (2006-03-21 20:29) [18]

Блин, и вместо FindForm я имел в виду FindWindow... ну торопился, мысль, думаю, понятна.


 
Leonid Troyanovsky ©   (2006-03-22 15:18) [19]


> Piter ©   (21.03.06 20:27) [16]


> Повторная проверка? Отлично, но может случится ситуация,
>  что каждая из копий создала окно и проводит повторную проверку.
> .. Обнаруживает уже запущенную копию и... ? Оба приложения
> закрываются, в результате ни одного запущенного процесса
> :)))

Такое впечатление, что ты возражаешь кому-то другому.
Я, собс-но, не противопоставлял FindWindow тому же,
если угодно, мьютексу. Просто назвал его для пущей
важности (или общности) именованным объектом.
Одному нужен семафор, другому событие, третьему - мьютекс.
Лично я предпочитаю проекцию файла.

> Конечно, чем больше таких повторных проверок и т.д. - тем
> шансы ошибки все больше стремятся к нулю.

Да, Бог с ней, с повторной проверкой.
Покажем сообщение и закроемся.

> Комбинация же FindForm, CreateForm такого не гарантирует
> нифига.

Ей и не нужно ничего гарантировать. Ее задача отыскать
первую копию (для активации ли, передачи ли параметров и др.).
Это, так сказать, плата за использование мьютекса (события,
семафора и т.д.) вместо проекции файла.

--
Regards, LVT.


 
Гаврила ©   (2006-03-22 19:18) [20]


> Piter ©


> у тебя элементарно нету ОДНОЙ функции, которая может
> проверить наличие окна и создать новое

Какая разница, это одна функция, или это не одена функция?
Это одна функция, представляющая собой кусок кода, реализованный где-то там в DLL или это кусок кода, реализованного тут же (пусть и не одной функцией с точки зрения паскаля).
Тем более что все равно что-то случилось между моментом запуска процесса и подходу к этому "узкому месту", и это, случившееся, явно не "одна функция" с точки зрения паскаля
Разумеется, если написать инициализацию так, что реальный Handle будет выделен после кучи дополнительных мероприятий (типа а-ля подключение к БД), мы увеличим вероятность такой неудачи. Но это не имеет принципиального отличия от "чистой ситуации".


 
Leonid Troyanovsky ©   (2006-03-22 19:40) [21]


> Гаврила ©   (22.03.06 19:18) [20]

> Какая разница, это одна функция, или это не одена функция?


Важно лишь то, что это атомарная функция, т.е. второй поток
не начнет ее исполнять, пока первый оттуда не вышел.

--
Regards, LVT.


 
Гаврила ©   (2006-03-22 20:36) [22]


> Leonid Troyanovsky ©


> Важно лишь то, что это атомарная функция, т.е. второй
>поток
> не начнет ее исполнять, пока первый оттуда не вышел.


А процесс?


 
Piter ©   (2006-03-22 21:06) [23]

Гаврила ©   (22.03.06 19:18) [20]
Какая разница, это одна функция, или это не одена функция?
Это одна функция, представляющая собой кусок кода, реализованный где-то там в DLL


принципиальная. "где-то там в DLL" она реализована ТАК, что невозможно получить ошибку, ты так НЕ сможешь сделать в своем процессе или тебе надо будет писать драйвер.


 
Пупкин   (2006-03-22 23:08) [24]

Форматируешь винт и этим ограничиваешь число. Делов-то


 
Leonid Troyanovsky ©   (2006-03-23 08:58) [25]


> Гаврила ©   (22.03.06 20:36) [22]

> > не начнет ее исполнять, пока первый оттуда не вышел.

> А процесс?


Для любых потоков, в том числе, из разных процессов.

--
Regards, LVT.


 
Гаврила ©   (2006-03-23 12:27) [26]


> Leonid Troyanovsky ©  


> Piter ©

Ну ладно, убедили
:-)


 
Defunct ©   (2006-03-23 12:57) [27]

> TStas

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


 
Piter ©   (2006-03-23 16:44) [28]

Defunct ©   (23.03.06 12:57) [27]

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


 
deamon_t   (2006-03-23 17:16) [29]

Имхо, вероятность этого исчезающие мала


 
Defunct ©   (2006-03-23 23:50) [30]

Piter ©   (23.03.06 16:44) [28]

Вначале сэмулируйте ситуацию когда на одном процессоре одновременно стартанут две копии. Потом можно будет продолжить полемику.

Приблизительно одинаковое время здесь откровенно "не катит", т.к. та копия которая стартанет приблизительно раньше, та и останется.


 
Piter ©   (2006-03-24 01:37) [31]

Defunct ©   (23.03.06 23:50) [30]
Вначале сэмулируйте ситуацию когда на одном процессоре одновременно стартанут две копии


Влегкую. Твой способ основан на сообщениях, никаких сообщений не будет без цикла выборки сообщений. А инициализация некоторых приложений может занимать существенное время, поэтому время выборки очередного сообщения может весьма продолжительным. За это время много что может случиться. Explorer как процесс с повышенным приоритетом вполне может успеть запустить другой процесс.

А уж на сильно загруженным компьютере вероятность такой ситуации повышается в разы.

Я уже приводил пример, что мне удавалось открыть пару окон установления dial-up соединения, что не должно происходить в при нормальном режиме невозможно. Налицо просчет данной реализации.

И эффекты очень забавные. Когда одно "окно" установило соединение, и ты жмешь соединиться во втором.

Никто не спорит, что реализовывать можно по разному, спор идет как идеологически правильно, чтобы не допускать ошибки в принципе. Можно использовать технологию, которая дает 99% вероятность успеха, если нет других технологий.

Но если есть вариант 100% безошибочной работы - то использовать желательно его, спорить никто не будет?


 
Defunct ©   (2006-03-24 02:12) [32]

>> Вначале сэмулируйте ситуацию когда на одном процессоре одновременно стартанут две копии

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


Причем тут вытесняющие потоки? Понятно что старт может быть прерван, однако так или иначе одна программа создаст основное окно раньше чем другая и очередь к этому окну будет создана раньше у другой копии программы. Броадкаст посылать лишь только после создания основного окна программы. Программа, которая первая создаст основное окно и победит в такой реализации.

> Я уже приводил пример, что мне удавалось открыть пару окон установления dial-up соединения, что не должно происходить в при нормальном режиме невозможно. Налицо просчет данной реализации.

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

PS: я могу привести код, а ты если есть желание попробуешь его "обломать".


 
Piter ©   (2006-03-24 13:19) [33]

Defunct ©   (24.03.06 2:12) [32]
я могу привести код, а ты если есть желание попробуешь его "обломать".


приводи.


 
Defunct ©   (2006-03-24 14:02) [34]

const
 WM_DONTINITIALIZE    = WM_USER + 0;
 WM_BRINGTOFRONT      = WM_USER + 1;

TForm1 = class( TForm )
private
   Server_START_UP : Integer;
   CanInitialize : Boolean;

   procedure WndProc(var msg: TMessage); override;
   procedure ProgramLeave(var msg:TMessage);message WM_DONTINITIALIZE;
   procedure ProgramBringToFront(var Msg:TMessage);Message WM_BRINGTOFRONT;

...
procedure TForm1.FormCreate(Sender: TObject);
begin
 CanInitialize := True;

 Server_START_UP := RegisterWindowMessage("WinRoute_Inspector StartUP message");
 if Server_START_UP = 0 then
    ShowMessage("Не удалось зарегистрировать сообщение"+#13+#10+
                "для пресечения повторного запуска программы");
 SendMessage(HWND_BROADCAST, Server_START_UP, Handle,0);

 if not CanInitialize then
    Halt(0);
 ....
end;

procedure TForm1.WndProc;
begin
 if (msg.Msg = Server_START_UP) and (Handle <> msg.WParam) then
    SendMessage(msg.WParam , WM_DONTINITIALIZE, Handle, 0);
 if (msg.Msg = TaskbarCreated) then
    if Config.PlacedToSystemTray then
       PlaceOnSystemTray;
 inherited;
end;

procedure TForm1.ProgramLeave;
begin
  msg.Result := 777;
  CanInitialize := false;
  SendMessage( msg.WParam, WM_BringToFront, Handle, 0);
end;

procedure TForm1.ProgramBringToFront;
begin
  msg.Result := 777;
  Show;
  Application.BringToFront;
end;


 
Piter ©   (2006-03-24 16:59) [35]

Хороший код, я бы так не догадался написать :)
Не учел бы, что винда такая умная и будет диспетчеризировать сообщения потока, когда он захвачен вызовом SendMessage.

Ну да ладно :)

Вот алгоритм ложной работы данного кода:

1) запускается первая копия, создается окно, выполняется дальнейший код "на пути" к:

SendMessage(HWND_BROADCAST...

2) в это время "параллельно" стартует вторая копия, тут важно, чтобы она успела создать свое окно ДО того, как в первой копии дело дойдет до "SendMessage(HWND_BROADCAST".

И не говорите, что такое невозможно - никто этого не знает. Возможно, RegisterWindowMessage будет долго обрабатываться в условиях тормозящей машины, иметь маленький приоритет.

В любом случае, существует ненулевая вероятность ситуации, когда оба приложения создадут окна, но ни в одном из них не дойдет до вызова "SendMessage(HWND_BROADCAST"

3) в первой копии доходит до вызова:

SendMessage(HWND_BROADCAST, Server_START_UP, Handle,0);

поток засыпает, винда пошла перебирать окна в системе

4) в это время во второй копии приложения исполнение кода тоже подходит к SendMessage, происходит вызов

5) вот тут то и диспетчеризируется броадкаст запрос от первой копии. Произойдет вызов TForm1.WndProc во второй копии, первой копии пошлется:

SendMessage(msg.WParam , WM_DONTINITIALIZE, Handle, 0);

так как поток первой копии находится в состоянии вызова системной функции SendMessage, то вполне возможно сообщение будет тут же диспетчеризировано. В первой копии установится флаг:

CanInitialize := false;

Далее второй копии будет послано сообшение WM_BRINGTOFRONT

6) поток второй копии также находится в режиме вызова системной функции SendMessage, будет исполнено: Application.BringToFront;

7) далее управление вернется к SendMessage, вызванной второй копией, будет разослан броадкаст от лица уже второй копии

8) так как первая копия все еще находится в состоянии вызова SendMessage - то сообщение будет диспетчеризировано тут же и в первой копии сработает: TForm1.WndProc

Второй копии будет выслано:

SendMessage(msg.WParam , WM_DONTINITIALIZE, Handle, 0);

9) ну вторая тоже вызывает SendMessage, поэтому сообщение также будет диспетчеризировано и во второй копии:

CanInitialize := false;

с последующими действиями и вызовом Application.BringToFront; в первой копии

10) далее произойдет выход из:

SendMessage(HWND_BROADCAST, Server_START_UP, Handle,0);

во второй копии, проверка на CanInitialize и Halt.

11) после чего произойдет выход из SendMessage в первой копии, проверка на CanInitialize и также Halt.


 
Piter ©   (2006-03-24 17:00) [36]

Это только один из вариантов развития событий. Без исходников винды тут точно не скажешь.

Да и очень вероятно, что в разных версиях Windows события будут развиваться по разному пути даже при совершенно одинаковых условиях.


 
Defunct ©   (2006-03-24 17:33) [37]

Piter ©   (24.03.06 16:59) [35]

Если следовать твоим рассуждениям, то, как я и говорил, в худшем случае закроются обе программы. Но запуск нескольких копий - однозначно исключен.


 
Piter ©   (2006-03-24 18:25) [38]

Defunct ©   (24.03.06 17:33) [37]
то, как я и говорил, в худшем случае закроются обе программы


а, ну если тебя это устраивает...

Но все таки я бы назвал это некорректным поведением.

Я не понимаю, зачем использовать этот способ, если можно использовать мьютексы? Она гарантировано дадут результат.

К тому же, мьютексы использовать оптимальнее. В твоем случае уже много что сделано, произведена инициализация всех модулей, созданы некоторые формы, зачем это, если запускаться не планируем?

А проверку мьютексами можно сделать прямо в самом начале.


 
Defunct ©   (2006-03-25 01:46) [39]

Piter ©   (24.03.06 18:25) [38]
> а, ну если тебя это устраивает...

Не надо доходить до крайностей. Т.к. ни один дибил не будет специально кликать по 30 раз на твоей программе. А коль уж действительно попадется такой дибил, которому вместо того чтобы работать с программой, надо, зная что программа расчитана одновременную работу только одной копии, всяко поизгаляться чтобы запустить 2 копии или больше, то это вполне нормальное для него наказание. Хотя к сожалению оно не сработает, одна копия таки останется.

> Я не понимаю, зачем использовать этот способ, если можно использовать мьютексы? Она гарантировано дадут результат.
> К тому же, мьютексы использовать оптимальнее.


Напоминает отрывок из Шрека:
- Ириски! Все любят ириски! Шрек, ты любишь ириски?

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


 
Piter ©   (2006-03-25 02:16) [40]

Defunct ©   (25.03.06 1:46) [39]
Напоминает отрывок из Шрека:
- Ириски! Все любят ириски! Шрек, ты любишь ириски?


а ты всегда это пишешь, когда предлагают решение БОЛЕЕ оптимальное, чем твое?

Defunct ©   (25.03.06 1:46) [39]
Хотя к сожалению оно не сработает, одна копия таки останется


почему не сработает? Расскажи. Ты видимо ковырял исходники Windows.

Defunct ©   (25.03.06 1:46) [39]
Например, чтобы передать параметры или выполнить кое-какие действия.


думаю, создание формы для этого вовсе не обязательно. Причем, такое создание, что в OnCreate вызывается Halt...


 
Piter ©   (2006-03-25 02:18) [41]

Defunct ©   (25.03.06 1:46) [39]
Т.к. ни один дибил не будет специально кликать по 30 раз на твоей программе


я тебе уже писал, что мне удавалось открыть 2 окошка установления одного Dial-up соединения. Правда, в этом время компьютер дикто тормозил и жутко свопил, но какая разница. И я не тыкал 30 раз.


 
Defunct ©   (2006-03-26 03:40) [42]

Piter ©   (25.03.06 02:16) [40]
> а ты всегда это пишешь, когда предлагают решение БОЛЕЕ оптимальное, чем твое?

Я не настаиваю на своем решении и тем более не говорю, что оно самое оптимальное и все должны делать именно так. Просто оно (решение) есть, и работает надежно. И нафига, конкретно мне мьютексы?
"Людоеды любят лук."

> думаю, создание формы для этого вовсе не обязательно. Причем, такое создание, что в OnCreate вызывается Halt...
imho - это уже из разряда экономии спичек.

> я тебе уже писал, что мне удавалось открыть 2 окошка установления одного Dial-up соединения.
Ну и что? Может окошко диалап соединения использует мьютексы? Или у тебя есть уверенность, что оно использует сообщения? Что-то мысль твою не уловил.


 
Piter ©   (2006-03-26 17:23) [43]

Defunct ©   (26.03.06 3:40) [42]
И нафига, конкретно мне мьютексы?


да ты можешь использовать что тебе угодно.
Мы говорим про оптимальные и правильные решения.

Я придерживаюсь принципа, что если можно сделать лучше - то надо сделать лучше, несмотря на то, что другое решение будет работать в 99% случаев. Но если теми же усилиями ты можешь сделать так, чтобы работало в 100% случаев - то надо сделать так.

Defunct ©   (26.03.06 3:40) [42]
Может окошко диалап соединения использует мьютексы?


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


 
MegaVolt ©   (2006-03-27 17:26) [44]

99% в одном месте 99% в другом в результате уже вероятность сбоя 2%
Если таких мест 100 то прога будет глючить стабильно. Вот чтобы этого не было и стараются хоть там где это точно возможно сделать 100% а не 99%


 
Defunct ©   (2006-03-28 02:35) [45]

Piter ©   (26.03.06 17:23) [43]
> если бы оно использовало мьютексы - такой ситуации в принципе не могло бы возникнуть.

Тогда откуда у тебя вдруг такая уверенность, что там именно сообщения и используются именно так, как привел я в [34].
Криво можно написать что угодно.

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

> Я придерживаюсь принципа, что если можно сделать лучше - то надо сделать лучше, несмотря на то, что другое решение будет работать в 99% случаев. Но если теми же усилиями ты можешь сделать так, чтобы работало в 100% случаев - то надо сделать так.

1. Что-то я не вижу варианта с мьютексами.
2. Вариант с сообщениями лично меня ни разу не подвел, поэтому  могу сказать, что он на 100% надежен.

>>Defunct ©   (26.03.06 3:40) [42]
>>Может окошко диалап соединения использует мьютексы?
>если бы оно использовало мьютексы - такой ситуации в принципе не могло бы возникнуть.

Да что ты такое говоришь? Мьютекс лишь средство, а более важный вопрос это то - как это средство используется программистом. Программист может все испаганить сам имея в арсенале очень мощные средства..
Я могу с полной уверенностью сказать, что задачу автора можно надежно решить любыми средствами обспечивающими общий доступ (шару) в т.ч. даже с помощью общего файла, общего сокета, общего ключа системного реестра и т.п., главное чтобы используемый ресурс был общим.


 
Leonid Troyanovsky ©   (2006-03-28 14:18) [46]


> Defunct ©   (28.03.06 02:35) [45]


> По поводу второго - если ты хочешь сказать, что мое решение
> неправильное - тогда найди ошибку.

Одну ошибку видно сразу: не foreground приложению не положено
делать себя foreground.

Кроме того, мне очень не нравятся бродкасты, хотя, конечно,
это не ошибка.

> 1. Что-то я не вижу варианта с мьютексами.

Я бы лучше увидел вариант с проекцией файла :)
Однако, сразу оговорюсь: должен быть обоснован выбор имени,
бо зашивать в код, скажем, GUID мне представляется корявым.

> 2. Вариант с сообщениями лично меня ни разу не подвел, поэтому
>  могу сказать, что он на 100% надежен.

Чтобы подлить масла в огонь, предложу свой давнишний вариант

http://groups.google.com/group/borland.public.delphi.winapi/msg/b2ebfc63eb002ebe

Хотя, конечно, и он не свободен от недостатков (кто заметит - каких?),
но, со своей задачей он справляется вполне успешно.

--
Regards, LVT.


 
Piter ©   (2006-03-28 17:23) [47]

Defunct ©   (28.03.06 2:35) [45]
Тогда откуда у тебя вдруг такая уверенность, что там именно сообщения и используются именно так, как привел я в [34].


я, собственно, не говорил, что там используется твой вариант

Defunct ©   (28.03.06 2:35) [45]
По поводу второго - если ты хочешь сказать, что мое решение неправильное - тогда найди ошибку.


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

Defunct ©   (28.03.06 2:35) [45]
Что-то я не вижу варианта с мьютексами


ты его легко можешь сам реализовать. И он прописан везде, в интернете куча примеров, в книжках многих написан

Defunct ©   (28.03.06 2:35) [45]
Вариант с сообщениями лично меня ни разу не подвел, поэтому  могу сказать, что он на 100% надежен


Ну тут даже и без комментариев.

Ты вполне можешь следовать логике "Если я не вижу ошибок - значит, их нет" - пожалуйста. Я пытаюсь по другому.


 
Leonid Troyanovsky ©   (2006-03-28 19:14) [48]


> Piter ©   (21.03.06 20:28) [17]

> * у тебя элементарно нету ОДНОЙ функции, которая может проверить
> наличие окна и создать новое


У меня есть. Только это не совсем функция, а, скажем, подход.
Но, сути ж оно не меняет?

--
Regards, LVT.


 
Defunct ©   (2006-03-29 01:44) [49]

Piter ©   (28.03.06 17:23) [47]
Бессмысленное переливание из пустого в порожнее.
(это не к тебе лично относится, а к тому во что превратилась ветка).

Leonid Troyanovsky ©   (28.03.06 14:18) [46]
> Одну ошибку видно сразу: не foreground приложению не положено
делать себя foreground.

Здесь я не соглашусь.. Т.к. по сути foreground приложение передает фокус своей более старой копии самостоятельно и добровольно.

> Кроме того, мне очень не нравятся бродкасты, хотя, конечно,
это не ошибка.

Это мнение я уже слышал и с ним даже согласен. Да броадкаст это плохо, да отвлекает почти все приложения, но запуск таких программ, как та в которой у меня произодится броадкаст происходит один раз со стартом сервера, и потом только админ может ее случайно запустить, и то врятли ему это придет в голову когда в трее и так висит иконка программы...


 
Leonid Troyanovsky ©   (2006-03-29 08:37) [50]


> Defunct ©   (29.03.06 01:44) [49]

> Здесь я не соглашусь.. Т.к. по сути foreground приложение
> передает фокус своей более старой копии самостоятельно и
> добровольно.


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/setforegroundwindow.asp

Хотя, более точно restrictions описаны в remarks to LockSetForegroundWindow

--
Regards, LVT.


 
Fay ©   (2006-03-29 20:12) [51]

2 Leonid Troyanovsky ©   (28.03.06 14:18) [46]
> GUID мне представляется корявым
Корявее, чем FindWindow? Ню-ню...


 
Defunct ©   (2006-03-30 03:56) [52]

Leonid Troyanovsky ©   (29.03.06 08:37) [50]

Ссылка к сожалению у меня не открылась.

Если там речь идет о рекомендациях не использовать SetForegroundWindow и
MS считает, что запустив приложение, которое просто молча сгинет из-за присутствия более старой копии и не передаст фокус старой копии - допустимо, то пусть они со своими ограничениями катятся куда подальше. Более того на это у меня есть мнение - идиотов хватает и среди тех кто пишет правила. До инфаркта пользователя нехорошо доводить, а это поверьте возможно, когда пром. программа "откажется" запускаться без причины.

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


 
Leonid Troyanovsky ©   (2006-03-30 09:06) [53]


> Fay ©   (29.03.06 20:12) [51]

> > GUID мне представляется корявым

> Корявее, чем FindWindow? Ню-ню...


Зашить в код GUID - конечно, более корявое решение.
Лично я предпочту EnumWindows (хотя, и не совсем FindWindow).
Для гуевых дельфийских приложений этого вполне хватает.
Неатомарность сочетания if EnumWindows() then .. меня
вовсе не расстраивает, бо в самом плохом случае (скажем, на
двухпроцессорной машине при "удачном" стечении обстоятельств)
запустятся два приложения, но это никак не должно отразиться на
их работоспособности.

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

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

Поэтому, ничего зашивать в код и не следует.

Ну, а для полноты же картины я бы упомянул еще один подход:

http://groups.google.com/group/fido7.ru.delphi.chainik/msg/278f89887ab26b31

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-03-30 09:08) [54]


> Defunct ©   (30.03.06 03:56) [52]

> Ссылка к сожалению у меня не открылась.


Сочуствую.
Вообще-то, http://msdn.microsoft.com весьма полезный ресурс,
бо содержит наиболее актуальную информацию.
Так что, стоит пнуть своих админов.

--
Regards, LVT.


 
Рафик ©   (2006-03-30 10:14) [55]

А если я программу запущу от разных пользователей?


 
Leonid Troyanovsky ©   (2006-03-30 11:33) [56]


> Рафик ©   (30.03.06 10:14) [55]

> А если я программу запущу от разных пользователей?


Разные пользователи работают в разных сессиях.

--
Regards, LVT.


 
Alexander Panov ©   (2006-03-30 12:12) [57]

Что вы спорите?
Предлагаю корректно реализовать эту задачу с такими начальными условиями:

1. Возможен запуск только одной копии программы.
2. Если копия программы запущена, переместить запущенный экземпляр на передний план.
3. ОС - Windows 2000 и выше.
А дальше уже можно критиковать.

PS.
Приложение оконное.


 
Leonid Troyanovsky ©   (2006-03-30 14:37) [58]


> Alexander Panov ©   (30.03.06 12:12) [57]

> А дальше уже можно критиковать.


Я уже привел, по-крайней мере, два варианта.
Если хочешь, вот и третий:

=== Вариант с Мьютексом ===
В файле проекта (.dpr) прямо можешь написать нечто вроде:

uses windows,...
var
 H: THandle;
begin
 H := CreateMutex(nil, True, "уникальное_имя_для_твоей_проги");
 if GetLastError = ERROR_ALREADY_EXISTS then
 begin
   H := FindWindow(nil, "название заголовка окна программы");
   SetForegroundWindow(H);
   Exit;
 end;
 Application.Initialize;
 Application.Title := "название заголовка окна программы";
 Application.CreateForm(TAppData, AppData);
 Application.CreateForm(TMain, Main);
 Application.Run;
 CloseHandle(H);
end;


Прочко Денис Владимирович.
sysadmin@)farmeko.khv.ru

Для критики все готово.

--
Regards, LVT.


 
Рафик ©   (2006-03-30 14:56) [59]


> Разные пользователи работают в разных сессиях.

Винда позволяет запускать в одной сессии из под разных пользователей


 
Leonid Troyanovsky ©   (2006-03-30 15:14) [60]


> Рафик ©   (30.03.06 14:56) [59]

> Винда позволяет запускать в одной сессии из под разных пользователей


И, что?

Окна, расположенные на однов десктопе, доступны для перечисления
EnumWindows, EnumThreadWindows & etc.
Объекты ядра могут иметь локальные имена (в пределах сессии),
а также и глобальные, с префиксом Global\, на все.

--
Regards, LVT.


 
Alexander Panov ©   (2006-03-30 16:31) [61]


> Leonid Troyanovsky ©   (30.03.06 14:37) [58


В этом варианте при не поднимется на передний план.
Конечно, перед SetForegroundWindow можно выполнить ShowWindow(H,SW_SHOW), но вот такой вариант исключает находждение окна:

procedure TForm1.FormCreate(Sender: TObject);
begin
 Application.Title := "test";
end;


 
Alexander Panov ©   (2006-03-30 16:32) [62]

>Leonid Troyanovsky ©   (30.03.06 15:14) [60]

А необходимость в динамическом изменении хинта к приложению возникает довольно часто для отображения нужной информации во всплывающем хинте приложения на панели задач.


 
Leonid Troyanovsky ©   (2006-03-30 18:59) [63]


> Alexander Panov ©   (30.03.06 16:31) [61]


> В этом варианте при не поднимется на передний план.
> Конечно, перед SetForegroundWindow можно выполнить ShowWindow(H,
> SW_SHOW),

Если речь про [58], то там не совсем точно, т.е. нужно SFW для
окна приложения.

procedure ActivatePrevInstance(wnd: HWND);
var
 h : HWND;
begin
 h := GetWindowLong(wnd, GWL_HWNDPARENT);
 if IsIconic(h) then
   ShowWindow(h, SW_RESTORE);
 SetForegroundWindow(h);
end;



> такой вариант исключает находждение окна:


Есть еще и класс. Кстати, ранее я предлагал, как это обходится -
использованием mmf vs mutex, в который и писать нужный хендл.

--
Regards, LVT.


 
Defunct ©   (2006-03-30 19:28) [64]

Leonid Troyanovsky ©   (30.03.06 09:08) [54]

Вообще-то чем выпендриваться с сочуствиями, лучше бы ответить на конкретный вопрос.

MSDN полный у меня установлен локально, и по инету мне шариться не приходится в поиске описания той или иной функции. В MSDN (April 2003) который у меня установлен нет никаких restrictions на использование SetForegroundWindow.

> Leonid Troyanovsky ©   (30.03.06 18:59) [63]
> Есть еще и класс. Кстати, ранее я предлагал, как это обходится -
> использованием mmf vs mutex, в который и писать нужный хендл.

А какой смысл в этом? Если только ваши предрассудки, то проще продолжать использовать HWND_BROADCAST.


 
Alexander Panov ©   (2006-03-30 21:54) [65]


> Defunct ©   (30.03.06 19:28) [64]
</I
> проще продолжать использовать HWND_BROADCAST.

>

Ну так приведи рабочий пример;)


 
Alexander Panov ©   (2006-03-30 22:18) [66]


> Defunct ©   (23.03.06 12:57) [27]
>
> Я для этой цели использую RegisterWindowMessage, при старте
> посылаю сообщение всем окнам, если в системе уже запущена
> копия программы, то словив это сообщение она выдвигает себя
> на передний план, и отсылает только что запущенной программе
> сообщение, чтобы та себя закрыла.


Вот критика этого метода:

1. Какой смысл в RegisterWindowMessage, если получающая программа не знает, какое сообщение обрабатывать?
2. Пример выдвижения программы самой себя тоже неплохо бы увидеть;)
3. Для того, чтобы только что запущенная вторая копия могла обработать сообщение, должно хотя бы быть создано хотя бы одно окно в приложении. Таковым является для VCL MainForm. Но в MainForm.OnCreate Может быть проделана масса предварительной работы до того, как окно получит и обработает сообщение, чего никак нельзя допускать.


 
Defunct ©   (2006-03-31 01:42) [67]

> Alexander Panov [65] & [66]

[34]...


 
Alexander Panov ©   (2006-03-31 02:05) [68]


> Defunct ©   (31.03.06 01:42) [67]


По поводу кода в [34]:

Не может быть так, что другое приложение ответит на Broadcast?
Что если этим методом пользуются сразу 2 разных приложения?


 
Eraser ©   (2006-03-31 02:11) [69]

хе-хе.. ну и раздули жи ветку )
скажу и я своё imho )

Насчёт целесообразности запрета запуска второй копии. Есть ситуации когда это необходимо, например любой сервер, который слушает определённый порт.

Насчёт способа определения существования второй копии. Тут ессено единственно правильного варианта нету, иначе бы столько разговоров тоже не было. Всё зависит от типа приложения.
Если данное приложение имеет документо-ориентированную структуру (типа ворда/экселя/винэмпа), то следует применять подход, при котором нам нужно каким то образом сообщить другому приложению о запуске второй копии.
Если приложение не документо-ориентированное, то следует использовать простой именованый объект ядра, но при этом, если вторая копия существует обязательно сообщить об этом юзеру (например через мессадж бокс). Иначе если первая копия повисла (и при этом не видно её окон), а вторая просто не будет запускаться - это приведет юзера в шок и панику :-)

В документо-ориентированных приложениях лучше, в данном случае, применять гибридную тактику, т.е. несколько разных подходов, как например это сделано в браузере Opera. Если браузер подвис, то при запуске второй копии, если не возможно передать адрес страницы в первую - высвечивается мессадж бокс, что мол одна копия проги уже запущена, если же первый экземпляр работает нормально, то в нём открывается нужная страница, а вторая копия спокойно уничтожается, при этом замечу, что с окном первого экземпляра ничего не происходит, т.е. его не пытаются переместить на первый план.


 
Германн ©   (2006-03-31 02:31) [70]


> Eraser ©   (31.03.06 02:11) [69]
>
> хе-хе.. ну и раздули жи ветку )
> скажу и я своё imho )


А стоило ли влезать? Заклюют! Имхо.
И так-то была напряжёнка. Да ещё Саша Панов проснулся. :-) Извини Саша, но иного термина у меня не нашлось. :-(


 
Defunct ©   (2006-03-31 03:34) [71]

Alexander Panov ©   (31.03.06 02:05) [68]

Ничего страшного не произойдет.. Windows все равно один broadcast разошлет раньше другого, а дальше там сплошной блок (с помощью SendMessage). Одно приложение тихо удалится, и на второй броадкаст просто некому будет "отвечать".


 
Defunct ©   (2006-03-31 03:39) [72]

> Что если этим методом пользуются сразу 2 разных приложения?

Если речь о разных типах приложений.. Дык тогда разные сообщения пусть регистрируют.
RegisterWindowMessage("Тип программ 1")
RegisterWindowMessage("Тип программ 2")


 
Defunct ©   (2006-03-31 04:04) [73]

Alexander Panov ©   (31.03.06 02:05) [68]

Ваши вроде бы простые вопросы совсем сбили меня с толку..[71] Можете не читать, он был написан, когда я был на своей волне и подумал, что в вопросах тот же контекст, который закладывал Piter(C) выше...

> Не может быть так, что другое приложение ответит на Broadcast?

Нет не может, т.к. зарегистрированное сообщение задается уникальной строкой также как и mutex. Естественно, если Вы зарегистрируете сообщение с именем, которое уже кем-то используется, то тогда есть вероятность что ответит какое-то другое приложение. При этом если рассматривать [34], то это приложение точно не выполнит требуемую цепочку действий, необходимую для закрытия нашего приложения. Т.е. оно не пошлет сообщение WM_DONTINITIALIZE с Handle окна в WParam.


> Что если этим методом пользуются сразу 2 разных приложения?

Ничего, одно приложение работает с одним сообщением, другое - с другим. Друг-другу они мешать не будут.


 
Leonid Troyanovsky ©   (2006-03-31 08:31) [74]


> Defunct ©   (30.03.06 19:28) [64]


> Вообще-то чем выпендриваться с сочуствиями, лучше бы ответить

Что мне лучше, я уж сам решу.
И попрошу следить за речью.

> MSDN (April 2003) который у меня установлен нет никаких
> restrictions на использование SetForegroundWindow.

Они есть там, IMHO, начиная с 99 года. Просто, в этой статье
описаны коряво: мол, в 9x/Me, а на самом деле - и в NT5+.
Поэтому, и говорил я, где надо читать более точный текст.

> > использованием mmf vs mutex, в который и писать нужный
> хендл.

> А какой смысл в этом? Если только ваши предрассудки, то

Потому, что это проще, чем использовать бродкаст.
Да и, еще, в дельфийских приложениях даже таймер
имеет окно верхнего уровня.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-03-31 08:50) [75]


> Eraser ©   (31.03.06 02:11) [69]


> Насчёт целесообразности запрета запуска второй копии. Есть
> ситуации когда это необходимо, например любой сервер, который
> слушает определённый порт.

Если необходимо, откроет его эксклюзивно - более ничего
и не требуется (в смысле ограничений). См. ранее по топику.

> разговоров тоже не было. Всё зависит от типа приложения.

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

Я недавно приводил ссылку на такое решение.

> юзеру (например через мессадж бокс). Иначе если первая копия
> повисла (и при этом не видно её окон), а вторая просто не
> будет запускаться - это приведет юзера в шок и панику :-

Если повисла, то, конечно, сообщить об этом юзеру,
запускать или запускать вторую копию - решать ему.

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

И почему же его не переместить? Может не умеют? :)

Юзер пускает приложение из проводника, комстроки и т.д., т.е.
из foreground приложения.
Приложение, запускаемое из foreground приложения будет foreground,
если не делать специальных усилий.
Поэтому юзер вправе рассчитывать, что ему покажут желаемое
именно foreground . Кстати, на совершенно законных основаниях.

--
Regards, LVT.


 
Defunct ©   (2006-03-31 09:10) [76]

>> Вообще-то чем выпендриваться с сочуствиями, лучше бы ответить
> Что мне лучше, я уж сам решу.
> И попрошу следить за речью.

И я сам решу каким тоном мне и с кем разговаривать.
Пост [54] заслуживает еще более грубого ответа.
Я люблю прямоту, а не общение с помощью намеков, которое только усложняет фильтрацию смысла из текста.

> Они есть там, IMHO, начиная с 99 года. Просто, в этой статье
> описаны коряво: мол, в 9x/Me, а на самом деле - и в NT5+.
> Поэтому, и говорил я, где надо читать более точный текст.

Кто они?
Если вы об этом:

This method allows SetForegroundWindow on Windows 98/Windows Me and Windows 2000/Windows XP to behave the same as Windows 95 and Windows NT 4.0, respectively, for all applications. The setup application should warn the user that this is being done so that the user isn"t surprised by the changed behavior. On Windows Windows 2000 and Windows XP, the call fails unless the calling thread can change the foreground window, so this must be called from a setup or patch application. For more information, see Foreground and Background Windows.

A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.

The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.


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


 
Alexander Panov ©   (2006-03-31 09:31) [77]

И все-таки...

Думаю, что существуют 3 универсальных решения. Одно для безоконных приложений(с этим как раз проблем нет), второе для оконных, третье для консольных.

Задача для безоконного приложения тривиальна. Задача для оконного не так тривиальна, но решаема вполне.

А вот для консольного(эта мысль возникла только сейчас) - не знаю. Даже не занимался вопросом. Хотя стоит подумать.


 
Defunct ©   (2006-03-31 09:36) [78]

Alexander Panov ©   (31.03.06 09:31) [77]

должно быть просто:
или консольное приложение отнести к "безоконным",
или создав невидимое окошко - перевести в разряд "оконных"
;>


 
Alexander Panov ©   (2006-03-31 09:38) [79]


> Defunct ©   (31.03.06 09:10) [76]


Ну я вообще не просто так написал в [66] (2. Пример выдвижения программы самой себя тоже неплохо бы увидеть;)). Выдвижение окна самого себя на передний план не такая тривиальная задача-). Просто покритиковать хотелось;)

В MSDN написано про not foreground winndow, но там есть одна мальнькая деталь. Я ее, например, не уловил сразу, из-за чего было сломано немало копий в споре.


> Defunct ©   (31.03.06 03:34) [71]
>
> Alexander Panov ©   (31.03.06 02:05) [68]
>
> Ничего страшного не произойдет.. Windows все равно один
> broadcast разошлет раньше другого, а дальше там сплошной
> блок (с помощью SendMessage). Одно приложение тихо удалится,
>  и на второй броадкаст просто некому будет "отвечать".


Если это твое приложение. А если чужое, но использует тот же номер сообщения?

Ситуация маловероятна, но возможна. А то, что возможно, бывает происходит чаще, чем хотелось бы.


 
Alexander Panov ©   (2006-03-31 09:40) [80]


> Defunct ©   (31.03.06 09:36) [78]
>
> Alexander Panov ©   (31.03.06 09:31) [77]
>
> должно быть просто:
> или консольное приложение отнести к "безоконным",
> или создав невидимое окошко - перевести в разряд "оконных"
> ;>


Проблема во второй части задачи: вывести на передний план.

Я пока не пытался работать с консольными приложениями. Если бы они ничем не отличались от оконных, тогда никаких проблем не было бы.-)


 
Defunct ©   (2006-03-31 16:47) [81]

Alexander Panov ©   (31.03.06 09:38) [79]

> Если это твое приложение. А если чужое, но использует тот же номер сообщения?

Уже ответил на этот вопрос [73]

> Ситуация маловероятна, но возможна. А то, что возможно, бывает происходит чаще, чем хотелось бы.

Ситуация действительно очень маловероятна. Можно попробовать задать сообщение строкой с русскими символами ;> что еще сильнее снизит вероятность появления такой ситуации.


 
Defunct ©   (2006-03-31 16:51) [82]

> Я пока не пытался работать с консольными приложениями. Если бы они ничем не отличались от оконных, тогда никаких проблем не было бы.-)

Дык, консольные приложения в подавляющем большинстве случаев используеются с перенапраленным выводом, и "резидентно" не висят в памяти долго ;>


 
Alexander Panov ©   (2006-03-31 17:06) [83]

>
> Defunct ©   (31.03.06 16:47) [81]
>
> Alexander Panov ©   (31.03.06 09:38) [79]
>
> > Если это твое приложение. А если чужое, но использует
> тот же номер сообщения?
>
> Уже ответил на этот вопрос [73]


Ведь не обязательно чужое приложение использует сообщение с регистрацией по имени?


 
Defunct ©   (2006-03-31 18:03) [84]

Alexander Panov ©   (31.03.06 17:06) [83]

Дык, грамотные приложения не будут использовать сообщения с номерами, зарезервированными под регистрацию без предварительной регистрации. Они будут использовать сообщения WM_USER + .. для своих нужд не так ли?

Приложения, которые используют "отфонарные" номера сообщений для своих нужд, IMHO нужно сразу отправлять в корзину.


 
Alexander Panov ©   (2006-03-31 18:19) [85]


> Приложения, которые используют "отфонарные" номера сообщений
> для своих нужд, IMHO нужно сразу отправлять в корзину.


Ну почему. Для внутрипрограммного взаимодействия совсем необязательно регистрировать сообщение. Вот для межпрограммного - да.

Так что никакого криминала в использовании номерв незарегистрированных сообщений нет.

Поэтому Broadcast с любым номер, в принципе, чреват вылетом некоего случайного приложения.


 
Defunct ©   (2006-03-31 20:08) [86]

> Ну почему. Для внутрипрограммного взаимодействия совсем необязательно регистрировать сообщение. Вот для межпрограммного - да.

Регистрировать не обязательно, но и использовать любые номера сообщений "от фонаря" тоже нельзя. В Windows отводится непомню сколько точно номеров начиная с номера WM_USER как раз для такого внутрипрограммного взаимодействия.

> Так что никакого криминала в использовании номерв незарегистрированных сообщений нет.

Конечно нет, если только не используются номера системных и зарезервированных под регистрацию сообщений в целях внутрипрограммного взаимодейтсвия.


 
Leonid Troyanovsky ©   (2006-04-01 11:40) [87]


> Defunct ©   (31.03.06 09:10) [76]

> тогда либо вы, либо я неправильно понимаем написанное в
> MSDN. Конкретно мое приложение не использует LockSetForegroudWindow,
>  соответственно никаких проблем на которые вы так упорно
> уже 4-й раз намекаете, но прямо ничего не говорите, быть
> не может.


Starting with Microsoft Windows 98 and Windows 2000, the system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.

Это перечень условий, для тех кто может set.

Прошу указать на такое условие:
окно процесса получило (бродкаст) сообщение.

--
Regards, LVT.


 
Alexander Panov ©   (2006-04-01 15:06) [88]


> Defunct ©   (31.03.06 20:08) [86]
> Регистрировать не обязательно, но и использовать любые номера
> сообщений "от фонаря" тоже нельзя. В Windows отводится непомню
> сколько точно номеров начиная с номера WM_USER как раз для
> такого внутрипрограммного взаимодействия.


Я не о том говорил. Любая программа может использовать сообщения из пользовательского диапазона свободно, как для внетреннего, так и для межпрограммного взаимодействия.

Если программа использует сообщение внутри приложения, не регистрируя его в системе(что вполне возможно - такое вижу сплошь и рядом), то при посылке сообщения из твоей программы широковещательного сообщения эта программа его получит и обработает в соответствии со своими понятиями. Вплоть до AV.


 
Defunct ©   (2006-04-01 23:25) [89]

Alexander Panov ©   (01.04.06 15:06) [88]

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

Да все верно.

> Если программа использует сообщение внутри приложения, не регистрируя его в системе(что вполне возможно - такое вижу сплошь и рядом), то при посылке сообщения из твоей программы широковещательного сообщения эта программа его получит и обработает в соответствии со своими понятиями. Вплоть до AV.

Из моей программы посылается броадкаст с сообщением, уникальный номер которого получен в результате регистрации сообщения. Соответвенно, номер этого сообщения НЕ ИЗ ПОЛЬЗОВАТЕЛЬСКОГО диапазона.

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

Leonid Troyanovsky ©   (01.04.06 11:40) [87]
A process can set the foreground window only if one of the following conditions is true
переводится как:
"процесс может установть окно на передний план только если одно из перечисленных условий справедливо".
В моем случае как минимум несколько условий True:
- нет активных меню,
- foreground not locked
- косвенно - there is not foreground window (после Halt(0))..


 
Alexander Panov ©   (2006-04-02 00:35) [90]


> Defunct ©   (01.04.06 23:25) [89]


Хорошо, согласен. Ты меня убедил. В принципе, такой метод для оконных программ подходит.
Только Broadcast вынести в dpr до создания главной формы, и будет все красиво.

Остаются консольные приложения.


 
Piter ©   (2006-04-02 01:12) [91]

Alexander Panov ©   (02.04.06 0:35) [90]
Только Broadcast вынести в dpr до создания главной формы, и будет все красиво


угу, а перед этим ручками создать сигнальное окно?

Нет, я уж лучше мьютексами...


 
Defunct ©   (2006-04-02 01:37) [92]

Alexander Panov ©   (02.04.06 00:35) [90]

> Только Broadcast вынести в dpr до создания главной формы, и будет все красиво.

Появится некоторая сложность в организации двухстороннего обмена.. Расчитывать только на MSG.Result нельзя, как раз из-за вероятности присутствия в системе таких программ, о которых вы говорили. (которые могут использовать номер нашего сообщения).

> Остаются консольные приложения.
Тут, я - пас. ;>


 
Leonid Troyanovsky ©   (2006-04-02 03:36) [93]


> Defunct ©   (01.04.06 23:25) [89]

> - косвенно - there is not foreground window (после Halt(0)).


Нет, конечно. Halt выполняется после SentMessage,
т.е. первая копия пытается активизировать себя тогда,
когда вторая foreground.

По поводу других true, можно сказать, что они необходимы,
но, все же, не достаточны.

--
Regards, LVT.


 
Defunct ©   (2006-04-02 04:23) [94]

Leonid Troyanovsky ©   (02.04.06 03:36) [93]

Может вы и правы. Хоть в старом MSDN нет таких условий, возможно стоит сделать так чтобы новая копия сама выдвигала окно старой копии наперед, тем более Handle окна известен и приходит ответным сообщением.

Но тут мне кажется могут возникнуть трудности с show.. Imho не очень красиво получится, т.к. только что запущенная программа не знает в каком состоянии находится предыдущая копия (вдруг она свернута и в тоже время видима), тогда будет глюк с миганием в таскбаре вместо отображения окна формы.

Я все-таки за то, чтобы программа (в данном случае старая копия программы) сама отвечала за корректность отображения своих окон.


 
Alexander Panov ©   (2006-04-02 05:40) [95]

>Defunct ©   (02.04.06 04:23) [94]

С Broadcast еще одна проблема возникает - приложения в разных сессиях...


 
Leonid Troyanovsky ©   (2006-04-02 11:11) [96]


> Defunct ©   (02.04.06 04:23) [94]


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

Не можно, а нужно.

> Но тут мне кажется могут возникнуть трудности с show.. Imho
> не очень красиво получится, т.к. только что запущенная программа
> не знает в каком состоянии находится предыдущая копия (вдруг

Здесь, видимо, важно состояние не столько первой копии, как запускаемой.
Т.е., то, что юзер выбрал (в параметрах ярлыка, start & etc: развернутое
на весь экран, свернутое в значок и др.) задать первой копии.

--
Regards, LVT.



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

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

Наверх




Память: 0.82 MB
Время: 0.014 c
15-1145184216
x.pro
2006-04-16 14:43
2006.05.07
Проблема с драйверами?


15-1144912070
Layner
2006-04-13 11:07
2006.05.07
Можно ли написать ActiveX компонент, внедрить его в HTML,


3-1142481768
Ezorcist
2006-03-16 07:02
2006.05.07
BDE или ADO? Помогите определиться.


15-1144997405
syte_ser78
2006-04-14 10:50
2006.05.07
вопрос по работе со временем.


2-1145514777
dera
2006-04-20 10:32
2006.05.07
Как узнать целое число месяцев между двумя датами?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский