how to make a vb.net app single instance?

R

Rich

yes, is there a way to prevent more than one instance of a
vb.net app from being invoked? If this requires API code
what API would I use? If it doesn't require API code may
I ask what property you set in the App or code to use?

Thanks,
Rich
 
H

Herfried K. Wagner [MVP]

* "Rich said:
yes, is there a way to prevent more than one instance of a
vb.net app from being invoked? If this requires API code
what API would I use? If it doesn't require API code may
I ask what property you set in the App or code to use?

<http://dotnet.mvps.org/dotnet/code/application/>
-> "Nur eine Instanz der Anwendung zulassen"

Just ignore the text and have a look at the code.
 
R

Rich

Thank you all for your replies. Vielen Danke!

Since I am still pretty new to VB.net I went with the
simplest solution, of those suggested here, which works
except that it doesn't bring up/into focus the already
running instance of the app like some of the more
sophisticated solutions mentioned (I was having problems
with <...> the angle brackets - do I need to include the
statements inside the brackets? Do I need to import
something else to use angle brackets?):
------------------------------------------------------
Imports System.Diagnostics

Dim aModuleName As String =
Diagnostics.Process.GetCurrentProcess.MainModule.ModuleName
Dim aProcName As String =
System.IO.Path.GetFileNameWithoutExtension(aModuleName)
If Process.GetProcessesByName(aProcName).Length > 1 Then
Application.Exit()
End If
-------------------------------------------------------

I tried adding the If Then code above to a

Public Sub Main()

(vb.net) and selected Sub Main as the startup module but
got an error message that there was no proper signature
for the sub Main. So I put the If Then code into the main
form's Load event and made that my startup object. That
worked. So is there a way, with this example code, to
make it so that the running app comes into focus if you
try to re-invoke? without making it too complex - maybe an
API or something?

Thank you all again for your replies and help.

Rich
 
S

Scott

Add these declarations to your main form....


' API Declarations
Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Int32, ByVal
nCmdShow As Int32) As Int32
Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Int32)
As Int32
' Constant for ShowWindow function
Const SW_SHOWNORMAL As Integer = 1


And modify your code as shown below....


Dim aModuleName As String =
Diagnostics.Process.GetCurrentProcess.MainModule.ModuleName
Dim aProcName As String =
System.IO.Path.GetFileNameWithoutExtension(aModuleName)
Dim RunningProcesses as Process() = Process.GetProcessesByName(aProcName)
If RunningProcesses.Length > 1 Then
' Show previous instance
ShowWindow(ExecutingProcesses(0).MainWindowHandle.ToInt32,
SW_SHOWNORMAL)
SetForegroundWindow(ExecutingProcesses(0).MainWindowHandle.ToInt32)
' Exit application
Application.Exit()
End If
 
R

Rich

Thanks for getting back to me on this. I am getting an
error though, on ShowWindow(ExecutingProcesses(0)... says

ExecutingProcesses not declared. Do I need to import
anything or inherit/implement something? I already have

Imports System.Runtime.InteropServices
------------------------------------------
If RunningProcesses.Length > 1 Then
' Show previous instance
ShowWindow(ExecutingProcesses(0).MainWindowHandle.ToInt32,
SW_SHOWNORMAL)
SetForegroundWindow(ExecutingProcesses
(0).MainWindowHandle.ToInt32)
' Exit application
Application.Exit()
End If
------------------------------------------
 
S

Scott

It's basically an array of all the processes with the name of the current application. In the code I sent previously, RunningProcesses was declared just before the "If" statement as shown below.

Dim RunningProcesses as Process() = Process.GetProcessesByName(aProcName)


Here's the code for the main routine again...


Dim aModuleName As String =
Diagnostics.Process.GetCurrentProcess.MainModule.ModuleName
Dim aProcName As String =
System.IO.Path.GetFileNameWithoutExtension(aModuleName)
Dim RunningProcesses as Process() = Process.GetProcessesByName(aProcName)
If RunningProcesses.Length > 1 Then
' Show previous instance
ShowWindow(ExecutingProcesses(0).MainWindowHandle.ToInt32,
SW_SHOWNORMAL)
SetForegroundWindow(ExecutingProcesses(0).MainWindowHandle.ToInt32)
' Exit application
Application.Exit()
End If
 
R

Rich

Thank you again for getting back to me (and for your
patience :). Unfortunately for me, my background with
processes ranges anywhere from weak to non-existent. My
problem is in getting the hwnd value required by

ShowWindow(ExecutingProcesses
(0).MainWindowHandle.ToInt32,SW_SHOWNORMAL)

and also same problem with SetForegroundWindow....

VB.net is complaining that 'ExecutingProcesses' isn't
declared. I placed the Dim and If Then statements in the
Form's Load Event. It works if I comment out
ShowWindow... and SetForegroundWindow... lines.

If I may bother you one more time (if not, don't worry -
I'll read up on thess APIs), but is there another way to
obtain the hwnd value than ExecutingProcesses? Can I get
it from the RunningProcesses var?

Thanks for your help,
Rich
-----Original Message-----
It's basically an array of all the processes with the
name of the current application. In the code I sent
previously, RunningProcesses was declared just before
the "If" statement as shown below.
Dim RunningProcesses as Process() = Process.GetProcessesByName(aProcName)


Here's the code for the main routine again...


Dim aModuleName As String =
Diagnostics.Process.GetCurrentProcess.MainModule.ModuleNam e
Dim aProcName As String =
System.IO.Path.GetFileNameWithoutExtension(aModuleName)
Dim RunningProcesses as Process() = Process.GetProcessesByName(aProcName)
If RunningProcesses.Length > 1 Then
' Show previous instance
ShowWindow(ExecutingProcesses (0).MainWindowHandle.ToInt32,
(0).MainWindowHandle.ToInt32)
' Exit application
Application.Exit()
End If



"Rich" <[email protected]> wrote in
message news:[email protected]...
 
S

Scott Fant

Actually, I apologize for that. I seem to have declared the variable as
"RunningProcesses" and then used it in the API calls under a different name.
I ran the code to verify that it worked before pasting it into the message
but then made some changes.

Just change the "ExecutingProcesses" variable to be "RunningProcesses" and
it should work. It's all supposed to be the same variable which is an array
of Process objects representing the current instances of your program.

Sorry for the mixup...

Scott
 
R

Rich

Well, it was approaching close of business on my last
post, had to go to a meeting, etc. So getting back to you
now. Yes, that was the fix. I guess I was letting .net
intimidate me since I am still pretty new to it. But I
thought RunningProcess was the var I was supposed to use.
Anyway, it works as advertised.

Many thanks for your help. Many thanks to all of you.
Vielen Danke für deine helfen.

Rich
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top