Запобігання запуску 2-x копій програми h2>
Відомо,
що Windows - багатозадачна система. Це звичайно добре. Але зворотною стороною
багатозадачності є те, що одночасно можна запустити кілька копій
однієї й тієї самої програми. Користувач може це зробити не спеціально, та й
друга копія програми може запуститися з-за помилки в програмі або ж самої
OC. Через клону можуть виникнути деякі проблеми, пов'язані з файловими
операціями, операціями з реєстром і т.п. Тому код пошуку та закриття
власної копії в програмі зовсім не зайвий. Є кілька методів
виконання знаходження копії. У цій статті я їх вам покажу. P>
Пошук головної форми (вікна) h2>
Щоб
знайти копію головного вікна можна скористатися функцією WinApi - FindWindow. У
як параметр цієї функції передається ім'я класу вікна, яке
використовувалося при реєстрації типу, визначально вікно форми або в системі
вікон (WndClass) і заголовка вікна. У Дельфі ім'я віконного класу WndClass
збігається з ім'ям класу форми в Object Pascal (наприклад TForm1). Функція
повертає 0, у випадку якщо вікна не існує, або дескриптор вікна, якщо вікно
існує. Основний код вашої програми повинен бути написаний так, що б
програма змогла запуститися, якщо результат функції FindWindow дорівнює нулю або
завершитися в зворотному випадку. Наступний приклад, якщо ви збираєтеся його
використовувати, потрібно вставити в dpr-файл проекту (меню Project - View Source). Приклад: p>
program Project1; p>
uses p>
Forms, p>
Unit1 in 'Unit1.pas' (Form1); p>
($ R *. res) p>
var p>
HWnd: THanlde; p>
begin p>
HWnd: = FindWindow ( 'TForm1', nil); p>
if HWnd 0 then p>
if not IsWindowVisible (HWnd) then p>
PostMessage (HWnd, wm_User, 0, 0); p>
SetForegroundWindow (HWnd) p>
else p>
begin p>
Application.Initialize; p>
Application.CreateForm (TForm1,
Form1); p>
// якщо
в програмі декілька форм, то створіть їх тут p>
// вручну, наприклад Application.CreateForm (TForm2, Form2) p>
Application.Run; p>
end; p>
end. p>
роз'ясню код
по рядках. У перших двох рядках я
оголосив змінну HWnd типу THandle для зберігання результату роботи функції.
Далі записую результат виконання функції FindWindow в змінну HWnd.
Потім порівнюю результат: якщо він не дорівнює нулю (тобто програма вже запущена і
даний екземпляр є копією) активізує головну форму запущеного
додатки. У зворотному випадку виконую операції з ініціалізації, створення форм
і запуску програми. p>
Однак
при використанні цього коду можуть виникнути деякі проблеми. Врахуйте, що
якщо ви запустите програму в той час, коли працює Дельфі з відкритим в ній
проектом запускається програми, то програма взагалі не запуститься. Це
пов'язано з тим, що в системі вже існує форма з сответствующім класом в
конструкторі Дельфі. Однак ви зможете запустити програму, якщо закриєте в
Дельфі файл юніта, пов'язаного з формою, і саму форму (або краще взагалі весь
проект). Якщо ж ви просто закриєте форму в конструкторі Дельфі, то вікно не
знищиться, а буде приховано і так само буде існувати в системі. Тому
вбудовувати цей код краще на етапі завершення роботи над програмою. p>
Використання мьютексом h2>
Mutex
- Це абревіатура для mutual exclusion (взаємне ісколюченіе). Це найбільш
традиційний підхід для середовища Win32. Взагалі мьютекс зазвичай використовують не для
знаходження копії програми, але цей об'єкт можна пристосувати і для цієї мети.
М'ютекс підтримується на рівні ОС і його специфіка така, що мьютекс з
заданим ім'ям може належати тільки одному додатку, або нікому. Після
того, як програма створила мьютекс, вона може перевірити, чи належить цей
об'єкт будь-якої програми. Для перевірки використовується функція WinApi --
WaitForSingleObject. Якщо в момент звернення до цієї функції мьютекс належить
кому небудь, то функція чекає певну кількість часу (передається в якості
параметра) до звільнення мьютекса (якщо мьютекс не буде звільнений то
функція поверне помилку з кодом wait_TimeOut). А якщо мьютекса не існує
(тобто основна програма не запущена), то програма стає власником
мьютекса. Реалізація такого підходу показано в наступному прикладі: p>
program Project1; p>
uses p>
Windows, p>
Forms, p>
Unit1 in 'Unit1.pas' (Form1); p>
($ R *. res) p>
var p>
hMutex: THandle; p>
begin p>
hMutex: = CreateMutex (nil, False,
'UniqueProgrammMutex'); p>
if WaitForSingleObject (hMutex, 0)
wait_TimeOut then p>
begin p>
Application.Initialize; p>
Application.CreateForm (TForm1,
Form1); p>
Application.Run; p>
end; p>
end. p>
Цей
метод є безумовно надійніше попереднього. Єдиний недолік цього
методу - це те, що при запуску копії програми головне вікно запущеного
додатки не активується, хоча це легко можна виправити шляхом пошуку
головного вікна у списку вікон або за допомогою описаної функції FindWindow. p>
Список літератури h2>
Для
підготовки даної роботи були використані матеріали з сайту http://www.soch.imperium.by
p>