PDA

View Full Version : سوال: تشخیص Suspend شدن یک پروسه.



Mask
شنبه 21 اسفند 1389, 22:56 عصر
با سلام.
یه برنامه جانبی دارم که من ننوشتم.
از دوستان سوال کردم که چطوری باید تشخیص بدم که پروسه این برنامه Suspend شده.
زحمت کشیدند و یه راه حلهایی رو فرمودند.
یکی اینکه یه مسیج برا اون برنامه بفرستیم و Flag تردش رو بگیریم. اگه جواب داد یعنی فعاله و در غیر این صورت یعنی Suspend شده.
آیا این روش صحیحه و چطوری باید پیاده سازیش کنیم.
ممنون میشم اگه با کد دوستان توضیح بدهند.

Felony
یک شنبه 22 اسفند 1389, 09:40 صبح
دیروز پشت تلفن من درست متوجه نشدم چی میگی ، کی بهت همچین پیشنهادی داده ؟!

3 تا راه داری :

1- از تابع WaitForSingleObject استفاده کنی و هندل Thread برنامه رو همراه با یک زمان Timeout بهش بدی ، اگر در زمان تعیین شده ترد پاسخی نده تابع مقدار WAIT_ABANDONED رو برگشت میده .

2- میتونی با تابع SuspendThread ترد رو Suspend کنی اگر تابع کارش رو درست انجام بده مقداری به جز 0 برمیگردوه و معلوم میشه Thread متوقف نبوده که تونسته به درخواست شما جواب بده ، بلافاصله بعد از این کار با تابع ResumeThread ترد رو با حالت اولیه بر میگردونید ، اگر هم 0 برگردوند یعنی Suspend بوده و نتونسته به درخواست شما پاسخ بده .

3- دیروز برات توضیح دادم ...

Felony
یک شنبه 22 اسفند 1389, 15:26 عصر
به نظرم استفاده از WaitForSingleObject بهترین گزینه باشه .

Mask
یک شنبه 22 اسفند 1389, 15:49 عصر
ممنون
کد زیر رو ببین:

var h:THandle;
begin
h:=Handle;
if WaitForSingleObject(H,1000) <> wait_timeout then
BEGIN
ShowMessage('yes');
end else
begin
ShowMessage('No');
end;
چطوری هندل برنامه مورد نظر رو بدم.؟؟؟؟؟؟؟؟؟؟

Felony
یک شنبه 22 اسفند 1389, 16:13 عصر
ممنون
کد زیر رو ببین:

var h:THandle;
begin
h:=Handle;
if WaitForSingleObject(H,1000) <> wait_timeout then
BEGIN
ShowMessage('yes');
end else
begin
ShowMessage('No');
end;
چطوری هندل برنامه مورد نظر رو بدم.؟؟؟؟؟؟؟؟؟؟
باید هندل Main Thread برنامه مورد نظر رو به دست بیاری و بهش پاس بدی ، یه نگاهی به کامپوننت ProcessInfo بنداز ، البته خودت هم میتونی به دست بیاریش ( OpenThread )

Mask
یک شنبه 22 اسفند 1389, 17:56 عصر
با سلام
من با ProcessInfo هندل برنامه اول رو میگیرم. بعد دستی وارد برنامه دوم میکنم.
با اینکه برنامه اول رو Suspend کردم اما بازم برنامه من نشون میده که ترد در حال اجراست.
آقا مجتبی دارم کچل میشم:خجالت::لبخند:
کد استفاده شده در برنامه دوم:

var h:THandle;
begin
h:=StrToInt(Edit1.Text);
if WaitForSingleObject(H,3000) <> wait_timeout then
BEGIN
ShowMessage('Yes');
end else
begin
ShowMessage('No');
end;
و نمونه برنامه ای هم که هندل خودش رو بدست میاره ضمیمه کردم.

lord_viper
یک شنبه 22 اسفند 1389, 18:18 عصر
با استفاده از تابع NtQuerySystemInformation و Thread_Information که مقدار State اون suspend بودن رو مشخص میکنه



SYSTEM_THREAD = packed record
KernelTime: LARGE_INTEGER;
UserTime: LARGE_INTEGER;
CreateTime: LARGE_INTEGER;
WaitTime: DWORD;
StartAddress: DWORD; // starting address of the thread
UniqueProcess: DWORD; // process ID (PID)
UniqueThread: DWORD; // thread ID (TID)
Priority: integer; // current priority
BasePriority: DWORD; // initial priority
ContextSwitchCount: DWORD;
State: integer; // thead state: active (<5), waiting (5)
WaitReason: integer; // waiting reason (5 = suspended)
Reserved1:DWORD;
end;

vcldeveloper
یک شنبه 22 اسفند 1389, 22:52 عصر
WaitForSingleObject برای بررسی Suspend بودن یک Thread کمک خاصی بهتون نمیکنه؛ می تونید از همون تابع SuspendThread استفاده کنید و مقدار خروجی اش را بررسی کنید.

tdkhakpur
دوشنبه 23 اسفند 1389, 00:30 صبح
استفاده از SuspendThread کار مناسبی نیست چون ممکنه با این کار آخرین شمارنده برای توقف ضروری ترد رو افزایش بدید و خود برنامه اصلی هم نتونه کار خودش رو به درستی انجام بده.
ولی در مورد اینکه نتیجه SuspendThread میتونه مشخص کنه که ترد میتونه پاسخ مثبت بده یا نه تقریبا نتیجه اتفاقی رو میتونه در بر داشته باشه.


به نظرم استفاده از WaitForSingleObject بهترین گزینه باشه .

هر شی بدون اجبار نباید با متد فوق جواب بگیره برای استفاده و پاسخ به WaitForSingleObject باید توسط CreateEvent رویداد ساخته بشه.


باید هندل Main Thread برنامه مورد نظر رو به دست بیاری و بهش پاس بدی ، یه نگاهی به کامپوننت ProcessInfo بنداز

اون هندلی که WaitForSingleObject لازم داره هندل ترد نیست هندل یک رویداده که باید تعریف بشه.

Felony
دوشنبه 23 اسفند 1389, 06:06 صبح
WaitForSingleObject برای بررسی Suspend بودن یک Thread کمک خاصی بهتون نمیکنه؛ می تونید از همون تابع SuspendThread استفاده کنید و مقدار خروجی اش را بررسی کنید.
اون مورد WaitForSingleObject (http://msdn.microsoft.com/en-us/library/ms687032(v=vs.85).aspx) رو تو انجمن های مایکروسافت پیشنهاد داده بودند و در ضمن تو راهنما MSDN در مورد این تابع آورده شده :


The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters the wait state until the object is signaled or the time-out interval elapses.

The WaitForSingleObject function can wait for the following objects:
Change notification
Console input
Event
Memory resource notification
Mutex
Process
Semaphore
Thread
Waitable timer

یعنی این تابع میتونه برای بررسی یک Thread هم استفاده بشه ، البته تو همون راهنما گفته شده ترد فراخوان باید دسترسی این کار رو داشته باشه ، آیا من اشتباه متوجه شدم ؟

Mask
دوشنبه 23 اسفند 1389, 16:41 عصر
میشه بیشتر توضیح بدید.

استفاده از SuspendThread کار مناسبی نیست چون ممکنه با این کار آخرین شمارنده برای توقف ضروری ترد رو افزایش بدید و خود برنامه اصلی هم نتونه کار خودش رو به درستی انجام بده.
ولی در مورد اینکه نتیجه SuspendThread میتونه مشخص کنه که ترد میتونه پاسخ مثبت بده یا نه تقریبا نتیجه اتفاقی رو میتونه در بر داشته باشه.

Felony
دوشنبه 23 اسفند 1389, 17:20 عصر
یک راه دیگه به ذهنم رسید و تست کردم و جواب هم داد ، میتونید با تابع SendMessageTimeout یک پیغام به پنجره برنامه مورد نظر بفرستید ، همونطور که میدونید تابع SendMessage تا زمان پردازش نشدن پیغام ارسالی در برنامه مقصد منتظر پردازش میمونه ، تابع SendMessageTimout همین کار رو با مدت زمان تعیین شده میکنه یعنی اگر شما زمان Timeout رو 10 میلی ثانیه قرار دادی اگر تابع SendMessage بعد از ارسال پیغام تا 10 میلی ثانیه بعد جوابی دریافت نکرد Timeout میده ، بنابراین اگر ترد برنامه مقصد Suspend باشه نمیتونه پیغام ارسالی رو پردازش کنه و تابع Timeout میده و شما میتونی متوجه Suspend شدن Thread بشی :

var
Handle, Result: Cardinal;
begin
Handle:= FindWindow('TForm1', 'Form1');
SendMessageTimeout(Handle, WM_Null, 0, 0, 0, 10, Result);
if Result= 0 then
ShowMessage('Runned')
else
ShowMessage('Suspended !');
end;

Mask
دوشنبه 23 اسفند 1389, 17:43 عصر
ممنون از وقتی که گزاشتی.
اما به من جواب نداد. همش اعلام میکنه Runned.

Felony
دوشنبه 23 اسفند 1389, 18:10 عصر
مطمئن هستید Main Thread برنامه Suspend هست ؟ زمان مربوط به Timeout رو کاهش بدید .

Mask
دوشنبه 23 اسفند 1389, 18:57 عصر
نمونه برنامه ها رو نگاه کنید.(حتی اگه برنامه ای هم در حال اجرا نباشه نشون میده که اجراست)

vcldeveloper
دوشنبه 23 اسفند 1389, 18:57 عصر
استفاده از SuspendThread کار مناسبی نیست چون ممکنه با این کار آخرین شمارنده برای توقف ضروری ترد رو افزایش بدید و خود برنامه اصلی هم نتونه کار خودش رو به درستی انجام بده.
ولی در مورد اینکه نتیجه SuspendThread میتونه مشخص کنه که ترد میتونه پاسخ مثبت بده یا نه تقریبا نتیجه اتفاقی رو میتونه در بر داشته باشه.
SuspendThread در هیچ جایی به جز debugger استفاده نداره، پس نیازی نیست که برنامه چک کننده نگران این موضوع باشه. SuspendThread و ResumeThread توابع مربوط به debugger ها در ویندوز هستند، نه توابع مربوط به کنترل عادی جریان برنامه.


هر شی بدون اجبار نباید با متد فوق جواب بگیره برای استفاده و پاسخ به WaitForSingleObject باید توسط CreateEvent رویداد ساخته بشه.

اون هندلی که WaitForSingleObject لازم داره هندل ترد نیست هندل یک رویداده که باید تعریف بشه.
همچین چیزی صحیح نیست؛ WaitForSingleObject با هر Object ایی که امکان Synchronize شدن داشته باشه، کار میکنه. Process ها و Thread ها هم یکی از این نوع Object ها هستند.



اون مورد WaitForSingleObject (http://msdn.microsoft.com/en-us/library/ms687032%28v=vs.85%29.aspx) رو تو انجمن های مایکروسافت پیشنهاد داده بودند و در ضمن تو راهنما MSDN در مورد این تابع آورده شده
گفته وضعیت Signaled بودن یا non-signaled بودن یک object رو چک میکنه، اما نگفته که آیا suspend شدن یک thread رو به عنوان Non-signaled در نظر میگیره یا نه، که در عمل نمیگیره.

Felony
دوشنبه 23 اسفند 1389, 21:43 عصر
نمونه برنامه ها رو نگاه کنید.(حتی اگه برنامه ای هم در حال اجرا نباشه نشون میده که اجراست)
اخوی شما هم کارهایی میکنی ها ... !

با این فایل های exe خوب من از کجا بدونم چی نوشتی و اشکال کجاست ؟ در ضمن برنامه دوم که چکش میکنی چه طور Suspend میشه ؟

tdkhakpur
دوشنبه 23 اسفند 1389, 23:28 عصر
همچین چیزی صحیح نیست؛ WaitForSingleObject با هر Object ایی که امکان Synchronize شدن داشته باشه، کار میکنه. Process ها و Thread ها هم یکی از این نوع Object ها هستند.


به دردم نخورده امتحانش کنم ولی به نظرم فقط برای Terminate جواب میده نه suspend یا هر enevt دیگه. به همین دلیل باید هندل event ساخته بشه .


Thread The CreateProcess, CreateThread, or CreateRemoteThread function returns the handle. A thread object's state is signaled when the thread terminates.

Mask
سه شنبه 24 اسفند 1389, 14:47 عصر
اخوی شما هم کارهایی میکنی ها ... !

با این فایل های exe خوب من از کجا بدونم چی نوشتی و اشکال کجاست ؟ در ضمن برنامه دوم که چکش میکنی چه طور Suspend میشه ؟
شرمنده حق با شماست...
در ضمن برنامه تستی رو با Process Explorert ساسپند میکنم.

Felony
سه شنبه 24 اسفند 1389, 16:49 عصر
شرمنده حق با شماست...
در ضمن برنامه تستی رو با Process Explorert ساسپند میکنم.
من تست کردم وقتی از SendMessageTimeout استفاده میکنی یک بار Suspended میده و یک بار Runned و این کار هم تکرار میشه و ترتیبش هم مشخص نیست یعنی بسته به زمان Timeout ممکنه برنامه به پیغام رسیده شده جواب بده ، تنها چیزی که به ذهنم میرسه این هست که از خروجی این تابع چند بار پشت سر هم نمونه گیری کنیم و در آخر کار نتیجه رو بررسی کنیم ، من یه کد نوشتم و تست کردم و این بار مشکل قبلی رو نداشت و خیلی راحت وضعیت برنامه رو مشخص کرد :

var
Result, Time: Dword;
Retval: LongInt;
Timeout, i, Count: Byte;
Hand: THandle;
begin
Hand:= FindWindow('TForm1', 'TestAPP');
if Hand<> 0 then
begin
Timeout:= 10;
Count:= 0;
for i:= 0 to 10 do
begin
Time:= GetTickCount;
Retval:= SendMessageTimeout(Hand, WM_NULL, 0, 0, SMTO_ABORTIFHUNG or SMTO_BLOCK, Timeout, Result);
Time:= GetTickCount - Time;
if Retval= 0 then
if Time < Timeout then
Inc(Count)
else
Dec(Count);
end;
if Count <= 5 then
ShowMessage('Runned')
else
ShowMessage('Suspended');
end else
ShowMessage('Can not find window ! ');
end;

تست کنید اگر باز هم مشکلی بود خبر بدید .

Mask
سه شنبه 24 اسفند 1389, 17:12 عصر
ممنون.
واقع تشکر . خیلی جالب بود.
فقط یه مشکل کوچیک دیگه میمونه. برنامه اصلی که میخام متوجه Suspend شدنش بشم دارای 4 تا ترد هست.
اما این کد فقط Suspend شدن ترد اصلی رو متوجه میشه.
البته دارم روش کار میکنم خودمم.
بازم ممنون.

vcldeveloper
سه شنبه 24 اسفند 1389, 19:07 عصر
فقط یه مشکل کوچیک دیگه میمونه. برنامه اصلی که میخام متوجه Suspend شدنش بشم دارای 4 تا ترد هست.
اما این کد فقط Suspend شدن ترد اصلی رو متوجه میشه.
دریافتپیام فقط برای Thread های دارای Message Loop امکان پذیر هست. اگر سایر Threadها این رو نداشته باشند (که معمولا ندارند)، نمی تونید براشون پیام بفرستید.

Felony
سه شنبه 24 اسفند 1389, 20:50 عصر
ممنون.
واقع تشکر . خیلی جالب بود.
فقط یه مشکل کوچیک دیگه میمونه. برنامه اصلی که میخام متوجه Suspend شدنش بشم دارای 4 تا ترد هست.
اما این کد فقط Suspend شدن ترد اصلی رو متوجه میشه.
البته دارم روش کار میکنم خودمم.
بازم ممنون.
ساده ترین راهی که باقی میمونه تابع SuspendThread و ResumeThread هست که قبلا توضیح دادم .