milkyway的窝

最初想法的诞生地

 

RAPI初始化算法和SAMPLE CODE

来自 http://www.cnblogs.com/walzer/archive/2006/02/05/325605.html

作者:Walzer
日期:2005.12.12

RAPI全写为Remote Application Interface, 就是PC端调用这组API, 通过ActiveSync来操作TARGET端WindowsCE作业. 这个功能估计以后在WINCE或WIN MOBILE的应用上会用到许多

我今天修改了同事留下的Updateboot.exe的代码, 改进蓝牙读写的模块. 这个地方我们用到了RAPI, 看一下他们在程序中初始化RAPI的做法

 HRESULT hRapiResult;
 hRapiResult = CeRapiInit();
 if(hRapiResult != S_OK)
 {
     m_ValueEdit.SetWindowText((LPCTSTR)"初始化RAPI失败");
     return;
 }

看起来是平淡无奇, 实际上单步一下就可以发现运行到CeRapiInit()时, 程序就BLOCK在这里了,死活走不下去, 并没有达到 if(hRapiResult != S_OK)的预期目的. 我查了一下CeRapiInit()的说明:

A call to CeRapiInit does not return until the connection is made, an error occurs, or another thread calls CeRapiUninit.

也就是说像我现在并没有把板子和PC相连并启动ACTIVE SYNC时, 这个CeRapiInit()是肯定赖着不走了, 程序会死在这里. (鄙视一下谁写的代码,这个坑好大啊)  因此想到了重新创立个等待进程调用CeRapiUninit来干掉它. 不过这样做显然不厚道, 创立进程需要占用更多的内存. 所以用了上句说明的下半段:

The CeRapiInitEx function does not block the calling thread. Instead, it uses an event to signal when initialization is complete.

建立个事件, 用WaitForSingleObject来等他, 超时就BYEBYE了. 贡献自己写的如下代码, 以后RAPI INIT可以参考

BOOL RapiInitialzation()
{
    RAPIINIT struRapiInit;   
//这个是CeRapiInitEx函数要求的入口参数
    DWORD dwWaitResult = 0;  //等待初始化完成事件的变量
    HRESULT hRapiResult = NULL; //CeRapiInitEx的返回HANDLE

    
if ( m_bRapiInitFlag == FALSE ) //全局的一个FLAG,如果初始化过就不再重复了
    {
        struRapiInit.cbSize 
= sizeof(RAPIINIT);  //填满该结构体仅有的三个成员
        struRapiInit.hrRapiInit = NULL;  //明知是输出参数也顺手填一下, 我以前吃过亏, 惊弓之鸟
        struRapiInit.heRapiInit = NULL;

        hRapiResult 
= CeRapiInitEx(&struRapiInit);  //关键点

        m_ValueEdit.SetWindowText((LPCTSTR)
"Wait 2 second for RapiInit"); //后面2秒程序要顿一下了, 得告诉用户.  m_ValutEdit和对话框里一个IDC_STATIC关联了.
        dwWaitResult = WaitForSingleObject(struRapiInit.heRapiInit, 2000);  //关键点

        
if( hRapiResult == S_OK && 
            struRapiInit.hrRapiInit 
== S_OK &&
            dwWaitResult 
!= WAIT_TIMEOUT)    //保守起见, 三个返回值都判断
        {
           m_bRapiInitFlag 
= TRUE;
           
return TRUE;
        }
        
else
        {
            m_ValueEdit.SetWindowText((LPCTSTR)
"The initialization of RAPI falied, you need to install an ActiveSync or connect the IPTV to PC");   //一般是没连接导致, 当然也可能用户没装ActiveSync
           return FALSE;
        }
    }
    
else
    {
         m_bRapiInitFlag 
= TRUE;
         
return TRUE;
    }
}

posted on 2007-01-16 09:42 milkyway 阅读(2986) 评论(1)  编辑 收藏 引用 所属分类: wince(别人的文章技巧总结)

评论

# re: RAPI初始化算法和SAMPLE CODE 2007-01-16 09:44 相思酸中有甜

另一篇文章 http://www.cnblogs.com/yakin/archive/2005/07/20/196569.aspx

RAPI:Remote Application Programming Interface

RAPI是基于ActiveSync的.所以在Device要加ActiveSync的组件,同时PC端要装ActiveSync。这样Device是server端,PC是Client端。
我是用VC6.0作为工具编写PC端APP来控制Device的。当然我们原来的VC中并没有包含RAPI的相关API实现,所以要添加RAPI的相关lib文件和头文件:RAPI.lib和RAPI.h。同时要在project\settings里面设置连接RAPI.lib。
相关编程环境建立后就可以开始编程了。

1) 初始化RAPI。
开始编写的时候忘了这一点,结果总是不行。后来在网上狂搜,搜到了微软日本的一篇相关文章,才搞明白。日语里面有很多汉字,大体还知道他在说什么,看来武大郎的故事有可能是真的哦!
HRESULT hr = CeRapiInit(); //must initilize RAPI first before performing other operation.
if ( hr != ERROR_SUCCESS )
{ return; }

2) 下面以修改蓝牙注册表为例:
打开注册表:
wcscpy((wchar_t *)Name, L"Software\\Microsoft\\Bluetooth\\HCI\\psKey");
if ((lRet = CeRegOpenKeyEx(HKEY_LOCAL_MACHINE, (wchar_t *)Name, 0, 0, &hChildKey)) == ERROR_SUCCESS)
{.......}
RAPI的函数都使用unicode,所以所有字符串都必须是unicode形式。这一点要注意。

查询注册表的值:
if (ERROR_SUCCESS == (lRet = CeRegQueryValueEx(hChildKey,
L"Pskey2", NULL, &dwType, (LPBYTE)Data,
&dwSize)))

修改注册表的值:
if(ERROR_SUCCESS == (lRet = CeRegSetValueEx(hChildKey,
L"Pskey2", NULL, NULL, (LPBYTE)&wData,
sizeof(wData))))

然后关闭注册表项:
CeRegCloseKey(hChildKey);

3) 关闭RAPI
CeRapiUninit();


我对RAPI的了解只是皮毛。随着了解的深入,我们可以用它写出强大的应用程序,比如完美的通过ActiveSync的升级程序。

  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

公告

随笔皆原创,文章乃转载. 欢迎留言!

常用链接

留言簿(37)

随笔分类(104)

随笔档案(101)

文章分类(51)

文章档案(53)

wince牛人

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜