PDA

View Full Version : خارج کردن یک برنامه اجرایی از حافظه



Mahdavi
چهارشنبه 28 آبان 1382, 14:04 عصر
با سلام
برنامه دارم که میخوام در صورت اجرای اون اگه قبلا نسخه ای از اون اجرا شده نسخه قبلی خارج بشه.
بعبارت دیگه هندل مربوط به فایل اجراییمو از کجا پیدا کنم ؟؟؟

houshmand
چهارشنبه 28 آبان 1382, 14:12 عصر
1-این قبلاٌ چندین بار گفته شده است و به روشهای دیگر
2-با findwindow می توانی پیدا کنی

Mahdavi
چهارشنبه 28 آبان 1382, 14:31 عصر
دوست عزیز
اگه توجه کرده باشید findwindow یک هندل میخواد نام اون پنجره.
منم دنبال بدست اوردن این هندلم چراکه نه تنها با findwindow بلکه با چند روش دیگه هم میشه برنامه اجرایی را از حافظه خارج کرد.
حتی مثالی هم برای excel دارم ولی برای برنامه خودم میخوام :lol:

SReza1
پنج شنبه 29 آبان 1382, 18:56 عصر
دوست عزیز یه جستجوی ساده میتونی این topic رو پیدا کنی!!
از طریق findwindow میشه!! و کلی توضیح هم داده شده!

Kambiz
پنج شنبه 29 آبان 1382, 20:57 عصر
استفاده از FindWindow روش صحیحی نیست چون احتمال اینکه دو تا برنامه مختلف دارای پنجره هم نام باشند زیاد هست. بجای استفاده از عنوان پنجره بهتره از نام فایل اجرایی استفاده کنیم که احتمال مشابه بودنش با یک برنامه دیگه کمتره.

uses
TLHelp32;

function FindExecutableProcessID(const ExeFileName: String): DWORD;
var
Snapshot: THandle;
ProcessEntry32: TPROCESSENTRY32;
begin
Result := 0;
Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
try
if Snapshot <> 0 then
begin
ProcessEntry32.dwSize := SizeOf(TPROCESSENTRY32);
if Process32First(Snapshot, ProcessEntry32) then
repeat
if StrIComp(PChar(ExeFileName), ProcessEntry32.szExeFile) = 0 then
Result := ProcessEntry32.th32ProcessID;
until (Result <> 0) or not Process32Next(Snapshot, ProcessEntry32);
end;
finally
CloseHandle(Snapshot);
end;
end;

function TerminateProcessID(ProcessID: DWORD; ExitCode: DWORD): Boolean;
var
ProcessHandle: THandle;
begin
Result := False;
ProcessHandle := OpenProcess(PROCESS_TERMINATE, False, ProcessID);
if ProcessHandle <> 0 then
try
Result := TerminateProcess(ProcessHandle, ExitCode);
finally
CloseHandle(ProcessHandle);
end;
end;

type
TTerminateAppRes = (tarSucceeded, tarNotRunning, tarFailed);

function TerminateApp(const ExeFileName: String; ExitCode: DWORD): TTerminateAppRes;
var
ProcessID: DWORD;
begin
ProcessID := FindExecutableProcessID(ExeFileName);
if ProcessID <> 0 then
if TerminateProcessID(ProcessID, ExitCode) then
Result := tarSucceeded
else
Result := tarFailed
else
Result := tarNotRunning;
end;
به عنوان نمونه اجرای کد زیر باعث می‌شه که یک نسخه از برنامه NotePad در حال اجرا بسته بشه:

procedure TForm1.Button1Click(Sender: TObject);
begin
case TerminateApp('notepad.exe', 0) of
tarSucceeded:
ShowMessage('The application terminated succesfully');
tarNotRunning:
ShowMessage('The application is not running');
else
ShowMessage('Failed to terminate the application');
end;
end;
اگر بخوایم تمام نسخه‌های NotePad رو ببندیم کد بالا رو باید اینجوری بنویسیم:

procedure TForm1.Button2Click(Sender: TObject);
begin
while TerminateApp('notepad.exe', 0) = tarSucceeded do
Sleep(0);
end;

Mahdavi
جمعه 30 آبان 1382, 12:10 عصر
با سلام
ممنون از راهنمایی تمام دوستان

Inprise
شنبه 01 آذر 1382, 18:14 عصر
استفاده از FindWindow روش صحیحی نیست چون احتمال اینکه دو تا برنامه مختلف دارای پنجره هم نام باشند زیاد هست. بجای استفاده از عنوان پنجره بهتره از نام فایل اجرایی استفاده کنیم که احتمال مشابه بودنش با یک برنامه دیگه کمتره.

من تصور میکنم احتمال وجود دو یا چند برنامه با نام پنجره یکسان با احتمال وجود دو یا چند برنامه با نام فایل اجرائی یکسان قابل مقایسه اند . لذا بهتر است از روشهای دیگر استفاده شود :


هنگام شروع هر برنامه یک موتکس با نام انحصاری ایجاد کنید . هنگام اجرای نسخه دوم برنامه ، برنامه قبل از اجرا چک میکند که آیا موتکسی با نام انحصاری خاص شما ( که اینجا دیگه تکراری بودنش تقریبا غیر ممکنه ) وجود داره یا خیر . اگر تابع ویندوزی CreateMutex نتوانست یک موتکس بسازد یعنی برنامه شما قبلا اجرا شده است .


program Project1;

uses
Forms, Windows,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
var
Mutex : THandle;
begin
Mutex := CreateMutex(nil, True, 'My_Unique_Application_Mutex_Name');
if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then
begin

// کدهای لازم برای پیدا کردن نسخه قبلی و بستن آنرا اینجا بنویسید

end
else
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
if Mutex <> 0 then
CloseHandle(Mutex);
end;
end;
end.


پیدا کردن نسخه قبلی با این شرط که "میدانیم نسخه قبلی وجود دارد" : ( این عبارت و روش با " پیدا کردن نسخه قبلی" خیلی فرق داره !! )


این به نظر من بهترین کد است :



function LookForPreviousInstance
(Handle : THandle; Param : Cardinal): boolean; stdcall;
var
buf : array[0..255] of char;
WindowModuleName : string;
WindowClassName : string;
wih : THandle; //هندل پنجره
begin
Result := True;

GetClassName(Handle, buf, SizeOf(buf));
WindowClassName := buf;

//بررسی برابری نام پنجره ها
if WindowClassName = TForm1.ClassName then
begin
wih := GetWindowLong(Handle, GWL_HINSTANCE),

GetModuleFileName(wih, buf, SizeOf(buf));
WindowModuleName := buf;

//بررسی برابری نام برنامه های تولید کننده پنجره های فوق الذکر
if WindowModuleName = ThisModuleName then
begin
FoundIt := True;
FoundHandle := Handle;

Result := False;
end;
end;
end;


موفق باشید

Inprise
شنبه 01 آذر 1382, 18:15 عصر
BUG : گویا تو قسمت محصور به تک Code نمیشه فارسی نوشت :roll:

Mahdavi
شنبه 01 آذر 1382, 22:49 عصر
با سلام و تشکر از همه دوستان
مشکل من حل شد :lol: