PDA

View Full Version : جلوگیری از اجرا تکرار برنامه



aleas2
سه شنبه 22 مرداد 1392, 19:19 عصر
سلام خسته نباشید دوستان چطور میشه کاری که بطور مثال برنامه text.exe زدم یه بار اجرا شد دفعه بعد روی test.exe کلیک میکنم دوباره اجرا نشه یعنی اگر چند بار روی text.exe کلیک کردم فقط یه بار اجرا بشه

علیرضا.ا
سه شنبه 22 مرداد 1392, 19:48 عصر
سوال منم هست:D
اگه راهی داشته باشه لطفا این چن تا سوال رو جواب بدین!
میشه تعداد رو محدود کرد مثلا 10 بار؟
اگه به عنوان لایسنس این کار رو بکنیم -به سادگی- قابل کرک هست یا نه؟

mehdi.mousavi
سه شنبه 22 مرداد 1392, 19:53 عصر
سلام خسته نباشید دوستان چطور میشه کاری که بطور مثال برنامه text.exe زدم یه بار اجرا شد دفعه بعد روی test.exe کلیک میکنم دوباره اجرا نشه یعنی اگر چند بار روی text.exe کلیک کردم فقط یه بار اجرا بشه

سلام.
برای اینکار، باید با استفاده از CreateMutex (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682411%28v=vs.85%29.aspx)، یه named mutex در ابتدای برنامه ایجاد کنید. سپس، مقدار بازگشتی اونو
بررسی کنید، اگر NULL نبود و GetLastError مقدار ERROR_ALREADY_EXISTS رو برگردوند، یعنی Instance دیگه ای از
برنامه اون mutex رو ایجاد کرده...

بدین ترتیب میتونید متوجه بشید که قبلا Instance ای از برنامه اجرا شده و در صورت نیاز، با استفاده از FindWindow یا
دیگر امکانات موجود، Instance قبلی رو پیدا کنید و اونو با استفاده از BringWindowToTop جلوتر از دیگر پنجره ها قرار بدید.

موفق باشید.

mehran901
سه شنبه 22 مرداد 1392, 20:41 عصر
خب راه ساده تری هم داره !!
به این شکل عمل کنین :

If App.PrevInstance Then
MsgBox "the program is running ", vbCritical
End
End If

mehran901
سه شنبه 22 مرداد 1392, 20:42 عصر
سوال منم هست:D
اگه راهی داشته باشه لطفا این چن تا سوال رو جواب بدین!
میشه تعداد رو محدود کرد مثلا 10 بار؟
اگه به عنوان لایسنس این کار رو بکنیم -به سادگی- قابل کرک هست یا نه؟

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

mehdi.mousavi
سه شنبه 22 مرداد 1392, 21:14 عصر
خب راه ساده تری هم داره !!
به این شکل عمل کنین :

If App.PrevInstance Then
MsgBox "the program is running ", vbCritical
End
End If


سلام.
در حال حاضر دقیق خاطرم نیست کی و کجا، اما PrevInstance همیشه set نمیشه (تا اونجاییکه یادمه تو Windows 3.1 یا نسخه های 16 بیتی ویندوز این Property درست Set میشه،
اما در نسخه های 32 بیتی، چندین حالت وجود داره که سیستم عامل اون Property رو Set نمیکنه). بطور نمونه، فکر میکنم اگر از درون IDE برنامه رو اجرا کنید، PrevInstance ست نشه،
یا اگر Folder برنامه رو تغییر بدید و اونو از دو مسیر جداگانه همزمان اجرا کنید (بازم تکرار میکنم، متاسفانه دقیق خاطرم نیست، اما اینو بوضوح یادمه که این Property همواره در دسترس
نیست). اما استفاده از Named Mutex ها رد خور نداره، چون Handle به Kernel Object ای به شما برمیگردونه که همواره یک Instance از اون وجود خواهد داشت...

در هر حال، راه ساده تر لزوما راه درست تر هم نیست. :)

موفق باشید.

SlowCode
سه شنبه 22 مرداد 1392, 21:23 عصر
سلام.
در حال حاضر دقیق خاطرم نیست کی و کجا، اما PrevInstance همیشه set نمیشه (تا اونجاییکه یادمه تو Windows 3.1 یا نسخه های 16 بیتی ویندوز این Property درست Set میشه،
اما در نسخه های 32 بیتی، چندین حالت وجود داره که سیستم عامل اون Property رو Set نمیکنه). بطور نمونه، فکر میکنم اگر از درون IDE برنامه رو اجرا کنید، PrevInstance ست نشه،
یا اگر Folder برنامه رو تغییر بدید و اونو از دو مسیر جداگانه همزمان اجرا کنید (بازم تکرار میکنم، متاسفانه دقیق خاطرم نیست، اما اینو بوضوح یادمه که این Property همواره در دسترس
نیست). اما استفاده از Named Mutex ها رد خور نداره، چون Handle به Kernel Object ای به شما برمیگردونه که همواره یک Instance از اون وجود خواهد داشت...

در هر حال، راه ساده تر لزوما راه درست تر هم نیست. :)

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

Mr'Jamshidy
سه شنبه 22 مرداد 1392, 22:29 عصر
سلام.
برای اینکار، باید با استفاده از CreateMutex (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682411%28v=vs.85%29.aspx)، یه named mutex در ابتدای برنامه ایجاد کنید. سپس، مقدار بازگشتی اونو
بررسی کنید، اگر NULL نبود و GetLastError مقدار ERROR_ALREADY_EXISTS رو برگردوند، یعنی Instance دیگه ای از
برنامه اون mutex رو ایجاد کرده...

بدین ترتیب میتونید متوجه بشید که قبلا Instance ای از برنامه اجرا شده و در صورت نیاز، با استفاده از FindWindow یا
دیگر امکانات موجود، Instance قبلی رو پیدا کنید و اونو با استفاده از BringWindowToTop جلوتر از دیگر پنجره ها قرار بدید.

موفق باشید.

این هم نمونه برنامه:

Const ERROR_ALREADY_EXISTS = 183&
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Form_Load()
Dim hMutex As Long
'Try to create a new Mutex
hMutex = CreateMutex(ByVal 0&, 1, App.Title)
'Did the mutex already exist?
If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
'Clean up
ReleaseMutex hMutex
CloseHandle hMutex
'More than one instance detected
MsgBox "More than one instance"
End
Else
'form load code
End If
End Sub

mehran901
سه شنبه 22 مرداد 1392, 22:36 عصر
یا اگر Folder برنامه رو تغییر بدید و اونو از دو مسیر جداگانه همزمان اجرا کنید (بازم تکرار میکنم، متاسفانه دقیق خاطرم نیست، اما اینو بوضوح یادمه که این Property همواره در دسترس
نیست). اما استفاده از Named Mutex ها رد خور نداره، چون Handle به Kernel Object ای به شما برمیگردونه که همواره یک Instance از اون وجود خواهد داشت...

در هر حال، راه ساده تر لزوما راه درست تر هم نیست. :)


کاملا درست میفرمایین ولی احساس کردم ی روش ساده میخوان واسه جلوگیری از اجرای مجدد برنامشون(با صرف نظر از ازاینکه با تغییر نام یا مسیرش باز اجرا بشه )

کاملا درسته اگه مسیر عوض بشه اسم فایل عوض بشه دوباره اجرا میشه

vbhamed
سه شنبه 22 مرداد 1392, 23:10 عصر
يك راه ديگه هم به شكل زير هست
كد رو داخل ماژول قرار بدين
Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Const InstanceCode = "A8F500EA:D54F:210F:ED0A:F4A5A20C038B"

Public Function PrevInstance() As Boolean

If FindWindow(vbNullString, ByVal InstanceCode) Then

PrevInstance = True
Exit Function

End If

CreateWindowEx 0&, "STATIC", InstanceCode, 0&, 0&, 0&, 0&, 0&, 0&, 0&, App.hInstance, 0&
PrevInstance = False

End Function
با اين كار هنگام اجراي چك مي‌كنه پنجره اي با نام دلخواه كه تو پارامتر InstanceCode ميديم وجود داره يا نه، اگر وجود نداشت يعني برنامه قبلا اجرا نشده پس برنامه اجرا ميشه و پنجره رو با اين نام ايجاد مي‌كنه كه البته اين پنجره ديده نميشه و فقط براي شناسايي استفاده ميشه

مزاياي اين روش :
1 - وابسته به پوشه اي كه برنامه از اون پوشه اجرا شده نيست
2 - InstanceCode دست خودمونه بنابراين مي‌تونيم حتي كاري كنيم كه دو تا برنامه مختلفمون كه ربطي به هم ندارن هم با همزمان نتونن اجرا نشن يعني دو تا برنامه جدا بنويسيم ولي InstanceCode يكسان بهشون بديم
3 - با كدنويسي مي‌تونيم كاري كنيم كه InstanceCode مختلفي در برنامه بتونن چك بشن، مثلا اگر برنامه 1 و برنامه 2 و برنامه 3 اجرا نبودن برنامه ما اجرا بشه يا برعكس اگر حتما برنامه 1 اجرا بود برنامه ما هم اجرا بشه و ...

اين روش استفاده از تابع بالا
If PrevInstance Then
MsgBox "Another instance is running.", vbCritical, "Error"
End
End If

new_chater
چهارشنبه 23 مرداد 1392, 01:29 صبح
با سلام

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

به عنوان مثال نرم افزار در systray بوده و قصد نمایش نرم افزار باز شده را به کاربر داریم

vbhamed
چهارشنبه 23 مرداد 1392, 06:37 صبح
سلام
راههاي مختلفي وجود داره
يكيش اينه كه موقع اجراي برنامه براي اولين بار، هندل فرمتون رو جايي ذخيره كنيد و اگر با روش بالا فهميديد كه برنامه قبلا اجرا شده، اون هندل رو بخونيد و با تابع API به نام SetWindowPos فرمتون رو دوباره نمايش بديد
يا مي‌تونيد از تابع ShowWindow استفاده كنيد و ...

new_chater
چهارشنبه 23 مرداد 1392, 15:16 عصر
کد نویسی من زیاد خوب نیست , اما منظور از showWindow باز خوانی یک برنامه باز شده در تسک منیجیره یا اینکه باید کد برنامه رو بغییر بدم و از اون طریق مثل مثال اول برنامه دوباره لود بشه ؟

آیا برنامه های hidden شده در systray هم از این قانون پیروی میکنند ؟

m.4.r.m
چهارشنبه 23 مرداد 1392, 15:54 عصر
این برنامه هم هست که توسط خود مایکروسافت نوشته شده :

Option Explicit

Public Const GW_HWNDPREV = 3

Declare Function OpenIcon Lib "user32" (ByVal hwnd As Long) As Long
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) _
As Long
Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, ByVal wCmd As Long) As Long
Declare Function SetForegroundWindow Lib "user32" _
(ByVal hwnd As Long) As Long

Private Sub Form_Load()
If App.PrevInstance Then
ActivatePrevInstance
End If
End Sub

Sub ActivatePrevInstance()
Dim OldTitle As String
Dim PrevHndl As Long
Dim result As Long

'Save the title of the application.
OldTitle = App.Title

'Rename the title of this application so FindWindow
'will not find this application instance.
App.Title = "unwanted instance"

'Attempt to get window handle using VB4 class name.
PrevHndl = FindWindow("ThunderRTMain", OldTitle)

'Check for no success.
If PrevHndl = 0 Then
'Attempt to get window handle using VB5 class name.
PrevHndl = FindWindow("ThunderRT5Main", OldTitle)
End If

'Check if found
If PrevHndl = 0 Then
'Attempt to get window handle using VB6 class name
PrevHndl = FindWindow("ThunderRT6Main", OldTitle)
End If

'Check if found
If PrevHndl = 0 Then
'No previous instance found.
Exit Sub
End If

'Get handle to previous window.
PrevHndl = GetWindow(PrevHndl, GW_HWNDPREV)

'Restore the program.
result = OpenIcon(PrevHndl)

'Activate the application.
result = SetForegroundWindow(PrevHndl)

'End the application.
Unload Me
End Sub