Lotus Domino/Notes是美国莲花公司出的企业通讯和群件服务平台。但由于其本身提供的开发工具的限制,在Notes中实现系统级功能十分困难。比如在Notes中,不能通过公式或脚本来得到一个
数据库的未读文档的数量和其内容。
经验:
1、在用NSFDbGetUnreadNoteTable函数取得未读文档列表时,发现在读取本地 数据库时,未读文档列表是正确的,而当读取 服务器上数据库时(即使你在本地做个复本,再读本地复本的未读文档列表也是一样),总是返回总文档数,即使在用NSFDbUpdateUnread函数更新了未读文档列表后仍是如此,只有在用文档集函数NIFUpdateCollection更新后才能得到真正的未读文档数。
2、在上面得到的未读文档数是整个数据库的全部未读文档,应和视图文档进行对比后才真正得到某视图或文件夹的未读文档。
3、Notes在处理中文时,要求每个中文前都必须有0x13字符才行。所以在处理中文数据库方面,自己还要自行处理中文名问题。
4、要进一步得到文档的字段内容,可以用将以下函数段加入上述函数中。
5、本文是实现该功能的主要函数,你可以将其写成一个DLL程序,那么就可以在你的Notes Script脚本程序中来使用它。你也可以利用它写成一个独立的应用程序,你就可以在Notes外部运行它了。
本程序在Windows2000 Server, Visual C++ 6.0下调试通过。如果本文有任何问题,请与作者联系。
参考文献:
Lotus C API 5.0.7 User Guide
Lotus C API 5.0.7 Reference
但这个未读文档数的小功能在做有些方面是
十分有用的,例如我们可以根据这个未读文档数来做个提醒功能,提醒用户该进行某类工作如文件签发等。Notes系统本身有个Minder的程序,它是在有新邮件来到的时候,提醒用户,并可提供一些基本的信息:来信人,标题等。我们也可以这样做(当然利用未读文档数来做不是完美,如果你有兴趣,你可以试试做个数据库钩子程序来实现,但总的来说,利用未读文档数来做较为简单。)。 本文就是讨论如何利用Notes提供的C API来实现读取一个Notes数据库的未读文档数和其信息。因为利用的是C API,所以我们的开发语言是C。开发工具我们选用的是VC++ 6.0。我们需要借助的是Notes本身提供的C API函数。Notes的大部分API都封装在nNotes.dll文件中。其中包括有ACL,Database,User,Document,Item等各个方面的API函数。它不光能实现几乎所有在Notes中实现的功能,它还提供了其他在Notes中难以想象的功能(换句话说,你可以自己写自己特有的Notes桌面程序而不再使用Notes.exe。当然它的功能还远不止这点)。利用Notes API包,我们可以做以下的程序: 1、独立应用程序。 2、DOMINO 服务器的扩展插入服务(add-in tasks)。 3、NOTES 客户机的菜单扩展插入(menu add-ins)。 4、NOTES 客户机可动态加载的函数库。 5、数据库的钩子驱动程序(HOOK Drivers)。 6、扩展管理程序的钩子函数库。 7、非NOTES数据库的驱动程序。 下面简单介绍一下我们后面会涉及的主要的Notes API函数: NotesInitExtended:初始化Notes环境,应在所有Notes API函数调用前初始化系统。 NSFDbOpen:打开指定的Notes数据库。 NSFDbClose:关闭指定的Notes数据库。 NSFDbGetUnreadNoteTable:取得指定数据库内的未读文档列表。 NSFDbUpdateUnread:更新数据库的未读文档列表。 NIFFindView:取得数据库内的指定视图或文件夹。 NIFOpenCollection:取得指定视图或文件夹的所有文档。 NIFUpdateCollection:更新指定视图或文件夹的所有文档。 NIFCloseCollection:关闭文档集。 NIFReadEntries:读取文档集的指定文档。 NSFNoteOpen:打开指定文档。 NSFItemGetText:取得文档的指定字段值。 程序流程: 数据库中有张类型为IDTable的未读文档列表,其中包含了该数据库的带有未读标志的文档号。这张表存储在数据库中和客户机的Desktop.dsk文件中。当然,在数据库和文件中的这张表是一样的。当他们不一致时,则在你打开数据库时,它们会自动同步,使他们保持一样。 我们就是要取得这张未读文档表,再统计一下这张表中有多少项,就知道了数据库中多少文档带有未读标志。我们还可以在此基础上取得该文档的一些具体信息。但这张表是整个数据库的未读文档列表,我们怎么得到某个视图或文件夹的未读文档数和信息呢?实际上,这才是我们真正关心的。我们可以再找到某个视图和文件夹的文档列表,再与上面的未读文档列表进行一一比较,相同的则是该视图或文件夹的未读文档列表。 |
主要程序如下:
////////////////////////////////////////////////////// // InitNotes:初始化Notes环境,打开数据库 // szServerName:服务器名 // szDBName:数据库名 // szDirectory:Notes系统目录 // 返回值:1 - 成功 // 0 - 失败 int CNotes::InitNotes(char *szServerName,char *szDBName,char *szDirectory) { STATUS status; char szPathName[MAX_PATH]; char szpInitPara[1][260]; // 数据库路径名=服务器名+“!!”+数据库名 if (strlen(szServerName)==0) strcpy(szPathName,szDBName); else { strcpy(szPathName,szServerName); strcat(szPathName,"!!"); strcat(szPathName,szDBName); } strcpy(szpInitPara[0],szDirectory); if (!m_bOpened) NotesInitExtended(1,(char**)szpInitPara); // 初始化Notes环境 status=NSFDbOpen(szPathName,&hDb); // 打开数据库 if (status!=NOERROR) { m_bOpened=false; return 0; } m_bOpened=true; return 1; } /////////////////////////////////////////////////// // GetUnread:取得指定视图或文件夹中的未读文档数 // szViewName:视图或文件夹名 // 返回值:-1 - 失败 // 其他 - 未读文档数 int CNotes::GetUnread(char *szViewName) { STATUS status; char szUserName[MAX_PATH]; status=SECKFMGetUserName(szUserName); // 得到当前用户名 if (status!=NOERROR) { m_bGetUnread=false; return -1; } status=NSFDbGetUnreadNoteTable(hDb,szUserName,_ strlen(szUserName),true,&hTable); // 取得数据库的未读文档列表 if (status!=NOERROR) { m_bGetUnread=false; return -1; } if (hTable==NULL) { m_bGetUnread=false; return -1; } status=NSFDbUpdateUnread(hDb,hTable); // 更新未读文档列表 if (status!=NOERROR) { OSMemFree(hTable); m_bGetUnread=false; return -1; } status = NIFFindView(hDb, szViewName, &ViewID); file://得到数据库的某视图或文件夹 if (status!=NOERROR) { OSMemFree(hTable); m_bGetUnread=false; return -1; } status=NIFOpenCollection(hDb,hDb,ViewID,0,hTable,_ &hCollection,NULL,NULL,NULL,NULL); if (status!=NOERROR) { OSMemFree(hTable); m_bGetUnread=false; return -1; } status =NIFUpdateCollection(hCollection); if (status!=NOERROR) { NIFCloseCollection(hCollection); OSMemFree(hTable); m_bGetUnread=false; return -1; } COLLECTIONPOSITION CollPosition; CollPosition.Level = 0; CollPosition.Tumbler[0] = 0; HANDLE hBuffer; DWORD NotesFound; WORD SignalFlags; Status=NIFReadEntries(hCollection,&CollPosition,_ NAVIGATE_NEXT,1L,NAVIGATE_NEXT,0xFFFF,READ_MASK_NOTEID,_ &hBuffer,NULL,NULL,&NotesFound,&SignalFlags); if (status!=NOERROR) { NIFCloseCollection(hCollection); OSMemFree(hTable); m_bGetUnread=false; return -1; } int iViewUnread=0; NOTEID NoteID; BOOL fFirst=TRUE; unsigned int i; NOTEID* IdList; if (hBuffer != NULLHANDLE) { IdList = (NOTEID far *)OSLockObject(hBuffer); while(IDScan(hTable, fFirst, &NoteID)) // 依次取得hTable表中的文档号 { fFirst = FALSE; for (i=0; i if (NoteID==IdList[i]) { iViewUnread++; break; } } OSUnlockObject(hBuffer); OSMemFree(hBuffer); } NIFCloseCollection(hCollection); OSMemFree(hTable); m_bGetUnread=true; return iViewUnread; } ////////////////////////////////////////// // CloseNotes:关闭Notes数据库 void CNotes::CloseNotes() { if (m_bOpened) NSFDbClose(hDb); m_bOpened=false; m_bGetUnread=false; } |
1、在用NSFDbGetUnreadNoteTable函数取得未读文档列表时,发现在读取本地 数据库时,未读文档列表是正确的,而当读取 服务器上数据库时(即使你在本地做个复本,再读本地复本的未读文档列表也是一样),总是返回总文档数,即使在用NSFDbUpdateUnread函数更新了未读文档列表后仍是如此,只有在用文档集函数NIFUpdateCollection更新后才能得到真正的未读文档数。
2、在上面得到的未读文档数是整个数据库的全部未读文档,应和视图文档进行对比后才真正得到某视图或文件夹的未读文档。
3、Notes在处理中文时,要求每个中文前都必须有0x13字符才行。所以在处理中文数据库方面,自己还要自行处理中文名问题。
4、要进一步得到文档的字段内容,可以用将以下函数段加入上述函数中。
BOOL fFirst = TRUE; int j=0; NOTEHANDLE noteHandle; while(IDScan(hTable, fFirst, &NoteID)) { fFirst = FALSE; for (i=0; i if (NoteID==IdList[i]) { if (NSFNoteOpen(hDb, NoteID,0, ¬eHandle)==NOERROR) { NSFItemGetText(noteHandle,szItemName,Buffer[j],MAX_PATH); } j++; break; } } |
5、本文是实现该功能的主要函数,你可以将其写成一个DLL程序,那么就可以在你的Notes Script脚本程序中来使用它。你也可以利用它写成一个独立的应用程序,你就可以在Notes外部运行它了。
本程序在Windows2000 Server, Visual C++ 6.0下调试通过。如果本文有任何问题,请与作者联系。
参考文献:
Lotus C API 5.0.7 User Guide
Lotus C API 5.0.7 Reference