page 1 of 1
Comments: 12 | Views: 1692
Hello,

I'm developing a small compact framework app (in c#) which basically has two states:

- Daemon (hidden form checking for updates and serverside account status of user)
- Fullscreen UI

My program consists of a single executable (and it needs to be a single executable due to the economic cost of code signing - thanks Verisign...)

What I basically want to do is launch the daemon the first time the user runs the executable. The next time the executable is run the application should go from "daemon state" to "fullscreen visible state".

My first thought was to create something like this as my program entry point:
  
        [MTAThread]
        private static void Main()
        {
             if(Bootstrapper.daemonRunning){
                 Application.run(FullscreenForm)
             }
             else{
                Bootstrapper.daemonRunning = true;
                Application.run(HiddenDaemonForm)

             }

        }


(Bootstrapper.daemonRunning is a class\static\singleton variable.)

This doesn't seem to work though. The default behavior in win mobile seems to be 'if user tries to relaunch executable when process of same name allready runs, just switch focus to the allready running process'.

So is there an elegant way of detecting multiple attempted launches of the same application?


littleguru
littleguru
allein, allein,... allein, allein!
You probably want to go with a mutex. When the next instance starts you check for it and if the mutex is present you switch to the other window (which probably needs some P/Invoke). Example is found here.
evildictaitor
evildictaitor
How could you use the adjective "indescribable" truthfully?
public class ForegroundAPI {
///<summary> ///TheFindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search. To search child windows, beginning with a specified child window, use the FindWindowEx function.
///</summary> // For Windows Mobile, replace user32.dll with coredll.dll [DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

// For Windows Mobile, replace user32.dll with coredll.dll [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

///<summary> /// Gets the handle to a window using the case-insensitive title of the Window.
///</summary> ///<param name="windowName">The name of the window to be found (using the Window's title)</param> ///<param name="wait">If true, halts program execution until the window can be found</param> private static IntPtr FindWindow(string windowName, bool wait)
{
IntPtr hWnd = FindWindow(null, windowName);
while (wait && hWnd == IntPtr.Zero)
{
System.Threading.Thread.Sleep(500);
hWnd = FindWindow(null, windowName);
}

return hWnd;
}

///<summary> /// Given an hWnd handle to a window, asks Windows to bring the window to the foreground. Returns true on success.
///</summary> ///<param name="windowName">The name of the window to bring to the top</param> ///<param name="wait">If true, halts program execution until the window has been brought to the foreground</param> public static bool BringWindowToTop(string windowName, bool wait)
{
IntPtr hWnd = FindWindow(windowName, wait);
if (hWnd != 0)
{
return SetForegroundWindow(hWnd);
}
return false;
}
}

public class Program {
public const string WindowPrefix = "MyWindow";

public static void Main(){
bool gotMutex = false;
Mutex winMutex = new Mutex(true,Assembly.GetExecutingAssembly().FullName, out gotMutex);
if(!gotMutex){
ForegroundAPI.BringWindowToTop("MyWindow", true);
return;
}

// this is pretty much the same, but we're extra careful to free up the mutex, even if we crash
// 'cos otherwise you won't be able to start a new app.
try {
Application.Run(new Form1());
} finally {
winMutex.ReleaseMutex();
}
}
}
littleguru
littleguru
allein, allein,... allein, allein!
That's what I meant Smiley Nice sample, evil.
figuerres
figuerres
???
thomanil wrote:
Hello,

I'm developing a small compact framework app (in c#) which basically has two states:

- Daemon (hidden form checking for updates and serverside account status of user)
- Fullscreen UI

My program consists of a single executable (and it needs to be a single executable due to the economic cost of code signing - thanks Verisign...)

What I basically want to do is launch the daemon the first time the user runs the executable. The next time the executable is run the application should go from "daemon state" to "fullscreen visible state".

My first thought was to create something like this as my program entry point:
  
        [MTAThread]
        private static void Main()
        {
             if(Bootstrapper.daemonRunning){
                 Application.run(FullscreenForm)
             }
             else{
                Bootstrapper.daemonRunning = true;
                Application.run(HiddenDaemonForm)

             }

        }


(Bootstrapper.daemonRunning is a class\static\singleton variable.)

This doesn't seem to work though. The default behavior in win mobile seems to be 'if user tries to relaunch executable when process of same name allready runs, just switch focus to the allready running process'.

So is there an elegant way of detecting multiple attempted launches of the same application?




you do know that you can buy a cert from most places that sell ssl certs right ?
fo example:
http://www.instantssl.com/google/ssl/codesign.html?ap=GoogleJan07InstantSSL&gclid=CIShn4P-j5ECFQdjsgod-HeXHQ

or

http://www.globalsign.com/digital_certificate/objectsign/index.htm

about half the cost of verisign.

search and find others ..... bet there are some that are even less.
Sven Groot
Sven Groot
You can't have everything; after all, where would you put it?
littleguru wrote:
You probably want to go with a mutex. When the next instance starts you check for it and if the mutex is present you switch to the other window (which probably needs some P/Invoke). Example is found here.

Does that work for Windows mobile? WM apps never get launched twice.
Sven Groot
Sven Groot
You can't have everything; after all, where would you put it?
figuerres wrote:
you do know that you can buy a cert from most places that sell ssl certs right ?
fo example:
http://www.instantssl.com/google/ssl/codesign.html?ap=GoogleJan07InstantSSL&gclid=CIShn4P-j5ECFQdjsgod-HeXHQ

or

http://www.globalsign.com/digital_certificate/objectsign/index.htm

about half the cost of verisign.

search and find others ..... bet there are some that are even less.

Code signing for Windows Mobile is different. First you have to sign your exe with your own cert (which has to be Verisign I believe) then you send it to some organisation who resign it with some cert thingy recognised by WM devices. Regular AuthentiCode certificates are not recognised on WM.
littleguru
littleguru
allein, allein,... allein, allein!
Sven Groot wrote:

littleguru wrote: You probably want to go with a mutex. When the next instance starts you check for it and if the mutex is present you switch to the other window (which probably needs some P/Invoke). Example is found here.

Does that work for Windows mobile? WM apps never get launched twice.


They aren't? Ah yes... you have to close it in the taskmanager otherwise they always stay up... Well in that case he only has to detect when the app becomes background and then foreground the second time...
evildictaitor
evildictaitor
How could you use the adjective "indescribable" truthfully?
If Mutex exists as well as the PInvokes specified, then yes, this code should work for Windows Mobile.

Note that you can turn off that feature in WM that it's always in memory - if the top right button is OK rather than X, it will unload it completely when you close.
Massif
Massif
aim stupidly high, expect to fail often.
evildictaitor wrote:

public class ForegroundAPI {
///<summary> ///TheFindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search. To search child windows, beginning with a specified child window, use the FindWindowEx function.
///</summary> // For Windows Mobile, replace user32.dll with coredll.dll [DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

// For Windows Mobile, replace user32.dll with coredll.dll [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

///<summary> /// Gets the handle to a window using the case-insensitive title of the Window.
///</summary> ///<param name="windowName">The name of the window to be found (using the Window's title)</param> ///<param name="wait">If true, halts program execution until the window can be found</param> private static IntPtr FindWindow(string windowName, bool wait)
{
IntPtr hWnd = FindWindow(null, windowName);
while (wait && hWnd == IntPtr.Zero)
{
System.Threading.Thread.Sleep(500);
hWnd = FindWindow(null, windowName);
}

return hWnd;
}

///<summary> /// Given an hWnd handle to a window, asks Windows to bring the window to the foreground. Returns true on success.
///</summary> ///<param name="windowName">The name of the window to bring to the top</param> ///<param name="wait">If true, halts program execution until the window has been brought to the foreground</param> public static bool BringWindowToTop(string windowName, bool wait)
{
IntPtr hWnd = FindWindow(windowName, wait);
if (hWnd != 0)
{
return SetForegroundWindow(hWnd);
}
return false;
}
}

public class Program {
public const string WindowPrefix = "MyWindow";

public static void Main(){
bool gotMutex = false;
Mutex winMutex = new Mutex(true,Assembly.GetExecutingAssembly().FullName, out gotMutex);
if(!gotMutex){
ForegroundAPI.BringWindowToTop("MyWindow", true);
return;
}

// this is pretty much the same, but we're extra careful to free up the mutex, even if we crash
// 'cos otherwise you won't be able to start a new app.
try {
Application.Run(new Form1());
} finally {
winMutex.ReleaseMutex();
}
}
}


I've done a similar thing before but used a chunk of shared memory to hold the window handle in.

That way, even if the app messes with its name, you can just grab the handle from the shared memory and use that. (naturally, onstartup if no shared memory is present, store the handle, and onexit delete the shared memory.)
evildictaitor
evildictaitor
How could you use the adjective "indescribable" truthfully?
Massif wrote:

I've done a similar thing before but used a chunk of shared memory to hold the window handle in.

That way, even if the app messes with its name, you can just grab the handle from the shared memory and use that. (naturally, onstartup if no shared memory is present, store the handle, and onexit delete the shared memory.)


Ooh. That's a nice solution, because you'll even be able to pass the startup arguments to your already-open app, so you could (for example) open the double-clicked document in the same window in a new tab, for instance.
littleguru
littleguru
allein, allein,... allein, allein!
Btw. evil, how did you embed the sourcecode in this way into the post? A tool?