Results 1 to 17 of 17

Thread: [2005] Single Instance Application

  1. #1

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    [2005] Single Instance Application

    I don't ask too many questions on here these days, but I figured I would ask about this and try to see if anyone maybe has some insight.

    What I am looking to do, is prevent multiple instances of my application from running. Yes I know you are probably saying "Just click the single instance application" checkbox, but unfortunatly, it is not that simple.

    There is a little known, but nasty bug in VBs application framework (which is what single instance application is part of). It is detailed here by yours truly, and is still waiting for resolution by Microsoft.

    If you don't feel like reading the bug submission, basically the problem is this:
    the Single Instance Application feature uses .NET remoting to setup a channel to listen for, detect, and handle additional instances of a given application. .NET remoting relies on TCP/IP, and certain firewalls break this functionality (mcafee and comodo to name 2, but there are more, windows onecare/windows firewall does not cause the bug, and it has all to do with how the given firewall product handles a request before access is granted)

    So anyway, since all this code wireup happens prior to the global application exception handler being hooked up, there is absolutely NO WAY to capture the socket exception that gets thrown when one of the offending firewalls blocks the remoting call. This causes a hard crash of the application. (you know the "do you want to send an error report" crash.)

    A really great VBer by the name of Bill McCarthy came up with a nice solution after seeing my bug report, however it uses features only available in .NET 3.5, and I need to resolve this for apps in .NET 2.0.

    So basically I need to try to find a workaround that simulates the single instance application framework, but does not use remoting to accomplish this. I have a feeling this issue will never be fixed by MS in .NET 2.0, and eventually fixed in a SP to 3.5 or perhaps not until whatever the next framework version is.

    The workaround needs to

    1) check for an already running instance of the app when a new instance is started up
    2) shut down the new instance in the event a first instance exists
    3) focus the already running instance (ie bring to front or maximize, etc)
    4) send any command line params from the second instance back to the first already running instance.


    So if you haven't already guessed, the thing I am stuck on at the moment is #4. All the rest are pretty simple using a few different methods.

    Does anyone have a solid way to pass data between the 2 exes without remoting?

    My application has file associations, so when a user double clicks a file that is associated with my app, it launches my app. This is why I need to handle this multiple instance thing, because if they double click a file, and my app is already open, I need to send that filename over to the already open instance so it can open that file as well.

    If you are still reading this, sorry for the long post, but I wanted to be as descriptive as possible to try to come up with a solution.
    Last edited by kleinma; Jan 22nd, 2008 at 12:11 PM.

  2. #2
    Code Monkey wild_bill's Avatar
    Join Date
    Mar 2005
    Location
    Montana
    Posts
    2,993

    Re: [2005] Single Instance Application

    Quote Originally Posted by kleinma
    Does anyone have a solid way to pass data between the 2 exes without remoting?
    How about message queueing?

  3. #3

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    I suppose anything is possible. However I guess my logical question there would be

    What are the requirements of Message Queuing (IE additional redist files?, requirement on end user system?, certain OS requirement?)

    It would have to be a solution that I could always guarantee to be present on an end users computer.

  4. #4
    Code Monkey wild_bill's Avatar
    Join Date
    Mar 2005
    Location
    Montana
    Posts
    2,993

    Re: [2005] Single Instance Application

    I'm pretty sure Windows doesn't require message queueing, so I guess that would be a problem. Maybe you could create a custom event log for your applications to communicate.

  5. #5
    Frenzied Member
    Join Date
    Jul 2006
    Location
    MI
    Posts
    2,012

    Re: [2005] Single Instance Application

    I recently had to do something very similar to this. I was able to accomplish it by using the StartupNextInstance event under Application Events. This allows you to read incoming parameters in an already running instance. I'm not sure if this will help you or not, I just thought I'd throw it out there...

  6. #6

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    nbrege, that only works when you checkoff the "Single Instance Application" checkbox in the project, which is exactly what I can not do because of the mentioned bug. StartupNextInstance is a product of TCP remoting and the single instance application framework.

  7. #7
    Fanatic Member
    Join Date
    Aug 2006
    Location
    In my head
    Posts
    913

    Re: [2005] Single Instance Application

    How about this? In your Sub Main, get the current list of processes running on that machine, if your application is in there then bring that app to the forefront and call the close on the current instance.

    Untested, but my random thought for the day.....and you help me so much I figure I should at least throw my 2 cents at ya!!!


    Good Luck!

    D
    Platforms of choice: Visual Studio 2005/2008 Professional : Visual Studio 2010 Enterprise : PHP - Notepad++/WAMP

    Please Rate If I helped you.
    Please remember to mark threads as closed if your issue has been resolved.

    Reserved Words in Access | Connection Strings

  8. #8
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: [2005] Single Instance Application

    I think you could use SendMessage Api method to send a message to the app instance main window.

    To send message to the window you need its handle so you could use Process.MainWindowHandle. It is possible that there might be more than one process with the same name since there might be more than one app instance therefore you might want to loop through the all processes and send the same message to the windows that corresponds to your app.

    The message can be custom message and let say Lparam or W param contains the message you want to pass.

    This is not tested but worth to try.

  9. #9

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    Quote Originally Posted by dminder
    How about this? In your Sub Main, get the current list of processes running on that machine, if your application is in there then bring that app to the forefront and call the close on the current instance.

    Untested, but my random thought for the day.....and you help me so much I figure I should at least throw my 2 cents at ya!!!


    Good Luck!

    D
    Sure, but if you check my post again, the problem I am stuck on is #4, what you are talking about is #1-3 which I already have resolved.

  10. #10

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    Quote Originally Posted by VBDT
    I think you could use SendMessage Api method to send a message to the app instance main window.

    To send message to the window you need its handle so you could use Process.MainWindowHandle. It is possible that there might be more than one process with the same name since there might be more than one app instance therefore you might want to loop through the all processes and send the same message to the windows that corresponds to your app.

    The message can be custom message and let say Lparam or W param contains the message you want to pass.

    This is not tested but worth to try.
    I have thought about using custom messages too. I actually have a few possible solutions on the table that I am currently testing, so I will post back with the proceedure and result of each of these methods once I have tested them all. Hopefully one of them is a perfect resolution to the issue.

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2005] Single Instance Application

    Remoting isn't tied to TCP. Perhaps there's no way to change the protocol used by the VB application framework but if you set up your own Remoting then you can use a different protocol. I'm no networking or remoting guru but maybe IPC wouldn't get interfered with by firewalls the way TCP does.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    John, I am actually testing an IPC solution right now after someone on another list mentioned it, I am converting one I found from C# to VB and I will post back with the results of that test.

    I was actually unaware it was in .NET 2.0, I thought it was added in .NET 3.5 along with the managed named pipe classes.

    I also did find an example of using unmanaged win32 apis to accomplish named pipes as well so I wouldn't need .NET 3.5 for that.


    So I am sure one of these will come to resolution. Also if I find IPC works, I am going to start wondering why TCP was used for the application frameworks single instance capabilities versus IPC.

  13. #13
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: [2005] Single Instance Application

    There is a workaround using the clipboard. Here is the code that is tested and works. The only limitation is that since it uses the clipboard it will erase what ever is in there but won’t have other permission or firewall problems.

    Code:
    Imports System.Runtime.InteropServices
    Public Class Form1
    
        <DllImport("user32", CharSet:=CharSet.Auto)> _
        Private Shared Function SendMessage( _
        ByVal hwnd As IntPtr, _
        ByVal wMsg As UInt32, _
        ByVal wParam As IntPtr, _
        ByVal lParam As IntPtr) As IntPtr
        End Function
    
        Private Const WM_CUSTOMMSG As UInt32 = 2000
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim msg As String = CStr(Date.Now.Ticks)
            Me.Label2.Text = "My Tiks: " & msg
            Me.Label3.Text = "My Handle: " & Me.Handle.ToString
            For Each p As Process In Process.GetProcesses
                If p.MainWindowTitle = Me.Text Then
                    My.Computer.Clipboard.SetText(msg)
                    SendMessage(p.MainWindowHandle, WM_CUSTOMMSG, IntPtr.Zero, IntPtr.Zero)
                End If
            Next
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            If m.Msg = WM_CUSTOMMSG Then
                If My.Computer.Clipboard.ContainsText Then
                    Me.Label1.Text = "Message:" & Environment.NewLine _
                    & My.Computer.Clipboard.GetText & Environment.NewLine _
                    & "Target window handle: " & m.HWnd.ToString
                End If
            End If
            MyBase.WndProc(m)
        End Sub
    
    End Class
    Attached Images Attached Images  

  14. #14

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    VBDT, it is a clever method of doing things, but this application goes out to hundreds of users, and I couldn't do something like that because that creates non standard behavior in Windows.

    If I had an app that kept erasing whatever I might have copied to clipboard, it would drive me mad.

  15. #15
    Fanatic Member
    Join Date
    Aug 2006
    Location
    In my head
    Posts
    913

    Re: [2005] Single Instance Application

    I apologize kleinma for not taking in the part where you only need help with the last one. I was thinking on it though.....could you maybe have an external .ini type file that your program keeps a systemfilewatcher on for changes - then when your app tries to start again with variances from the currently running on you can pick them up and incorporate them via the .ini file. Maybe this is a bit far-fetched and definitely outside the box.....just a thought though

    If/When you figure it out can you post the solution, I for one would be most interested in how this is handled.

    Thanks and good luck my friend!!

    D
    Platforms of choice: Visual Studio 2005/2008 Professional : Visual Studio 2010 Enterprise : PHP - Notepad++/WAMP

    Please Rate If I helped you.
    Please remember to mark threads as closed if your issue has been resolved.

    Reserved Words in Access | Connection Strings

  16. #16

    Thread Starter
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373

    Re: [2005] Single Instance Application

    Someone else (not here) made that same suggestion about the filesystemwatcher, and while it would likely work, it does somewhat feel like a cheap hack. That's not to say its a bad idea, but if there is a better fool proof way to handle things, then that is what I am after.

    So anyways, I spent pretty much ALL DAY working on this stupid issue, which annoys me because it is all because of a bug that should not exist in the first place. However, I was able to make a successful working demo that does infact do exactly what I need, and still uses remoting, just ICP remoting instead of TCP remoting. This means a firewall won't get in the way.

    You can download the source code here
    Please note the following things:

    1) It is a VS 2008 project, however it targets .NET 2.0 framework. If you don't have VS 2008, sorry. (Or go download it. its way better)

    2) I have todo comments in the exception handlers for setting up the remoting because I am not quite sure what the best course of action is in the event remoting fails for any reason and I am not sure how I want it to act yet.

    3) The ZIP file doesn't contain the BIN or OBJ folders, so you need to build the project after opening it

    4) After you build the project, test it OUTSIDE the IDE. This is because when you run inside the IDE, it tacks ".vshost.exe" to the end of your assemblies name, which causes the name matching not to work so it doesn't see the second instance as the same program.

    There may be some revisions over the next few days as I continute to test, so I will update this thread if that happens.

  17. #17
    PowerPoster VBDT's Avatar
    Join Date
    Sep 2005
    Location
    CA - USA
    Posts
    2,922

    Re: [2005] Single Instance Application

    Quote Originally Posted by kleinma
    VBDT, it is a clever method of doing things, but this application goes out to hundreds of users, and I couldn't do something like that because that creates non standard behavior in Windows.

    If I had an app that kept erasing whatever I might have copied to clipboard, it would drive me mad.
    I agree, I would not use it also but I though it might help you with some new ideas.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width