Форум: "Прочее";
Текущий архив: 2006.10.29;
Скачать: [xml.tar.bz2];
ВнизПара вопросов Найти похожие ветки
← →
DelphiLamer © (2006-10-08 11:37) [0]Как замутить так,
чтобы приложение можно было запустить только в одной копии?
//////////////////////////////////////////////////////////////////////////
Как узнать версию(автора, описание ит.п.) exe или dll файла?
← →
ProgRAMmer Dimonych © (2006-10-08 12:15) [1]Из DelphiWorld:
program Project1;
uses
Forms,
Windows,
Unit1 in "Unit1.pas" {Form1};
{$R *.RES}
var
hwnd: THandle;
begin
hwnd := FindWindow("TForm1", "Form1");
if hwnd = 0 then
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end
else
SetForegroundWindow(hwnd)
end.
← →
Anatoly Podgoretsky © (2006-10-08 13:43) [2]Вопрос настолько популярный, ищи по ключевому слову Mutex или ко мне на сайт за FAQ
← →
Johnmen © (2006-10-08 13:56) [3]или по ключевому слову Semaphore
← →
Anatoly Podgoretsky © (2006-10-08 14:33) [4]Semaphore не для этой цели, а так конечно можно использовать большинство объектов ядра, но мьютекс самый прямой путь именно для этого и предназначен, два состояния есть/нет
← →
Ученик чародея © (2006-10-08 14:36) [5]
program xxx;
uses
oneruned in "oneruned.pas",
Forms,
...
-------------------------------------------------------------------
unit oneruned;
interface
implementation
uses
Windows;
var
Mutex : THandle;
MutexName : array[0..1024] of Char;
function StopLoading : boolean;
var
L,I : integer;
begin
// В качестве уникального имени мьютекса используем полный путь
// к исполняемому файлу приложения
L := GetModuleFileName(MainInstance,MutexName,SizeOf(MutexName));
// В имени мьютекса нельзя использовать обратные слэши, поэтому
// заменяем их на прямые
for I := 0 to L - 1 do
if MutexName[I] = "\" then
begin
MutexName[I] := "/";
end;
Mutex := CreateMutex(nil,false,MutexName);
Result := (Mutex = 0) or // Если мьютекс не удалось создать
(GetLastError = ERROR_ALREADY_EXISTS); // Если мьютекс уже существует
end;
initialization
if StopLoading then halt;
finalization
if Mutex <> 0 then
CloseHandle(Mutex);
end.
← →
Anatoly Podgoretsky © (2006-10-08 14:39) [6]У кода есть один недостаток, программа может быть запущена из разных папок, поэтому имя мьютекса должно быть предопределенное, работа программы не должна зависить от ее положения. Поэтому если выкинуть все до CreateMutex, то будет лучше.
← →
Anatoly Podgoretsky © (2006-10-08 14:40) [7]Видимо это был ленивый программист или не совсем интеллектуально развитый, который или не смог придумать имя или ему было лень.
← →
Percent (2006-10-08 14:46) [8]или ему было лень...
нажать Ctrl + Shift + G
← →
Eraser © (2006-10-08 14:47) [9]> [5] Ученик чародея © (08.10.06 14:36)
данный код можно использовать максимум на ОС Win2K, в XP может привести к ошибкам.Terminal Services: The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session name space. The remainder of the name can contain any character except the backslash character (\). For more information, see Kernel Object Namespaces.
(c) MSDN.
AFAIK по-умолчанию мьютекс создается в локальном пространстве имен терминальной сессии.
вот более правильный код.function GlobalCheck: Boolean;
var
pSD: PSECURITY_DESCRIPTOR;
sa: SECURITY_ATTRIBUTES;
begin
Result := true;
pSD := PSECURITY_DESCRIPTOR(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
if not InitializeSecurityDescriptor (pSD,
SECURITY_DESCRIPTOR_REVISION) then
begin
LocalFree(HLOCAL(pSD));
Exit;
end;
// Добавить NULL ACL к дескриптору безопасности.
if not SetSecurityDescriptorDacl(pSD, true, nil, false) then begin
LocalFree(HLOCAL(pSD));
Exit;
end;
sa.nLength := sizeof(sa);
sa.lpSecurityDescriptor := pSD;
sa.bInheritHandle := true;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
CreateMutex(@sa, True, "Global\ROMServerGlobal");
if GetLastError = ERROR_ALREADY_EXISTS then
begin
Result := false;
end;
end;
end;
← →
Eraser © (2006-10-08 14:53) [10]> [9] Eraser © (08.10.06 14:47)
точнее полный код выглядит так (чтобы работало на win9x/NT системах)CreateMutex(nil, True, "ROMServer");
if GetLastError = ERROR_ALREADY_EXISTS then
begin
MessageBox(0, PChar("Already EXISTS!"), SApplicationName, MB_ICONERROR);
Halt;
end;
if not GlobalCheck then
begin
MessageBox(0, PChar("Already EXISTS!"), SApplicationName, MB_ICONERROR);
Halt;
end;
← →
Внук © (2006-10-08 14:56) [11]>>Johnmen © (08.10.06 13:56) [3]
>>или по ключевому слову Semaphore
Или по ключевому слову "замутить"
← →
kaif © (2006-10-08 15:01) [12]А я вот делаю проще.
Просто отыскиваю класс или название главного окна моего приложения при помощи функции API FindWindow.
Это примитивно, но дубово. Нужно лишь назвать главное окно как-нибудь хитрее, чем просто "MainForm".
Разве так нельзя?
← →
Внук © (2006-10-08 15:02) [13]kaif © (08.10.06 15:01) [12]
Можно. Если окно уже успело создаться...
← →
Eraser © (2006-10-08 15:03) [14]> [12] kaif © (08.10.06 15:01)
> Разве так нельзя?
Можно. Более того, так удобнее, если нужно из второй копии передать, допустим, параметр командной строки в первую.
← →
kaif © (2006-10-08 15:25) [15]Внук © (08.10.06 15:02) [13]
kaif © (08.10.06 15:01) [12]
Можно. Если окно уже успело создаться...
Об этом я не подумал... Обычно юзер пытается создать второе окно, когда первое свернул и совершенно про него забыл (в моих задачах). То есть в моих задачах не произойдет особой катастрофы, если все же будет создано два окна одновременно.
Я как-то применял еще один способ - файл отображаемый в память. Правда не помню, как это делалось. возможно, второй способ надежнее. Но первый понятнее и удобнее в 99% случаев, ИМХО.
К тому же относительно использования GetModuleFileName или ParamStr(0) могу сказать следующее. А что, если вдруг юзер переименует EXE-файл приложения и запустит второй экземпляр таким способом?
Как-то недавно я изводил один вирус. Вирус делал вот что: при попытке запустить RegEdit, он закрывал его. Я просто переименовал файл RegEdit, спокойно его запустил и нашел путь к файлу вируса в реестре там, где свой автозапуск прописывают все трояны на свете. После чего я вышел из системы, загрузился во второй системе, удалил файл вируса, вернулся, запустил уже нормально RegEdit и удалил лишнюю запись из HK_LOCAL_MACHINE/Software/Microsowft/Windows/CurrentVersion/Run.
Если бы создатели вируса искали не процесс RegEdit, а имя класса окна RegEdit, мне пришлось бы дольше мучиться.
← →
VirEx © (2006-10-08 16:33) [16]program Project1;
uses
Forms,
Windows,
Unit1 in "Unit1.pas" {Form1};
{$R *.RES}
var
hwnd: THandle;const
txtMutex = "MYNAMEISBORISILIVEINTHEMOSCOW";
begin
if OpenMutex(MUTEX_ALL_ACCESS,false,txtMutex ) = 0 then begin
CreateMutex(nil,true,txtMutex);//устанавливаем мьютекс
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end.
← →
Anatoly Podgoretsky © (2006-10-08 18:23) [17]
> нажать Ctrl + Shift + G
Тоже лень
← →
Ученик чародея © (2006-10-08 18:36) [18]
> Anatoly Podgoretsky © (08.10.06 14:39) [6]
> У кода есть один недостаток, программа может быть запущена
> из разных папок, поэтому имя мьютекса должно быть предопределенное,
> работа программы не должна зависить от ее положения. Поэтому
> если выкинуть все до CreateMutex, то будет лучше.
Обычно, программы запускаемые из разных папок - разные программы. А запуск одиночного приложения реализуется в основном для того чтобы пользователь зажав мышку на иконке приложения не получил 10 одновременных запусков.
Этот код хорош тем, что его можно просто подключить к проекту и дальше не думать о проблеме.
← →
Anatoly Podgoretsky © (2006-10-08 18:40) [19]Не всегда условие обычности выполняется, пользователи быстро поймут, что можно обойти твое ограничение просто запустив из папки. Лучше предопределенное имя, например по Ctrl + Shift + G, тоже думать не нужно и ошибка исключена и код короче.
← →
vidiv © (2006-10-08 19:04) [20]
> program Project1;
>
> uses
> Forms,
> Windows,
> Unit1 in "Unit1.pas" {Form1};
>
> {$R *.RES}
>
> var
> hwnd: THandle;
>
> const
> txtMutex = "MYNAMEISBORISILIVEINTHEMOSCOW";
>
> begin
> if OpenMutex(MUTEX_ALL_ACCESS,false,txtMutex ) = 0 then
> begin
> CreateMutex(nil,true,txtMutex);//устанавливаем мьютекс
> Application.Initialize;
> Application.CreateForm(TForm1, Form1);
> Application.Run;
> end;
> end.
И все же данный код не дает 100% гарантию. Шанс что будет запущенно два приложения все же остается :)
← →
Marser © (2006-10-08 19:06) [21]> [3] Johnmen © (08.10.06 13:56)
> или по ключевому слову Semaphore
Семафор, надо полагать, нужен, если копий может быть две, три, четыре... но не больше N.
← →
Anatoly Podgoretsky © (2006-10-08 19:08) [22]
> И все же данный код не дает 100% гарантию. Шанс что будет
> запущенно два приложения все же остается :)
Зато вот этот дастMutex := CreateMutex(nil,false,MutexName);
Result := (Mutex = 0) or // Если мьютекс не удалось создать
(GetLastError = ERROR_ALREADY_EXISTS); // Если мьютекс уже существует
← →
Anatoly Podgoretsky © (2006-10-08 19:10) [23]
> Семафор, надо полагать, нужен, если копий может быть две,
> три, четыре... но не больше N.
Да семафор это счетчик
← →
Loginov Dmitry © (2006-10-08 19:17) [24]Обычно так делаю:
program Project1;
uses
Windows;
.........
begin
CreateMutex(nil, False, "[{395DFCF9-4421-44AE-9090-41ED6827F034}]");
if GetLastError = ERROR_ALREADY_EXISTS then Halt;
.....
end.
Гарантия - процентов 99, но пока ни разу не подводило :)
← →
Anatoly Podgoretsky © (2006-10-08 19:19) [25]А на что отводишь один процент, вроде шансов нет. Это объект ядра и создаются они только последовательно.
← →
Пусик © (2006-10-08 19:23) [26]
> Anatoly Podgoretsky © (08.10.06 19:19) [25]
> А на что отводишь один процент, вроде шансов нет. Это объект
> ядра и создаются они только последовательно.
Наверное, один процент - это вероятность запуска в терминальной сессии...
← →
Anatoly Podgoretsky © (2006-10-08 19:31) [27]Ну и что, каждый терминальный пользователь имеет право запустить программу, сессии изолированы. Представь, если бы только первый пользователь имел право запустить Ворд.
← →
Пусик © (2006-10-08 19:33) [28]
> Anatoly Podgoretsky © (08.10.06 19:31) [27]
> Ну и что, каждый терминальный пользователь имеет право запустить
> программу, сессии изолированы.
В том случае, если программой это предусмотрено.
← →
Loginov Dmitry © (2006-10-08 19:36) [29]Anatoly Podgoretsky © (08.10.06 19:19) [25]
А на что отводишь один процент
А один процент - это когда пофиг - запустится ли прога или нет. Например мы на работе пишем софт, вероятность запуска которого - 90 %. По каким причинам оставшиеся 10 % - не известно!
... Куда-то не в то русло ушел. Короче 1% отвожу на "военное время" :)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2006.10.29;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.06 c