Window Mobile/CE的PC端安装测试
PDA通过数据线同步电脑后,将netcf和SQLCE的CAB文件手动的复制到PDA里,还得手动的建立目录,创建快捷方式(麻烦)。现在不止实施人员这么做,连客户也要这么做(PDA备电没电了,就还原了),想了想有没有简便方式,好像在见过,在网上搜索一番,然后开始动手,不过都得感谢下面“2位”:
1.OpenNETCF.Desktop.Communication
2.Microsoft ActiveSync 4.5
大致原理:利用Rapi对PDA里的文件,目录创建,复制的操作,其次就是用 Microsoft ActiveSync 安装目录里CEAPPMGR.EXE在PC给PDA安装CAB。
首先,在网上下载的OpenNETCF.Desktop.Communication的源码,换个8.0的解决方案,然后编译成DLL。
然后,创建一个Windows程序项目,引入刚编译的DLL,然后在CS文件添加:
using System.Collections;
using System.IO;
using System.Threading;
接下来就是实例化RAPI类(主角),然后就是声明点全局变量来使用:
//源文件目录 也是程序启动目录
private string _loadPath;
//目标目录 也是安装目录
private string _newPath = @"\Storage Card\PDA\";
//目标数据目录
private string _newDataPath = @"\Storage Card\PDA\Data\";
//目标图片目录
private string _newPhotoPath = @"\Storage Card\PDA\Photo\";
//PDA桌面文件夹路径
private string _newlnkPath = @"\Windows\Desktop\";
//CEAPPMGR.EXE路径用于PC安装CAB
private string _CabSetuper = "C:\\Program Files\\Microsoft ActiveSync\\CEAPPMGR.EXE";
//组件目录名
private string _CabPathName = "Cab";
//主程序目录名
private string _exePathName = "Data";
//rapi
private OpenNETCF.Desktop.Communication.RAPI _rapi;
//日志
private List<string> _logData;
#endregion
#region 窗体加载
private void frmMain_Load(object sender, EventArgs e)
{
PlaySound();
FormShow();
_loadPath = Application.StartupPath;
_rapi = new OpenNETCF.Desktop.Communication.RAPI();
_logData = new List<string>();
}
#endregion
其次,就是弄几个关于rapi的复制文件,删除一些常用操作的方法:
private bool CopyFileToPDA(string oldFile, string newFile)
{
try
{
_rapi.CopyFileToDevice(oldFile, newFile, true);
LogAdd("复制文件", newFile);
return true;
}
catch (Exception ex)
{
LogAdd("错误", ex.Message);
return false;
}
}
private void ConnectPDA()
{
_rapi.Connect(true, 0);
while (!_rapi.DevicePresent)
{
MessageBox.Show("请确保PDA已经与PC同步!");
_rapi.Connect(true, 0);
}
}
private void CabSetup(string canfile)
{
try
{
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
System.Diagnostics.Process p = new System.Diagnostics.Process();
info.FileName = _CabSetuper;
info.Arguments = canfile;
info.CreateNoWindow = false;
p.StartInfo = info;
p.Start();
p.WaitForExit();
LogAdd("安装CAB", canfile);
Thread.Sleep(2000);
}
catch (Exception ex)
{
LogAdd("错误", ex.Message);
}
}
private bool CreateDirectory(string path)
{
try
{
_rapi.CreateDeviceDirectory(path);
LogAdd("创建目录", path);
return true;
}
catch (Exception ex)
{
LogAdd("错误", ex.Message);
return false;
}
}
private bool DeleteDirectory(string path)
{
try
{
_rapi.RemoveDeviceDirectory(path, true);
LogAdd("删除目录", path);
return true;
}
catch (Exception ex)
{
LogAdd("错误", ex.Message);
return false;
}
}
private bool DeleteFile(string file)
{
try
{
_rapi.DeleteDeviceFile(file);
LogAdd("删除文件", file);
return true;
}
catch (Exception ex)
{
LogAdd("错误", ex.Message);
return false;
}
}
#endregion
上面代码中的LogAdd方法是自定义安装日志,用于安装失败时,叫客户发来研究的,呵呵:
private void SaveLog()
{
if (_logData.Count == 0) return;
string tmp = string.Empty;
foreach (string s in _logData)
{
tmp += s + "\r\n";
}
FileStream fs = new FileStream(string.Format("{0}\\LOG{1}.txt", Application.StartupPath, DateTime.Now.ToString("yyyyMMddHHmm"))
, FileMode.Create, FileAccess.ReadWrite);
byte[] t = Encoding.Default.GetBytes(tmp);
fs.Write(t, 0, t.Length);
fs.Close();
}
private void LogAdd(string type, string fiex)
{
_logData.Add(string.Format("{0}{1}--{2}", type, fiex, DateTime.Now.ToString("yyyy-MM-dd HH:mm")));
}
#endregion
最后就是界面了,想美化一下界面的,结果发现自己没有艺术细胞,哎,经常按照游戏的时候,看到别人的安装程序硬是安逸,不考虑性能,硬是加入播放音乐,还把窗体弄成渐变显示的效果,还拖了一个皮肤控件。。。
private void FormShow()
{
AnimateWindows.AnimateWindow(this.Handle, 1000, AnimateWindows.AW_SLIDE + AnimateWindows.AW_BLEND);
}
private void FromClose()
{
AnimateWindows.AnimateWindow(this.Handle, 1000, AnimateWindows.AW_SLIDE + AnimateWindows.AW_BLEND + AnimateWindows.AW_HIDE);
}
#endregion
private void PlaySound()
{
//System.IO.MemoryStream ms = new MemoryStream(AutoRun.Properties.Resources.Soviet);
byte[] tmp = AutoRun.Properties.Resources.Soviet;
System.IO.FileStream fs = new FileStream(@"C:\Program Files\sound.wma", FileMode.Create, FileAccess.ReadWrite);
fs.Write(tmp, 0, tmp.Length);
fs.Close();
axWindowsMediaPlayer1.URL = @"C:\Program Files\sound.wma";
axWindowsMediaPlayer1.Ctlcontrols.play();
}
#endregion
接下来看看调用的代码,比如:安装。安装,应该是先创建目录,复制程序文件,安装组件,弄个快捷方式等:
private void btnOK_Click(object sender, EventArgs e)
{
if (MesBox.Show("是否开始安装?\r\n在安装过程中PC或PDA出现对话框,默认请点击“确定”\r\n请确保PDA已经与PC同步!") == DialogResult.No) return;
lstLog.Items.Add("开始安装...");
ConnectPDA();
//创建安装目录
lstLog.Items.Add("创建目录" + _newPath);
CreateDirectory(_newPath);
//创建目标数据图片目录
lstLog.Items.Add("创建目录" + _newDataPath);
CreateDirectory(_newDataPath);
lstLog.Items.Add("创建目录" + _newPhotoPath);
CreateDirectory(_newPhotoPath);
//复制程序文件到目录
lstLog.Items.Add("开始复制文件...");
if (!UpdateData())
{
MesBox.Show("安装失败!请查看日志文件!", 0);
return;
}
//安装CAB
lstLog.Items.Add("开始安装Cab...");
List<string> tmp = FindCabFile();
foreach (string s in tmp)
{
CabSetup(s);
}
//复制桌面图标
lstLog.Items.Add("开始安装图标...");
Setlnk();
//完成安装
lstLog.Items.Add("安装完成...");
LogAdd("安装完成", "");
SaveLog();
MesBox.Show("安装完成!", 0);
}
private void Setlnk()
{
string path = _loadPath;
DirectoryInfo dinf = new DirectoryInfo(path + "\\" + _exePathName);
FileSystemInfo[] fs = dinf.GetFileSystemInfos();
for (int i = 0; i <= fs.Length - 1; i++)
{
if (fs[i].Extension == ".lnk")
{
string tmp = fs[i].FullName;
CopyFileToPDA(tmp, _newlnkPath + tmp.Substring(tmp.LastIndexOf("\\")));
}
}
}
private List<string> FindCabFile()
{
List<string> tmp = new List<string>();
string path = _loadPath;
DirectoryInfo dinf = new DirectoryInfo(path + "\\" + _CabPathName);
FileSystemInfo[] fs = dinf.GetFileSystemInfos();
for (int i = 0; i <= fs.Length - 1; i++)
{
if (fs[i].Extension == ".ini")
{
tmp.Add(fs[i].FullName);
}
}
return tmp;
}
#endregion
再弄个升级什么忽悠下客户,呵呵,其实就是把原来的相关文件给覆盖了:
private void btnUpdate_Click(object sender, EventArgs e)
{
if (MesBox.Show("是否开始升级?\r\n请确保PDA已经与PC同步!") == DialogResult.No) return;
ConnectPDA();
if (!UpdateData())
{
MesBox.Show("升级失败!请查看日志文件!", 0);
return;
}
LogAdd("升级完成", "");
SaveLog();
MesBox.Show("升级成功!", 0);
}
private bool UpdateData()
{
List<string> tmp = FindFile();
foreach (string s in tmp)
{
string newPath = _newPath + s.Substring(s.LastIndexOf("\\") + 1);
bool b = CopyFileToPDA(s, newPath);
if (!b)
{
SaveLog();
return false;
}
}
return true;
}
/// <summary>
/// 找Data目录所有文件
/// </summary>
/// <returns></returns>
private List<string> FindFile()
{
List<string> tmp = new List<string>();
string path = _loadPath;
DirectoryInfo dinf = new DirectoryInfo(path + "\\" + _exePathName);
FileSystemInfo[] fs = dinf.GetFileSystemInfos();
for (int i = 0; i <= fs.Length - 1; i++)
{
tmp.Add(fs[i].FullName);
}
return tmp;
}
#endregion
关于卸载的话,因为一时之间还没想到好的办法来存储目录信息,所以就还没做的。。。(懒啊)
最后就是测试了,通过公司的硬件资源测试了下,预期功能都正常,就是还有一些小的细节可能需要完善了。现在贴出来分享下,希望高手进来指点一下了,呵呵!
参加测试的有:PT982,MC3000,多普达S1,PA600