PDA

View Full Version : اجرای برنامه فقط یکبار



A_Salimi
شنبه 25 اسفند 1386, 16:06 عصر
سلام دوستان

اگه برنامه ای در محیط ویندوز اجرا شده چطور میشه از اجرای مجدد اون جلوگیری کرد (مثلا برنامه ای که با vc ساخته شده ) و اجرا شده و در لیست prosess های ویندوز قرار داره چطور میشه از ایجاد همون برنامه در بار دوم جلوگیری کرد ؟(مثل jetAudio )

آیا یک تابع API وجود داره ؟

با تشکر

Nima_NF
شنبه 25 اسفند 1386, 17:02 عصر
شما می توانید یک تابع با استفاده از FindWindow بنویسید و امتحان کنید که آیا از میان برنامه های اجرا شده ، برنامه ای با className ساخته شده قبلی شما وجود دارد یا خیر.

مثلا تابع زیر در صورتی hwnd را غیر صفر برگرداند نشاندهنده این است که چنین پنجره ای قبلا وجود دارد (قبلا اجرا شده است) و شما تها کاری که باید انجام دهید این است که return 0 را برگردانید تا برنامه جدید کارش را فورا تمام کند (یعنی اصلا اجرا را ادامه ندهد)،
ضمنا کد زیر به win32 هست که می توانید به راحتی با معادل MFC آن ها جایگزین کنید:



HWND GetRunningWin ()
{
HWND hwnd = ::FindWindow ( your_ClassName , 0);

if (::IsWindow (hwnd))
{
HWND hwndP = ::GetLastActivePopup (hwnd);

if (::IsWindow (hwndP))
hwnd = hwndP;
}
else
hwnd = 0;

return hwnd;
}

موفق باشید

A_Salimi
شنبه 25 اسفند 1386, 20:34 عصر
ممنونم

خوب منظورتون اینه که باید در ابتدای اجرای برنامه مقدار بازگشتی از تابع رو چک کنم و اگه صفر بود که برنامه اجرا شه و در غیر اینصورت نه . . .

خوب این چک کردن تو کجا باید بررسی شه ؟





if(GetRunningWin()==0)
.
.
.

Nima_NF
شنبه 25 اسفند 1386, 22:49 عصر
فقط شما در MFC حتما باید نامی دلخواه برای lpszClass برنامه یا دیالوگ خودتان تعریف کنید و بهترین مکان هم برای فراخوانی تابعی که در پست قبل گذاشتم بلافاصله در ابتدای InitInstance هست تا برنامه شما اصلا ایجاد و نمایش داده نشود.

لینک زیر هم نمونه MFC آن را نشان می دهد:

http://www.developerfusion.co.uk/show/1716/5/

BitMap
یک شنبه 26 اسفند 1386, 06:29 صبح
می تونی از ریجستری استفاده کنی
و اگر می خواهی فقط یبکبار در هنگام بالا آمدن ویندوز اجرا بشه یک کلید مخصوص اگر اشتباه نکنم با نام RunOnce برای این کار وجود داره

A_Salimi
یک شنبه 26 اسفند 1386, 14:45 عصر
کار کردن با توابع API ویندوز در هر حال نیازمند داشتن تجربه هستش

چند تا سوال دارم :
تابع InitInstance چه کاری رو در برنامه انجام میده ؟

و دوم اینکه چه قسمتهایی از برنامه پس از اطمینان از صفر بودن مقدار برگشتی تابع بایستی اجرا شوند ؟ یعنی یه جورایی نقطه شروع اجرای هر برنامه کجاست تا بواسطه اون از اجرای بقیه برنامه جلوگیری شه ؟
من نمیدونم بعد از بررسی صفر بودن مقدار برگشتی توابع به چه کدهایی اجازه اجرا بدم ؟

دوستمون bitmap هم به استفاده از رجیستری اشاره کردند که این هم جالب به نظر میرسه البته من نمیدونم که آیا با اجرای هر برنامه کلیدی در رجیستری ایجاد میشه که بخواهیم با بررسی وضعیت اون از اجرای دوباره برنامه جلوگیری کنیم یا نه ؟

BitMap
یک شنبه 26 اسفند 1386, 17:53 عصر
وقتی برناه بالا آمد وجود یک کلید رو بررسی می کنی ، اگر قبلا وجود داست برنامه بسته میشه وگرنه ان کلید ایجاد میشه و اجرای برنامه ادامه پیدا میکنه

A_Salimi
یک شنبه 26 اسفند 1386, 23:35 عصر
من احساس میکنم که نتونستم نظرمو به درستی منتقل کنم

حرف حساب من اینه : توی یک برنامه mfc اول چه کدهایی اجرا میشن ؟آیا از OnInitDialog کدها شروع به اجرا میکنن فرضا شما می خواهید در یک برنامه مبتنی بر کادر تبادلی یه کاری کنید که برنامه اجرا نشه و با run کردن برنامه بدون هیج خطایی فقط برنامه اجرا نشه !!!!
فرض میکنم من یک متغیر عمومی به این صورت تعریف میکنم :



Int x=1;

حالا میخوام یه جورایی برنامه اجرا نشه پس در ادامه اینطوری مینویسم :




If(x==2)
{
کدهایی که باعث اجرا برنامه میشوند
}

این کدها چی هستند ؟ شاید هم منظورتون اینه که بعد از اجرای برنامه اون رو ببندم مثلا از EndDialog استفاده کنم ؟

واقعا من یکی نمیدونم:افسرده: لطفا راهنمایی بدید

Nima_NF
یک شنبه 26 اسفند 1386, 23:38 عصر
راحت ترین و رایج ترین روش را به شمامعرفی کردم ، لینک پیاده شده به MFC را که در پست قبل گذاشتم مشاهد کردید؟

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

اصلا چیز پیچیده ای نیست ، اگر برنامه شما با نام کلاسی که قبلا تعریف کرده اید در حالت اجرا وجود داشته باشد باید جلوی ادامه برنامه جدید را بگیرید ؛ بهترین مکان در مرحله ای است که پنجره جدید شما هنوز ساخته نشده باشد یا به عبارت دیگر در اولین مکان ممکن. (حال یا با برگرداندن یک مقدار False یا خودتان با استفاده از دستورات بستن برنامه جلوی اجرای مجدد را می گیرید)

در InitInstance همه مقدار دهی های اولیه برنامه شما قبل از ایجاد و نمایش آن می تواند انجام شود ، لذا بهترین مکان برای همین امر می باشد. اگر هم برنامه دیالوگی هست در همان OnInitDialog یا هر جای ممکن قبل از آن.

A_Salimi
دوشنبه 27 اسفند 1386, 15:46 عصر
من نمیدونم چرا کدی رو که شما دادید همیشه صفر رو بر می گردونه یعنی نمیدونم چرا هیچوقت حتی با اینکه اون برنامه در بار دوم هم اجرا میشه در if اول اجرا نمیشه !!! (در مد دیباگ دیدم)

من کاری رو که میخواستم رو با فایلها انجام دادم اما با استفاده از FindWindow نتونستم جواب بگیرم در اون لینکی هم که دادید (من یکی که خوب متوجه نشدم چون فکر میکنم مربوط به پروژه های چند سندی میشد)

در هر حال میشه بگید اشتباه من کجاست ؟ من به این صورت عمل میکنم :
بعد از تعاریف header ها دو متغیر عمومی hwnd و hwnd1 رو به صورت زیر تعریف میکنم :



HWND hwnd,hwnd1;

در ادامه :





HWND GetRunningWin()
{
LPCTSTR lpszUniqueClass = _T("test");
HWND hwnd = ::FindWindow (lpszUniqueClass ,0);
if (::IsWindow (hwnd))
{
HWND hwndP = ::GetLastActivePopup (hwnd);
if (::IsWindow (hwndP))
hwnd = hwndP;
return hwnd;
}
else
return hwnd1;
}


و در ادامه در OnInitDialog() به این صورت :





if(GetRunningWin()==hwnd)
EndDialog(IDD_TEST_DIALOG);




در تئوری که همه چیز درست به نظر میاد اما در عمل نه : انتظار میره در اجرای اولیه برنامه چون هنوز پنجره ای باز نیست مقدار hwnd1 برگردونده شه و خط بعد از if اجرا نشه (که همینطور هم هست ) اما در اجراهای بعدی باز هم hwnd1 برگردونده میشه

amir_civil
دوشنبه 27 اسفند 1386, 16:57 عصر
بهترین کار:


HANDLE WINAPI CreateMutex(
__in LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in LPCTSTR lpName
);

A_Salimi
دوشنبه 27 اسفند 1386, 18:46 عصر
خوب این چیزایی که نوشتید مفهومش چیه ؟ یه توضیح مختصر لطفا بدید . . .

ممنونتون میشم

amir_civil
دوشنبه 27 اسفند 1386, 22:51 عصر
اگر برنامه هندل مورد نظر رو نداد وبا شکست مواجه شد یعنی اینکه برنامه در حال اجراست msdn رو ببین

Nima_NF
دوشنبه 27 اسفند 1386, 23:10 عصر
مراحل را کامل انجام ندادید ، تا وقتی توابع MFC را دارید از Win32 استفاده نکنید !
نام کلاس را برای برنامه خود تعریف نکرده اید و ....

برنامه شما چون به صورت تک دیالوگ هست ، باید حتما آن را با تنظیمات جدید رجیستر کنید تا بتوانید نام کلاس جدید را تعریف کنید.
4 مرحله این مقاله را به ترتیب انجام دهید و تمام :
http://69.10.233.10/KB/dialog/SingleInstance_src.aspx


تذکر 1: یک پروژه تک دیالوگ جدید ساخته و مراحل مقاله فوق را دقیقا به همان شکل دستورات انجام دهید
تذکر 2: حتما مراحل را در InitInstance انجام دهید نه در OnInitDialog
تذکر 3: کدهای مرحله 3 را ابتدای InitInstance و سپس بعد از آن کدهای مرحله 4 را قرار دهید

تذکر 4: فعلا دنبال CreateMutex هم نروید که جز مباحث پیشرفته همروند سازی ها هست و نیازمند دانش بیشتری هست و پس از تسلط سپس به آن ها بپردازید.

A_Salimi
سه شنبه 28 اسفند 1386, 01:22 صبح
ممنونم

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

:لبخندساده: