Auto-launching CF apps with the HKLMInit Registry Key

If you’ve ever needed to automatically launch an application under Windows CE then you probably know that one of the most common ways is to put an entry into the device registry under HKLMInit.  This works great for native applications, but for CF applications success is hit or miss.  The reason is that CF applications require certain system APIs to be up and running before they can run.  For a native app that has this requirement, the solution is simple: you call either IsApiReady or WaitForAPIReady (depending on the OS version) and then continue when you’re satisfied.  For CF apps it won’t work.  The APIs need to be ready long before Main is entered and any of your managed code is running.


Of course the “right” solution is that the CF team should have put that check into the loader so we could launch this way, but they didn’t so we have to work around it.


So how do we get around this?  Well we leverage the initialization process itself.  When an app is launched from HKLMInit, it is responsible for calling SignalStarted once it is running.  This allows any other items launching from HKLMInit to set up dependencies, for example if item 60 depends on item 50, item 60 won’t launch until item 50 has called SignalStarted.  What we can do is create a native application that acts as a launch gate.  This gate app will call the appropriate wait function, and only after the APIs we need are available does it call SignalStarted.  We can then launch any CF application using HKLMInit by simply having the gate application launch first, and then having the CF app depend on the gate.


So in the registry, it would look like this:


[HKEY_LOCAL_MACHINEInit]
    “Launch90″=”gateapp.exe”
    “Depend90″=hex:1e,00 ; depend on GWES, which is at 30
    “Launch91″=”MyCFApp.exe”
    “Depend91″=hex:5a,00 ; depend on gateapp


And here’s the source code for a basic gate app:


extern “C” DWORD WaitForAPIReady(DWORD, DWORD);
extern “C” BOOL IsAPIReady(DWORD hAPI);

int _tmain(int argc, _TCHAR* argv[])
{
    // quick sanity check – HKLMInit will send in our order number
    if(argc == 0) return 0;

    BOOL success = FALSE;

    // wait for window manager – that should be enough for us
    #if _WIN32_WCE > 0x500
        success = (WaitForAPIReady(SH_WMGR, 5000) == WAIT_OBJECT_0);
    #else
        int i = 0;
        while((! IsAPIReady(SH_WMGR)) && (i++ < 50))
        {
             Sleep(100);
        }

        success = (i < 50);
    #endif

    if(success)
    {
        int launchCode = _ttoi(argv[1]);
        SignalStarted(launchCode);
    }
    else
    {
        RETAILMSG(TRUE, (_T(“CFInitGate timed out – SH_WMGR was not ready after 5 secondsrn”)));
    }

    return 0;
}

5 thoughts on “Auto-launching CF apps with the HKLMInit Registry Key”

  1. An excellent code snippet.

    Should the line

    #if _WIN32_WCE > 0x500

    not be

    #if _WIN32_WCE >= 0x600

    otherwise minor versions of Windows CE 5 try to compile
    the WaitForAPIReady block of code.

    Like

  2. The _WIN32_WCE define, I *think* is not that closely tied to the minor version. I think all versions of 5.0 (including all minor versions) still are at 0x500. Of course I could be wrong, so it’s worth checking.

    Like

  3. Thank you, it worked with 0x500 for me, running Windows Mobile 6.5.5 (CE 5.2.24635)

    No more random exception error message! 🙂

    I have a question, I am using it to load HARET and boot linux and I would like to not load the GUI / Today screen, is that possible?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s