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
OpenNETCF.Desktop.Communication;
using
System.Collections;
using
System.IO;
using
System.Threading;
接下来就是实例化RAPI类(主角),然后就是声明点全局变量来使用:
#region
变量
//
源文件目录 也是程序启动目录
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的复制文件,删除一些常用操作的方法:
#region
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方法是自定义安装日志,用于安装失败时,叫客户发来研究的,呵呵:
#region
日志操作封装
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
最后就是界面了,想美化一下界面的,结果发现自己没有艺术细胞,哎,经常按照游戏的时候,看到别人的安装程序硬是安逸,不考虑性能,硬是加入播放音乐,还把窗体弄成渐变显示的效果,还拖了一个皮肤控件。。。
#region
窗体打开关闭效果
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
#region
播放声音
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
接下来看看调用的代码,比如:安装。安装,应该是先创建目录,复制程序文件,安装组件,弄个快捷方式等:
#region
安装
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
再弄个升级什么忽悠下客户,呵呵,其实就是把原来的相关文件给覆盖了:
#region
升级
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