Lotus C++ Api

Тема в разделе "Lotus - Программирование", создана пользователем SparkLone, 21 фев 2008.

  1. SparkLone

    SparkLone Гость

    Доброго,
    Кто нибудь имеет опыт работы с сабжем?
    99 процентов кода уже работает, но при попытке сохранить LNNote выкидывается странное сообщение
    "Error: Signature on document is invalid (inconsistent field signatures)" и не сохраняет изменения.
    Мне надо по сути изменить Database Script, другого пути кроме как перебор всех LNNote что то не нашел.. Читает, а вот сохранить не получается..
     
  2. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    кроме замены исходника в $DBScript его еще откомпилировать нужно и положить $DBScript_O, оба эти поля после изменения должны быть подписаны..
     
  3. SparkLone

    SparkLone Гость

    Для: Kee_Keekkenen
    Точно, видел такой LNNote, правда даже подумать не мог что там что то откомпилированное лежит...
    Не могли бы вы рассказать поподробней, как программно откомпилить, подписать (кем лучше подписывать), желательно с примером кода? Информации в инете практически ноль по C++ Api для лотуса.. (
     
  4. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    для компиляции скриптов есть пара функций NSFNoteLSCompile и NSFNoteLSCompileExt это C Api функции, а ты как я понимаю на на С++ пишешь.. как это писать я не знаю.. в LS в классе NotesItem есть метод Sign (NSFNoteSignExt, NSFNoteSignExt3 в C Api)..
     
  5. SparkLone

    SparkLone Гость

    Для: Kee_Keekkenen
    Да.. Что то я таких классов в C++ API не нашел (
    Охх.. Не было печали, как бы не пришлось все под C API переписывать и не дай бог если в нем нет того что есть в C++ API и нужно будет в проекте..
    Спасибо за наводку, буду ковырять.
     
  6. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    не волнуйся все там есть..
     
  7. SparkLone

    SparkLone Гость

    Для: Kee_Keekkenen
    Эхх.. Чем бы программист не занимался, лишь бы за***лся.. Действительно есть такая функция NSFNoteLSCompile. По документации есть только в C API, поматерившись, остыв, решил проверить навскидку. Оказалось что хотя в хелпе нигде не указано, но из под C++ API тоже можно ее вызывать.
    Код (Text):
        note.GetItems(&items);
    for (j = 0; j < items.GetCount(); j++)
    {
    item = items[j];
    if(item.GetName()== "$DBScript")
    {
    text = item;
    LNString lns(GetFileContent("dbscript.txt").c_str());
    text.SetValue(lns);
    try
    {
    note.Sign();                                                note.Save();
    nHandle = note.GetNoteHandle();
    STATUS stat = NSFNoteLSCompile(db.GetDatabaseHandle(), nHandle, 0);
    if (stat=NSFNoteUpdate(nHandle,0))
    {
    printf("Error: can't update note after LS Compilen");
    }
    break;
    }
    catch (LNSTATUS lnerror)
    {
    ShowError(lnerror);
    }
    }
    }
    note.Close();
    Все отрабатывает даже без ошибок.. Но, после этого пытаюсь открыть базу - ловлю ошибку
    ---------------------------
    Lotus Notes
    ---------------------------
    Generic LSE Failure (no more info!)
    ---------------------------
    OK
    ---------------------------

    Слов нет, одни эмоции (
     
  8. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    может нужно подписывать и сохранять после обновления нота ?!
     
  9. SparkLone

    SparkLone Гость

    Не..
    Если вызывать
    Код (Text):
    STATUS stat = NSFNoteLSCompile(db.GetDatabaseHandle(), nHandle, 0);
    note.Sign();
    При sign'е вылетает "Error: Object has not been initialized"
     
  10. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    по моему вот такой порядок функций должен быть..

    WinNSFNoteOpenByUNID(m_objDbDesign.dbhandle, aUnid,0 , hNote)
    WinNSFNoteLSCompile(m_objDbDesign.dbhandle,hNote,0)
    WinNSFNoteSign(hNote)
    WinNSFNoteUpdate(hNote,0)
    WinNSFNoteClose(hNote)
     
  11. SparkLone

    SparkLone Гость

    Для: Kee_Keekkenen
    По моему та же фигня выходит.. не могу уверять наверняка, т.к. использую все таки C++ API, посему немного переделал, вместо твоего вариант сделал что то вроде:
    Код (Text):
        NOTEHANDLE hNote;
    HANDLE dbHandle;
    dbHandle = db.GetDatabaseHandle(TRUE);
    LNNote note = GetDBScriptNode(db); //моя функция
    hNote = note.GetNoteHandle(TRUE);
    ... код изменяющий скрипты..
    NSFNoteLSCompile(dbHandle,hNote,0);
    NSFNoteSign(hNote);
    NSFNoteUpdate(hNote,0);
    note.close();
    db.close();
    В процессе выполнения - ни одного warning'а, все отрабатывает чисто и результат все тот же: "Generic LSE Failure (no more info!)". Останавливаю сервер, через дизайнер смотрю базу - все скрипты слетели (хотя програмным кодом до сих пор видяться нормально).

    Может конечно дело в том как меняются сорцы скриптов, но иначе прийдется переходить и дальше на C API.. Надо будет попробовать менять скрипты через C API, если не выйдет - накатать прототип полностью на C API..
     
  12. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    1. а если руками в дизайнере этот код вставить и откомпилировать ?
    2. а если на api только заменить текст кода скрипта и сохранить, а после в дизайнере посмотреть корректность вставки кода и пересохранить (компилировать) ?
    3. если все ок по первым пунктам, то остается еще возможность того, что библиотека действительно корректно заменена и откомпилирована, но ссылки на нее из других объектов базы нарушены, поэтому имеет смысл в конце всего на api перекомпилировать все скрипты базы, как это обычно делается в дизайнере...

    в моей практике довольно часто случалось при создании библиотек с множеством скриптовых классов - библиотеки корректно компилировались, однако, при тестировании вываливалась та же ошибка, что и у тебя.. спасала перекомпиляция всего..
     
  13. SparkLone

    SparkLone Гость

    Kee_Keekkenen
    1. Не совсем понимаю как это можно сделать. Посредством API ведь можно снять/задать лишь дамп "Database Script".
    Типа:
    Код (Text):
    '++LotusScript Development Environment:2:5:(Options):0:74
    Option Public
    Option Declare
    Option Compare Nocase
    Use "Common"

    '++LotusScript Development Environment:2:5:(Forward):0:1
    Declare Class UIMemoDocument
    Declare Function QuerySaveExtension(Source As notesUIdocument, lngActionInProgress As Long, continue As Variant) As Integer
    Declare Function PostSaveExtension(Source As notesUIdocument, lngActionInProgress As Long) As Integer
    Declare Function QueryCloseExtension(Source As notesUIdocument, continue As Integer) As Integer
    Declare Function PostOpenExtension(Source As notesUIdocument, lngFlags As Long) As Integer
    Declare Sub FaxToProc(Source As Notesuidocument, Continue As Variant)
    Declare Function FaxGetDomain () As String
    Declare Function FaxLookupNAB (CurrentName As Variant, SendToList() As Variant, GroupList() As Variant, FaxDomain As Variant) As Integer
    Declare Function FaxMsgText (MsgNumber As Variant, TextInsert As String) As String
    И т.д.. "Database script" как я понимаю не считается скриптом, ,чтобы работать с ним посредством удобного API, оттуда и проблемы ( db.ScriptLibraryExists("$DBScript") говорит false)
    Таким образом я добираюсь через список всех LNNote.
    Для нахождения LNNote с 'Database Script', написал функцию
    Код (Text):
    LNNote XanderGetDBScriptNode(LNDatabase& db)
    {
    LNNOTETYPE type;
    LNNoteArray notes;
    LNNote note;
    LNItem item;
    BOOL is_agent = true;
    LNDocument doc;
    LNINT i, count;
    LNText text;
    LNString script_text;

    db.GetNotes(&notes);
    count = notes.GetCount();
    for (i = 0; i < count; i++)
    {
    note = notes[i];
    type = note.GetNoteType();
    if (LNNOTETYPE_DATABASE_SCRIPT == note.GetNoteType())
    {
    note.Open();
    // open form or subform note
    if (note.HasItem(DESIGN_FLAGS))
    {
    LNText flags_item; // get $Flags item
    note.GetItem(DESIGN_FLAGS, &flags_item);
    LNINT counter = flags_item.GetCount();
    for (LNINT j = 0; j < counter; j++)
    {
    LNINT loc; // needed by FindChar, but not used here
    if (LNString(flags_item[j]).FindChar(DESIGN_FLAG_DATABASESCRIPT, 0, &loc) == LNNOERROR)
    {
    return note;
    }
    }
    }
    }
    }
    }
    А потом использую найденный нод так:
    Код (Text):
        LNItemArray items;
    note.GetItems(&items);
    cout << items.GetCount() << endl;
    for (j = 0; j < items.GetCount(); j++)
    {
    item = items[j];
    if(item.GetName()== "$DBScript")
    {
    text = item;
    LNString lns(GetFileContent("dbscript.txt").c_str());
    text.SetValue(lns);
    .. дальше уже подписываем, компилим, сохраняем
    }
    }
    note.Close(); // don't need this open anymore
    2. А если сделать sign и save (без sign'а не сохранить), и без рекомпиляции октрыть базу в дизайнере - при просмотре Database script - Он вообще покажет что там пусто.. Хотя программно по прежнему прочитать можно будет.
     
  14. Kee_Keekkenen

    Kee_Keekkenen Well-Known Member

    Регистрация:
    5 сен 2006
    Сообщения:
    616
    Симпатии:
    4
    просто в первом пункте я имел ввиду, что правильно ли (?) заносится текст библиотеки в поле.. ведь Database script это документ, и соответственно, можно только заменить значение поля $DBScript и сохранить его.. вероятно, если удастся сохранить, то при открытии бд может возникнуть какая-нибудь ошибка, хотя и не должно, потому что использоваться должны ранее скомпилированные скрипты в $ScriptLib_O.. этим я хотел понять правильно ли заносится текст кода библиотеки с тем, что открыть базу в дизайнере и посмотреть можно ли пересохранить библиотеку и будут ли ошибки..

    но это все же уход в сторону, только тестирование..

    а как на счет перекомпиляции всех скриптов базы, после удачной замены и компиляции библиотеки ?
     
  15. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Камрады, а почему не хотите прогнать DatabaseScript через очередь
    DXLExporter -> DOMPraser -> DXLImporter?

    В DOMParser'e поменять скрипт на нужный, а DXLImporter сам скомпилит при импорте.
    Если же дизайн закрыт (тогда не сработает DXLExporter), то можно вообще на лету сгенерить нужный DatabaseScript и его импортнуть.
    Структура XML там совсем несложная.
     
  16. SparkLone

    SparkLone Гость

    Kee_Keekkenen
    К сожалению не ясно что именно делается не правильно. Текущий текст $DBScript получаю так:
    Код (Text):
        LNItem item; //здесь DBScript, как именно он получается писал выше
    LNText text;
    LNString script_text; //сюда дампится содержание DBScript в текстовом виде

    text = item;
    text.GetText(&script_text);
    И если его сразу же записать обратно как было показано выше - проблемы остаются. То ли не тот текст скрипта (не в том формате) подставляется, то ли технология сохранения/компиляции не та..

    А на счет рекомпиляции.. Я попытался отрекомпилировать все LNNote а не только скрипты (по той причине что тот же DBScript почему то не считается скриптом). Под самый конец (уже откомпилировалось порядка 450 из 560 элементов) - вылетели ошибки и все упало. И вообще переподписывать всю базу на мой взгляд - не самый лучший вариант.. Получается что владельцем всех элементов будет Админ, как то это не есть гуд.. В идеале изменения вообще бы подписать дизайнером баз, не знаю возможно ли это..

    Omh
    Хм, спасибо за идею, интересный вариант, буду пробовать )
     
  17. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    API это конечно как бы круче :rolleyes:
    Но тут DXL-кой вполне можно обойтись и даже особо напрягаться не придёться :)
     
  18. SparkLone

    SparkLone Гость

    Omh
    Прототип начинал делать не я, потом разработка на некоторое время была приостановлена, а я уже исходил из сделанного. Многие вещи конечно пришлось делать по другому, но как то в данной ситуации посмотреть в сторону Lotus Script'а не догадался )

    P.S. Сдампить всю базу уже удалось, DatabaseScript там присутствует, теперь осталось научиться находить Database Script, чтобы подсовывать его SetInput (а не всю базу), и попробовать записать модификации, заработает или нет.
     
  19. SparkLone

    SparkLone Гость

    Omh
    А у Вас совершенно случайно нет опыта с этой техникой? )
    С XSLT поработать в свое время довелось, но как это все реализовано в Lotus'е что то не ясно.. Взял пример из help'а

    Код (Text):
    Sub Click(Source As Button)
    Dim session As New NotesSession
    filename$ = "dump"

    Dim xmlin As NotesStream
    Set xmlin=session.CreateStream
    If Not xmlin.Open("d:\dbscripts\" & filename$ & ".dxl") Then
    Messagebox "DXL Cannot open " & filename$,, "Error"
    Exit Sub
    End If
    If xmlin.Bytes = 0 Then
    Messagebox "DXL File did not exist or was empty",, filename$
    Exit Sub
    End If

    Dim xslin As NotesStream
    Set xslin=session.CreateStream
    If Not xslin.Open("d:\dbscripts\" & filename$ & ".xsl") Then
    Messagebox "XSL Cannot open " & filename$,, "Error"
    Exit Sub
    End If
    If xslin.Bytes = 0 Then
    Messagebox "XSL File did not exist or was empty",, filename$
    Exit Sub
    End If

    Dim xmlout As NotesStream
    Set xmlout=session.CreateStream
    Call xmlout.Open("d:\dbscripts\" & filename$ & ".txt")
    Call xmlout.Truncate

    Dim transformer As NotesXSLTransformer
    Set transformer=session.CreateXSLTransformer(xmlin, xslin, _
    xmlout)
    Call transformer.Process
    End Sub
    В качестве xsl подставлял (то что в примере тоже не прокатило) это, ожидая что Лотус просто сделает копию, пееркопировав все ноды (так по крайней мере работал движок с которым я работал раньше)
    Код (Text):
    <?xml version="1.0" ?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl" >
    <!-- By default, copy everything -->
    <xsl:template match="/">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    Но на выходе я получаю глупость, а именно копию XSL файла, только со слегка поехавшим форматированием..

    Задумка то моя думаю ясна - по дефолту все перекопировать, кроме нужных мне нод, которые я заменю.. Но по использованию XSL в Лотусе практически нет инфы..
     
  20. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Не, XSLTransformer тебе не нужОн.
    Я предлагал путь DXLExp -> DOMParser -> DXLImp.
    Тут есть статья, где чел описывал настройку embedded view на любую базу через DXL.
    Это примерно то, что тебе нужно.

    Ещё можешь глянуть вот это.
     
Загрузка...

Поделиться этой страницей