In going over my custom installer code from a few years ago, I now remember
that someone from Microsoft strongly recommended that we now install apps
onto WM5 (and now WM6) devices by using ActiveSync's CeAppMgr.exe and not
the WCELOAD.EXE on the device as we were used to in previous device
operating systems. As you can see from the code snippet, I first detect
whether the device is using WM5 or later and switch the method of CAB
delivery. My code has been working fine on WM 2003, WM5 devices and also on
WM6 devices. My app is a consumer app so it needs to be able to install onto
any of our customers Pocket PCs or Pocket PC phones.
Though this code may not be exactly what you are looking for, I hope it is
of use in understanding the way we went after using the hint from the
Microsoft person.
Regards,
Neville Lang
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** My Custom Installer class (partial code) ***
// Class fields
private const string CEAPPMGR_PATH =
@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\CEAPPMGR.EXE";
private const string ACTIVESYNC_INSTALL_PATH = @"SOFTWARE\Microsoft\Windows
CE Services";
private const string INSTALLED_DIR = "InstalledDir";
private const string CEAPPMGR_EXE_FILE = @"CEAPPMGR.EXE";
private const string CEAPPMGR_INI_FILE = @"MyApp.ini";
private const string APP_SUBDIR = @"\MyAppFolder";
private const string ACTIVESYNC_EXE_FILE = "WCESMGR.EXE";
private const int BASE_AS = 371; // Base value for ActiveSync private
bool bWM5 = false; // Windows Mobile 5.0 (or later) private
const int WM_MIN_VERSION = 5; // WM5 or later
private bool MyInstaller(string MsiSource, string MsiTarget)
{
string strProdCab1 = "MyApp_PPC.ARM.cab";
string strProdCab2 = "MyApp_PPC.ARMV4.cab";
....
....
//--- Check the version of ActiveSync --------
if (! CheckActiveSync() )
{
return false;
}
// Initialise RAPI
if (!RAPI.IsDeviceConnected(5000))
{
HandleErrors(23);
return false;
}
//--- Get the Operating System version on the device ------------------
RAPI.CEOSVERSIONINFO DeviceOS = new RAPI.CEOSVERSIONINFO();
int iRet = RAPI.CeGetVersionEx(out DeviceOS);
if (iRet == 0)
{
HandleErrors(24);
return false;
}
// Check if the Device's operating system is WM5 or later
if (DeviceOS.dwMajorVersion >= WM_MIN_VERSION)
{
this.bWM5 = true;
}
....
....
if (this.bWM5)
{
// Find the location where the application will be installed
string installPath = this.GetAppInstallDirectory();
// Create target directory off the ActiveSync folder for my App
Directory.CreateDirectory(installPath);
// Copy the two CABs and AppMgr INI file to the ActiveSync directory
System.IO.File.Copy(Path.Combine(MsiTarget, strProdCab1),
Path.Combine(installPath, strProdCab1), true);
System.IO.File.Copy(Path.Combine(MsiTarget, strProdCab2),
Path.Combine(installPath, strProdCab2), true);
System.IO.File.Copy(Path.Combine(MsiTarget, strProdCabIni),
Path.Combine(installPath, CEAPPMGR_INI_FILE), true);
// Get the path to CeAppMgr.exe
RegistryKey keyAppMgr = Registry.LocalMachine.OpenSubKey(CEAPPMGR_PATH);
string appMgrPath = (string) keyAppMgr.GetValue(null);
keyAppMgr.Close();
// Run CeAppMgr.exe to install the files to the device
Process.Start(appMgrPath, "\"" + Path.Combine(installPath,
CEAPPMGR_INI_FILE) + "\"");
}
else // True if device o/s earlier than WM5
{
...
...
RAPI.PROCESS_INFORMATION info = new
CustomInstaller.RAPI.PROCESS_INFORMATION();
Cursor.Current = Cursors.WaitCursor;
RAPI.CopyFileToDevice(MsiTarget + strProdCab2, @"\" + strProdCab2,
true);
RAPI.CeCreateProcess("WCELOAD.EXE", "/noui /noaskdest " + @"\" +
strProdCab2, 0, 0, 0, 0, 0, null, 0, ref info);
Cursor.Current = Cursors.Default;
}
} // MyInstaller method
//=====================================================
private bool CheckActiveSync()
{
if (Environment.OSVersion.Version.Major < 6) // True if Windows
version is not Vista
{
// First check if ActiveSync installed on main computer by
checking for the Windows CE Services key
RegistryKey regkey =
Registry.LocalMachine.OpenSubKey(ACTIVESYNC_INSTALL_PATH);
if (regkey == null)
{
HandleErrors(17);
return false;
}
// Get the path where ActiveSync installed
string strInstallPath =
Convert.ToString(regkey.GetValue(INSTALLED_DIR));
if (strInstallPath == "") // True if this value not found
{
HandleErrors(17);
return false;
}
regkey.Close();
// Check the version of ActiveSync on the desktop
string strFilename = strInstallPath + @"\" +
ACTIVESYNC_EXE_FILE;
if (System.IO.File.Exists(strFilename))
{
FileVersionInfo myFVI =
FileVersionInfo.GetVersionInfo(strFilename);
int currentAS = (myFVI.FileMajorPart * 100) +
(myFVI.FileMinorPart * 10) + myFVI.FileBuildPart;
if (currentAS < BASE_AS)
{
HandleErrors(15);
return false;
}
}
else
{
HandleErrors(16);
return false;
}
}
return true;
}
//=====================================================
private string GetAppInstallDirectory()
{
// Get ActiveSync install directory
RegistryKey keyActiveSync =
Registry.LocalMachine.OpenSubKey(ACTIVESYNC_INSTALL_PATH);
if (keyActiveSync == null)
{
throw new Exception("ActiveSync is not installed !!");
}
// Build target directory path under the Activesync folder
string activeSyncPath = (string)
keyActiveSync.GetValue(INSTALLED_DIR);
string installPath = activeSyncPath + APP_SUBDIR;
keyActiveSync.Close();
return installPath;
}
//=====================================================
MyApp.ini (Below are the lines in this text file)
---------
[CEAppManager]
Version = 1.0
Component = MyApp
[MyApp]
Description = MyApp - An application for the Pocket PC
CabFiles = MyApp_PPC.ARMV4.cab,MyApp_PPC.ARM.cab
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~