用CAPI實現notes的郵件提醒

Lotus Domino/Notes是美國蓮花公司出的企業通訊和羣件服務平臺。但由於其本身提供的開發工具的限制,在Notes中實現系統級功能十分困難。比如在Notes中,不能通過公式或腳本來得到一個數據庫的未讀文檔的數量和其內容。但這個未讀文檔數的小功能在做有些方面是十分有用的,例如我們可以根據這個未讀文檔數來做個提醒功能,提醒用戶該進行某類工作如文件簽發等。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

 

發佈了24 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章