Issue:
Using setup.dll in my applications CAB to install support CABs (ie:
sql.ppc3.arm.CAB and sqlce.ppc3.arm.CAB).
I am trying to provide backwards compatibility for Microsoft Mobile 5.0 OS.

A little history.I developed a mobile application that ran perfect on Dell
Axim versions 5.0 and earlier on Windows CE version OS. Now that our clients
are purchasing Dell Axim 5.1/5.1v the app fails. This is because the OS was
"upgraded" to Windows Mobile 5.0 for these new devices, which includes
Compact Framework 2.0 also upgraded.

To resolve the failure; I downloaded the Microsoft Visual Studio 2005 and
re-compiled my application/s. I adjusted references to library components as
needed and I added a CAB project. Made a few edits in the .inf and put the
package together.

Everything installs on the mobile device BUT the supporting CABs (mentioned
above) do NOT automatically install as they did before. I will get "compact
frame work" related errors until I manually initiate install of the
additional CABs. Then everything works fine. No changes to the setup.dll
code were made except I re-compiled in VS '05 for support on Windows Mobile
5.0 Pocket PC SDK (ARMV4I).




Question:
Is there sample C++ code that shows how to create a setup.dll for Mobile 5.0
that will auto install multiple supporting CABs and will run on Mobile 5.0
OS?

I'm only running one instance of wceload.exe. I get its handle, run one CAB
and finish, then run subsequent.Here is a simple example of code in my dll:

// Sample CESetup DLL

#include <windows.h>
#include <tchar.h>
#include "ce_setup.h"
#include <winbase.h>

const TCHAR szTITLE[] = TEXT("CESetup Sample DLL");
const TCHAR szINST_INIT[] = TEXT("Install_Init\n\nContinue?");
const TCHAR szINST_EXIT[] = TEXT("Install_Exit\n\nContinue?");
const TCHAR szUNINST_INIT[] = TEXT("Uninstall_Init\n\nContinue?");
const TCHAR szUNINST_EXIT[] = TEXT("Uninstall_Exit");
const TCHAR szError[] = TEXT("Error");

BOOL WINAPI DllMain(HANDLE hMod, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}

codeINSTALL_INIT Install_Init(
HWND hwndParent,
BOOL fFirstCall,
BOOL fPreviouslyInstalled,
LPCTSTR pszInstallDir)
{
return codeINSTALL_INIT_CONTINUE;
}

codeINSTALL_EXIT Install_Exit(
HWND hwndParent,
LPCTSTR pszInstallDir,
WORD cFailedDirs,
WORD cFailedFiles,
WORD cFailedRegKeys,
WORD cFailedRegVals,
WORD cFailedShortcuts)
{
DWORD dwError = NOERROR;
PROCESS_INFORMATION pi = {0};

LPWSTR lpExe = TEXT("\\windows\\wceload.exe");
LPWSTR lpCmdLine = TEXT("\\windows\\sql.ppc3.arm.cab");

CreateProcess(lpExe, lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, NULL,
&pi);
if (pi.hProcess)
CloseHandle (pi.hProcess);
if (pi.hThread)
CloseHandle (pi.hThread);

Sleep(10000);

lpCmdLine = TEXT("\\windows\\sqlce.ppc3.arm.cab");
CreateProcess(lpExe, lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, NULL,
&pi);
if (pi.hProcess)
CloseHandle (pi.hProcess);
if (pi.hThread)
CloseHandle (pi.hThread);

return codeINSTALL_EXIT_DONE;
}

codeUNINSTALL_INIT Uninstall_Init(HWND hwndParent, LPCTSTR pszInstallDir)
{
return codeUNINSTALL_INIT_CONTINUE;
}

codeUNINSTALL_EXIT Uninstall_Exit(HWND hwndParent)
{
return codeUNINSTALL_EXIT_DONE;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

I left out some fat so it is easy to read.Thanks to anyone how can point me
in the right direction!!

Chuck

P.S
I hope I get an answer because I would hate to keep posting this for the
rest of my life until I do :-)


--
Charcoal
Going Mobile...Keep me moving.

Re: Mobile 5.0 deploy multiple CAB - wce-load.exe by rowans

rowans
Sun Dec 18 22:33:30 CST 2005

i have a coded example.
upon exit of the main CAB installation it calls another exe which
installs all the cabs
the code it at:
http://row1.info/content/view/85/2/


Re: Mobile 5.0 deploy multiple CAB - wce-load.exe by Charcoal

Charcoal
Mon Jan 02 10:29:05 CST 2006

Fantastic! TY SOOO Much
--
Charcoal
Going Mobile...Keep me moving.


"rowans@gmail.com" wrote:

> i have a coded example.
> upon exit of the main CAB installation it calls another exe which
> installs all the cabs
> the code it at:
> http://row1.info/content/view/85/2/
>
>

Re: Mobile 5.0 deploy multiple CAB - wce-load.exe by Charcoal

Charcoal
Thu Feb 09 12:02:35 CST 2006

Hey Rowan,

Sorry it has taken this long to follow up with you. Very busy as Iâ??m sure
you are. I just wanted to let you know I resolved the setup issue and would
like to share the fundamentals of the solution so you can help others as you
have helped me.

Problem: Using a setup dll in my applications CAB to launch multiple
supporting CABs failed with Windows Mobile 5.0 because only one instance of
wceload.exe can run at any given time. One must check to see if the process
is running and can only start a new one once it has ended.

My solution (although not perfect) stems from Rowan Youngsonâ??s suggestion in
this article http://row1.info/content/view/85/2/ .

First I created a separate application, call it â??Startup.exeâ??. This is
actually a good idea because now when updates are available for the main
application â??Main.exeâ??, they can be downloaded via web service; Startup will
manage the update instructions in an xml config file and create a process to
launch the Main application. Doing this without a â??controller app (Startup)â??
would be difficult otherwise because you canâ??t update the Main application,
its config files, or the DB if they are in use by the Main application.

Anyway, I digress, soâ?¦back to launching multiple CABSâ?¦.

I created a class that manages the process threadingâ?¦.

public class ProcessInfo
{
/// <summary>
/// Part of the ProcessInfo class
/// </summary>
public Int32 hProcess;
/// <summary>
/// Part of the ProcessInfo class
/// </summary>
public Int32 hThread;
/// <summary>
/// Part of the ProcessInfo class
/// </summary>
public Int32 ProcessID;
/// <summary>
/// Part of the ProcessInfo class
/// </summary>
public Int32 ThreadID;
}

I imported the necessary libray infoâ?¦.

// CreateProcess PInvoke API
[DllImport("Coredll.dll", SetLastError = true)]
private extern static int CreateProcess(
string imageName,
string cmdLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
Int32 boolInheritHandles,
Int32 dwCreationFlags,
IntPtr lpEnvironment,
IntPtr lpszCurrentDir,
IntPtr si,
ProcessInfo pi
);

[DllImport("coredll.dll", SetLastError = true)]
private extern static Int32 WaitForSingleObject(
IntPtr Handle,
Int32 Wait);

[DllImport("CoreDll.dll")]
private extern static Int32 CloseHandle(
IntPtr hProcess);

[DllImport("CoreDll.dll")]
private extern static Int32 GetLastError();

[DllImport("CoreDll.dll")]
private extern static Int32 GetExitCodeProcess(
IntPtr hProcess,
out Int32 exitcode);

I then created a method in which to call when creating processes to
runâ?¦(NOTE: This first little â??IFâ?? piece just allows me to run my 'Main' app
after 1 second and waits for no man! Elseâ?¦wait for the user to respond.
Example: User needs to confirm when a process ended by tapping â??OKâ?? after the
SQLCE CAB installs. Then the next process will runâ?¦

public static bool CreateProcess( string ExeName, string CmdLine)
{
Int32 wait;
if (ExeName == MainApp)
{
wait = 1000;
}
else
{
wait = -1;
}

Create the process info obj and make sure it exists

ProcessInfo pi = new ProcessInfo();

if (CreateProcess(ExeName, CmdLine, IntPtr.Zero, IntPtr.Zero,
0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, pi) == 0)
{
return false;
}

It will run and wait for user to respond or not, depending on the condition
set in the first â??IFâ?? stament aboveâ?¦

WaitForSingleObject((IntPtr)pi.hProcess, wait);

Int32 exitCode;

Once the CAB installs then the user usually selects â??OKâ?? to confirm a
successful install. This action triggers this Exit processâ?¦You could handle
any errors with â??GetLastErrorâ??.

if (GetExitCodeProcess((IntPtr)pi.hProcess, out exitCode) == 0)
{
MessageBox.Show("Failure in GetExitCodeProcess");
CloseHandle((IntPtr)pi.hThread); // Free handles
CloseHandle((IntPtr)pi.hProcess);
return false;
}

A successful confirmation exit will jump you here and free up the handles.

CloseHandle((IntPtr)pi.hThread); // Free handles
CloseHandle((IntPtr)pi.hProcess);

if (exitCode != 0)
return false;
else
return true;
}
Thatâ??s it baby! Of course I left out a lot of code to simplify this, but
also to make sure a cut and paste would work with few modifications.

You may want to include various System references too like:
using System.Reflection;
using System.Runtime.InteropServices;
....etc...InteropServices is a must.

Be sure to include a call to the â??CreateProcessâ?? method and include the
parameters as defind in the dllImport â??CreateProcessâ??.

CreateProcess("wceload.exe", @"\windows\sqlce.ppc3.arm.CAB");

For more info see
http://msdn.microsoft.com/library/en-us/wcekernl/html/ceconProcessThreadFunctions.asp?frame=true

Thanks Again Chuck Mahenski
--
Charcoal
Going Mobile...Keep me moving.


"rowans@gmail.com" wrote:

> i have a coded example.
> upon exit of the main CAB installation it calls another exe which
> installs all the cabs
> the code it at:
> http://row1.info/content/view/85/2/
>
>