Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Вниз

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

 
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...



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

Форум: "Основная";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.6 MB
Время: 0.011 c
10-1118159389
F1
2005-06-07 19:49
2006.05.07
Word, OLE/COM


2-1145442756
@gent
2006-04-19 14:32
2006.05.07
Как мне выводить в Memo не только ответ, но и решение


15-1144992492
ANB
2006-04-14 09:28
2006.05.07
Какое число дает ошибку при математическом округлении ?


15-1144403066
Таня
2006-04-07 13:44
2006.05.07
Трудная задача по Информатике


15-1145187539
Константин Артемьев
2006-04-16 15:38
2006.05.07
Заказ на небольшую Delphi программу





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский