现在的位置: 首页 > 综合 > 正文

【原创】管道开发指南——Miken

2013年06月30日 ⁄ 综合 ⁄ 共 8829字 ⁄ 字号 评论关闭
§6.1 管道的作用
管道主要用于PalmOS平台上的应用程序与桌面计算机进行资料同步。当进行一个热同步操作时,热同步管理器将调用管道,保持桌面计算机与手持设备的资料同步,将手持设备的资料备份到桌面计算机,或者从桌面计算机下载资料到手持设备。
了解管道
一个标准的Windows管道是一个动态链接库,它提供热同步管理器的调用入口函数。在一个给定的热同步操作中可能与下面的部分或者所有部件相关:
热同步管理器(HotSync Manager):这个程序控制整个热同步过程。热同步管理器运行在桌面电脑的后台,监视特定的通信端口,以响应从PalmOS手持设备发来的请求。热同步管理器处理桌面电脑和手持设备基本的通信,控制一台桌面电脑多个用户的同步,安装新的应用程序和数据库到掌上设备,因为冷启动或者其他原因导致灾难性的数据丢失后来恢复掌上设备上的数据;
管道(Conduits):管道是一个插件模块,它处理掌上设备上的应用程序和桌面电脑数据源之间的数据交换。在一个热同步操作过程中,热同步管理器调用每一个注册的管道,完成相应的数据同步过程。一个管道不需要和用户进行任何的交互,就能完成修改桌面电脑、掌上设备或者两者的数据。当你设计一个管道时,不与用户进行任何交互是很重要的。当一个用户进行远程同步,他是没有办法去处理从管道得到的任何提示;
通告Dlls(Notifier DLLs):假如某个管道和桌面应用程序同时修改某数据,那么在同步过程中必须通知桌面应用程序不要对该数据操作,这样可以阻止数据被破坏或者产生记录副本。在热同步管理器调用管道去执行数据传输之前,管理器会为某些特殊的管道调用通告Dll。通告Dll依次把信息以桌面应用程序能够理解的格式传递给适当的桌面程序。这种处理的最好例子是“Palm Desktop”,它不允许用户在同步过程中修改任何数据。“Palm Desktop”之所以知道正在同步过程中,是因为有它自己的通告Dll-pdn20.dll 通知它;
Palm端应用程序:一般Palm端的应用程序是作为一个快速的数据采集工具,为桌面应用程序提供一些有用的数据。它也可以作为一个轻便的阅读器,随时查看从桌面下载的数据资料。要使它支持热同步处理,你不需要为它额外添加任何代码;
桌面应用程序:鉴于管道设计中固有的机动性,事实上任何桌面应用程序都可以和PalmOS掌上设备共享数据。桌面应用程序可以创建数据然后发送给掌上设备,处理从掌上设备得到的数据,或者和掌上设备共享数据。
同步管理器API:这组API提供桌面电脑和掌上设备使用管道通信的功能。不管掌上设备怎么和桌面电脑连接,这组API都能直接读和写掌上设备的数据;

热同步处理的步骤
当用户开始一个同步操作,不管是按下了底座的热同步按钮,还是点击了掌上设备热同步程序中的热同步按钮,同步管理器就开始工作了。下面的步骤大体上描述了整个热同步过程:
1、 用户确认和定位:每一个PalmOS掌上设备都有一个唯一的User ID与管理器相关联。如果掌上设备是第一次被用来进行同步操作,热同步管理器将提示你选择一个用户,这样当一台桌面电脑和多部掌上设备进行同步操作时,就可以保持数据的分离。在同步过程开始时,管理器要确保该UserID是合法的,然后定位到该用户在桌面电脑的路径。举个例子,我自己的用户路径就是c:/palm/Miken。许多管道保存他们的信息在这个子目录;
2、 决定同步类型:一个管道会执行两种同步操作中的某一种:慢同步和快同步。在慢同步中,管道会把掌上设备数据库的每一条记录和PC的数据源进行比较,而在快同步中,管道仅仅比较那些置了修改标志的记录;
假如掌上设备最后一次同步是在同一台PC,热同步管理器将通知管道执行快同步,否则将执行慢同步,因为管道此时不能依赖每条记录的修改标记了;
3、 桌面应用程序的通知:热同步管理器调用相应的通告Dll,以便让桌面应用程序知道热同步管理器是否正在修改PC和Palm共享的数据;
4、 管道安装:如果通告没有出现问题,同步管理器将返回掌上电脑每个应用程序的Creator ID。假如一个管道是为某一个特定的CreatorID安装,同步管理器将加载这个管道到一个将运行的模块列表。
同步管理器也浏览那些在掌上电脑上类型不是“DATA”的数据库。假如数据库设置了备份位,同步管理器就把这些数据库加入到一个列表,在同步过程中内建的备份管道将处理这个列表;
5、 安装:现在同步管理器可以使用它内置的管道去安装在桌面电脑队列里的任何数据库。一般这些数据库是由Palm的安装工具(instapp.exe)放入队列的。在Windows中,Palm安装工具将这些数据库拷贝到改用户目录的Install子目录下。譬如在我的电脑中等候安装的数据库都在c:/Palm /Miken/Install目录下;
6、 管道执行:同步管理器循环去处理在第四步已经准备好的管道列表,依次调用每一个管道去同步掌上设备和桌面电脑的数据;
7、 二次安装:在同步管理器3.0.1或者更高版本中,它将再次调用安装管道,这就给同步操作一个机会,使它可以得到任何管道安装队列里的任何数据库。这一步允许一个管道产生一个数据库,并且把它“推”给掌上设备,从Web或者其他网络源返回的信息对于管道来说是非常有用的。举个例子,AvantGo使用这个功能把最新下载的Web页安装到掌上设备;
8、 数据库备份:同步管理器调用备份管道,将第四步准备好的备份队列里的数据库存储到相应用户的Backup子目录下。举个例子,我的备份目录就是c:/Palm /Miken/Backup目录;
9、 同步信息更新:同步管理器已经完成了大部分任务,它会更新同步时间,PC ID和用户ID,如果有必要,也将更新掌上设备的同步应用程序。同步管理器还将发送给掌上设备一个精简的同步日志文件,用户通过这个日志文件可以知道同步操作中产生的错误和警告。
10、 第二次桌面应用程序通知:同步管理器第二次调用通告Dll,来检查同步操作是否完成,桌面应用程序是否可以安全的修改共享数据源;
11、 掌上应用程序通告:PalmOS给那些新安装的和在同步过程中数据被修改的应用程序发出通告,通常是发送sysAppLaunchCmdSyncNotify消息给它们。一些应用程序需要立即执行一些操作,譬如重启警告,注册接受到的Beam数据;

§6.2管道程序的开发
本节我们将重点讲述怎样使用Microsoft Visual C++6.0和CDK4.01开发Windows上的管道程序。我们假定您熟悉面向对象的程序设计思想,能够使用Visual C++进行软件开发,有动态链接库的开发经验。
管道开发工具包(CDK)可以从Palm的官方网站免费下载,它包含所有的模板,对象类和一些必需的文档,你利用这个开发包可以轻松创建一个Mac OS和Windows平台的管道。如果您开发Mac OS平台的管道,你需要安装Metrowerks CodeWarrior3.0以上版本。开发Windows平台的管道,你有两种选择:
1、使用Microsoft Visual C++ 6.0 和Windows版的CDK
2、Symantec Visual Cafe Pro for Java 和 the CDK Java Edition。 CDK Java版在Microsoft Visual J++ 1.1已经测试,但是Visual Cafe Pro由Palm公司的开发平台支持。
随书附带的光盘包括Mas OS平台的CDK4.0版、Windows平台的CDK和Java版的CDK。
我们需要做些什么:
一个功能完整的管道Dll,需要我们向同步管理器提供以下接口函数的具体实现:
ExportFunc long OpenConduit(PROGRESSFN pFn, CSyncProperties& rProps);
ExportFunc long GetConduitName(char* pszName,WORD nLen);
ExportFunc DWORD GetConduitVersion();
ExportFunc long ConfigureConduit(CSyncPreference& pref);
ExportFunc long GetConduitInfo(ConduitInfoEnum infoType, void *pInArgs, void *pOut, DWORD *pdwOutSize);
ExportFunc long CfgConduit( ConduitCfgEnum cfgType, void *pArgs, DWORD *pdwArgsSize);

我来具体讲讲这几个函数的作用:
OpenConduit:打开管道后进行的操作,是管道真正同步数据的部分,你需要根据
rProps.m_SyncType判断同步的方向,然后在该函数的实现中添加数据实现同步的代码。在你的开发过程中,你只要将这个函数实现就行了,其他可以使用向导生成的代码。当然如果有必要,你也可以修改其他接口函数的实现代码;
GetConduitName:将管道名返回给管理器。如果你使用管道配置工具为你的管道取了名字,同步管理器就不再调用这个函数。你在GetConduitInfo中加入了对infoTypeEConduitName的处理,它也不会被调用;
GetConduitVersion:取出你的管道的版本号;
ConfigureConduitCfgConduit:是当你改变该管道的配置信息时被调用的。当你选取同步管理器菜单的“Custom”项时,会出现用户自定义的对话框。你选取你的管道,按“Change”按钮,这时就会调用这个函数。我一般只实现了CfgConduit,程序运行的也很稳定;
GetConduitInfo:你可以得到缺省的同步类型,用户名,用户ID,管道的CreatorID等等信息。当你使用向导为你新建一个管道工程的时候,你会发现这几个接口函数都已经为你准备好了,你只要根据你的需要添加一些代码就行了。

使用管道向导:打开VisualC++6.0,选择File菜单的New项,创建一个新的工程,如图6-1所示

图6-1 使用Conduit向导新建工程
我们将创建一个名为FirstConduit的管道工程。按下OK按钮,将出现向导第一步的界面,如图6-2所示,

图6-2 Conduit向导第一步
Generic类型将提供Palm地址本、日程表、记事本、任务(这四个程序都是PalmOS附带的)和一般类型五种选择,它向你提供一般的管道基本类接口;MFC类型的也类似,只是它使你可以在程序中使用Palm的MFC内库;第三种类型向你提供建立一个管道Dll的基本框架,包括你需要的Dll入口点位置,你通过调用App函数可以更加灵活的进行管道Dll的开发,同时工程的结构也比较简单,所以我们在本章中先介绍使用这种类型的开发方法,选择“Conduit entry points only(no sync logic)”,按下“Next”按钮,进入第二步。在这一步中你需要选择你的管道的特征。”Archiving”项可以让你能够对一个与桌面数据源分离的文件进行读写操作,“Sync action configuration dialog”则在程序中加入管道同步方向选择的对话框,选择第三项,进入第三步。直接按下Finish按钮,我们的工程就创建好了。

图6-3 Conduit向导第二步

图6-4 Conduit向导第三步
管道编码:在这个例子中我只是让你知道管道已经运行了,所以仅仅在Log中输出一句同步成功的信息。你只需要做以下两步就够了:
1、在FistConduitGenCond.cpp的开始添加 #include <hslog.h>
2、修改OpenConduit入口点函数:
ExportFunc long OpenConduit(PROGRESSFN pFn, CSyncProperties& rProps)
{
long retval = -1;
if (pFn)
{
// TODO - create your own custom sync class, and run it
}
LogAddEntry("My First Conduit", slSyncFinished, FALSE);
return(0);
}

工程环境设置:选择Project菜单的Setting项,进入项目设置对话框,如图6-5,

图6-5 项目环境变量设置1
指定同步管理器的路径和文件名,以便我们可以直接执行管理器,调试我们的管道Dll。在该对话框中有一项“Program arguments”,你可以加入“-ic”开关,这样可以启用CDK自带的管道跟踪器。我在开发过程中使用了我自己的跟踪器,所以关闭了这项功能。我的跟踪器你可以在光盘中得到。同时你也需要改变Dll的输出路径,如图6-6所示。当然如果你的CDK安装目录与我不同的话,你需要做相应的修改。
管道的手工安装:我们在管道的发行中,是不可能要让用户手工安装的,我们需要另外写一个自动安装管道的程序。在这里我们只是为了方便我们的开发,使用手工的安装方法。在目录

图6-6 项目环境变量设置2
/CDK401/Common/Bin/C4.01,我们可以得到管道配置的工具“CondCfg.exe”,执行它,出现如图6-7

图6-7 管道配置工具
的界面,按“Add”按钮,将我们新的管道添加进去。具体的配置如图6-8所示。需要顺便提一下的是,
其中的“Creator ID”是与掌上设备应用程序.prc的Creator ID相匹配。
到目前位置,PC端的已经完成(当然在同步过程中它没有传输我们的数据,我们需要编写代码完成),现在我们还要写一个相应的Palm的应用程序。
Palm端的应用程序:使用CodeWarrior创建一个新的工程,按照图6-9修改Creator ID。编译成.prc.

图6-8 新管道的配置

图6-9 改变.prc的Creator ID
测试管道:将.prc先同步到Palm上,选择VC集成开发环境Build菜单的Execute项,执行装载了我们管道的管理器,按下同步按钮,则出现如图6-10的界面,

图6-10 同步处理过程中
表示同步正在进行中。同步完成后,这个界面就会自动消失。同步完成后,右键点击托盘中的同步管理器的图标,在出现的菜单中选择“View Log…”项,你将在Log文件中看到“OK My First Conduit”,这说明我们的管道运行正确了。
如果你已经做到这一步了,恭喜你,你已经学会了管道开发的基本步骤!第四节将以一个具体实例来详细讲解一个进行数据同步功能的管道。如果你理解了第四节,你就已经完全有能力开发完整的管道商业程序了。

§6.3 管道开发过程中的调试技巧
我之所以在进行具体的讲解管道开发之前,谈程序调试的技巧,是因为我深知作为一名程序员,好的调试方法无疑会使他的开发工作事半功倍,而且懂得调试程序也是一名程序员必备的素质。我在这节中将向你讲讲两个非常有用的技巧:模拟器直接调试管道和管道的跟踪。

模拟器直接调试管道:你需要在模拟器中进行以下设置:
1、打开模拟器同步程序的菜单,如图6-11;

图6-11 同步程序的菜单
2、选择“调制解调器同步设置”项,如图6-12进行设置,确定;

图6-12修改调制解调器参数
3、选择菜单的“局域网同步设置“项,如图6-13进行设置,确定;

图6-13局域网同步参数
4、选择菜单的“主机设置“项,如图6-14进行设置,确定;

图6-14 主机设置
5、选择模拟器同步程序“Modem热同步”下的“输入电话”按钮,在弹出的“电话设置”对话框中什么也不填,直接按下“确定”按钮,出现如图6-15的界面;

图6-15 设置Modem热同步
6、在模拟器的右键菜单中选择“settings”的“Properties”项,按照如图6-16进行设置;

图6-16 模拟器的属性设置
7、点击托盘中同步管理器的图标,从菜单中选择“Network”。
现在你就可以直接按照如图6-17按下“Modem热同步”图标,

图6-17 使用模拟器同步
进行模拟器直接同步了。这样如果你没有机器,你也可以学习管道技术,有机器的朋友用模拟器调试也方便的多。
管道的跟踪:因为管道实际上就是一个Dll,所以给我们的调试带来了一定的麻烦,当然单步跟踪也是有效的。而一个好的调试方法无疑会提高我们的开发效率,所以掌握一种好的调试方法是必须的。如果你是VisualC++高手,你一定有比我更好的办法,你可以直接跳到下一节。我介绍的方法比较适合VisualC++初学者。
在光盘中有我自己写的一个调试器(Debugger.exe),我将简单的教你使用它。
1、将头文件Miken.h拷入你的工程目录,选择Project菜单的“Add To Project”项,将这个文件加入到你的工程;
2、在FistConduitGenCond.cpp文件的开始加入对它的引用: #include “Miken.h;
3、选择”Project”的“Settings”项,在出现的对话框中选中“C/C++”标签页,在“Preprocessor definitions”下的编辑框中添加“_MikenDebug”宏定义。这是一个开关,如果没有这个宏,则不会出现任何调试信息。所以你可以在调试时加上这个宏,而管道调试成功,则去掉这个宏,重新编译一下你的工程,就不会再有任何调试信息了。
4、我向你提供了四个宏接口,M_Debug0、M_Debug1、M_Debug2、M_Debug3,如果需要你可以在头文件中扩充。如果你需要查看程序某一行的运行结果,你可以加入:
M_Debug0("哈哈,我的管道来了",0);
M_Debug1("现在你在同步数据库的第%d条记录",m_RecordNo,1);
M_Debug2("字段%s,值为:%d", m_FieldName,m_FieldValue,2);
M_Debug3("第%d条记录,字段%s,值%d", m_ RecordNo, m_FieldName, m_FieldValue,3);
宏接口的最后一个参数是表示以什么颜色显示字符串信息,分别是:
0:RGB(0,0,255) 1:RGB(27,47,247) 2:RGB(0,94,0) 3:RGB(255,0,0) 其他数字:RGB(0,255,0)
这样当调试信息太多时,你可以以颜色区分它们。如用3表示错误信息,则你在调试器中看到红色字符信息就表示有错误发生。

§6.4 一个复杂管道的实现
下面我将以一个医院住院部的巡房系统为例,向你讲述做一个管道的详细步骤。为了使程序简洁,让读者容易理解,我只选取两张表,且每张表只取三个字段,必要之处我给出注释。在例子中,我只编写了从Palm端读写数据库的代码,对PC端的数据库操作,你可以使用ADO、ODBC和DAO等等,具体编码你可以参考相关书籍。
Palm端应用程序:完整应用程序可以到光盘上得到,这里我只列出表结构:
typedef struct //病人病历表
{
int PatientSex;
//性别,0: 男 1:女
int PatientAge; //年龄
char HistoryNo[7];//住院号,主关键字
}CaseHistory,*pCaseHistory;

typedef struct //长期医嘱表
{
char HistoryNo[7];
//住院号
char PatientName[9]; //姓名
char Section[5]; //科别

}LongAdvice,*pLongAdvice;

管道的实现
1、参照6.2节用向导生成一个新的工程,取名为Hospital;
2、参照6.3节中“管道的跟踪”部分,将“Miken.h”加入到你的工程,在HospitalGenCond.cpp
的开始处引用它,并且添加宏定义_MikenDebug;
3、表结构定义, caseTemp和adviceTemp为两个临时结构:
typedef struct //病人病历表
{
long PatientSex;
//性别,0: 男 1:女

long PatientAge;
//年龄
char* HistoryNo; //住院号,主关键字
}CaseHistory,*pCaseHistory;

typedef struct //长期医嘱表
{
char* HistoryNo;
//住院号
char* PatientName; //姓名
char* Section; //科别
}LongAdvice,*pLongAdvice;

typedef struct
{
char point[1];
}caseTemp;

typedef struct
{
long sex;
long age;
char point[1];
}adviceTemp;
4、修改OpenConduit部分:
ExportFunc long OpenConduit(PROGRESSFN pFn, CSyncProperties& rProps)
{
long retval = -1;
switch (rProps.m_SyncType)
//得到现在设定的同步方向
{
case ePCtoHH:
//PC到Palm
M_Debug("你现在的操作是 PC-->Palm",0);
retval = CopyPCtoPalm(rProps);
break;
case eHHtoPC:
//Palm到PC
M_Debug("你现在的操作是 Palm-->PC",0);
retval = CopyPalmtoPC(rProps);
break;
case eSlow:
//慢同步和快同步

break;
case eFast:
break;
}
return(retval);
}

5、自定义函数CopyPCtoPalmCopyPalmtoPC的实现代码,见光盘的工程。

作者 webmaster   

http://www.msale.net/index.php?page=4&mode=article&k=9

抱歉!评论已关闭.