Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2722
  • Last Modified:

Running Lotusscript code on start up of Lotus Notes

Hi

  I have some DLLs to initialize which should be done one time that is when notes start up and terminate it at notes termination. I want to do this before my mail database opens... I tried to use the database script in mail database. But I am not able to dynamically append my code into the existing database script, that is while my client installs my application. Right now I am only able to replace the whole database script using C API. But I know it is not safe to do this. Please tell me some place where I can write some lotusscript code which will load a view with some 200 documents. Only if this view is loaded I will be able to proceed with my application. I want the place the code in some stable location... That is it should never fail.
I also tried to use the database script in bookmarks.nsf but I dont how far this will also be stable and it requires to copy all of my script libraries once again into bookmark.nsf which will lead to code repetition which may cause further other problems.

I dont know how far I am clear with my question... If I am not clear please let me know I will try to explain my problem more clearly.

I am expecting for some good answers.

Thanks in advance to all the experts who answer this.
Regards
savitha.
0
SavithaMohan
Asked:
SavithaMohan
  • 6
  • 5
  • 4
  • +3
3 Solutions
 
Sjef BosmanGroupware ConsultantCommented:
Don't know if there is any documentation about this, but I know TeamStudio starts when Notes starts. I suppose they use one line in the Notes.ini for this, i.e.
   NSF_HOOKS=hkciao.dll

Maybe you could start your DLL using the above?
0
 
qwaleteeCommented:
I did something like this for a client.  Made one change ti Bookmark.nsf -- had it load a small frame containing a form.  Used the PostOpem of the form to run some code, includng API calls to update designof Bookmark.nsf.  I imagine you could run some termination code in the QueryClose for the form.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
HemanthaKumarCommented:
Savitha,

Since you mentioned that your app will work only when the view is loaded.. Which view ? Inbox !!

If you are depending upon a view, then build a script library and include your dll calls in it and then call this library in the view (In queryopen or Initialize)

~Hemanth

0
 
qwaleteeCommented:
It might beuseful if you described what you are really trying to accomplish (think more in requirements or business terms).
0
 
David777Commented:
why do you want to append code to your database script? There is another way can help to do this, you can add those code to script liberary then in your database script you can call them according to different condition.
0
 
SavithaMohanAuthor Commented:
Thanks for the quick replies.I 'll try all the alternatives and get back.
0
 
SavithaMohanAuthor Commented:
Thank you sjef_bosman. I tried NSF_HOOKS with my DLL. But it is crashing the Lotus Notes always. It is not stable.

The next I tried was comment from qwaletee. Along with Intialise of few DLLs I also had to
run a Timer object. If I add it in Bookmark.nsf the Timer object would run even If my mail
database is not opened. I know it would cause serious performance issue so I decided not to
use it.

HemanthaKumar, If I add my Script in Inbox then it will be called whenever I go to Inbox view
(i.e the user each time moves to some other folder and comes back). This will Intialise my
DLLs multiple times and will lead to Crash.

My purpose is to put my code in Database Script:
      I want to initialize two dlls, start the Timer object and load a view. Likewise
I want to terminate my DLLs, Timer object and I want to do this only the first time I
open my Mail database and close it when the user closes it.

I just need to add a single line Use "MyScriptLibrary" in the Options Section
of Database Script. Right now I am implementing the following way.
 
The code attached gets the Database Script. Finds the $DBScript Item. Gets the
existing Lotus Script code, appends my code to it and replaces the whole Lotus Script code
to the $DBScript Item.

options.SetNoteType(LNNOTETYPE_DATABASE_SCRIPT);
DbSrc.Search("@All",&notesSrc, &options);
note = noteSrc[0];
note.GetItems(&items ,LNITEMTYPE_TEXT);

if(item.GetName()== "$DBScript")
      lnText = item;
      lnText.GetText(&lnString);
      cout << lnString;
      //Modify the lnString and set the new string
      
      lnText.SetValue(lnNewString);
}

note.Save(LNNOTESAVEFLAGS_DEFAULT);
note.Close();

After doing this when I open the database in the designer I am getting an error. It is
 "Generic LSE Failure (no more Info !) and my new code is not shown in the Designer
 where as If I go and see it in the Design Properties Tab, I am able to see it.
 
Suggest me some stable solution which is more reliable.
 
Thanks in advance
0
 
Sjef BosmanGroupware ConsultantCommented:
I don't understand what you're trying to accomplish (someone wrote this before...). You wrote above "It is not stable", but exactly what isn't stable? If "it" refers to your DLL's, then I agree. The NSF_HOOKS method inside Notes is very stable, but I assume you require more information how to hook your DLL to Notes.

Unless you give us a lot more info about what you are trying to do and not about how you intend to do it, we cannot help you. You need DLL's, but why? You need views to be loaded, but why? What do you mean with "loaded"? This could be a problem with my understanding of English of course.
0
 
SavithaMohanAuthor Commented:
Hi sjef_bosman,
 Sorry for not explaining the problem more clearly. For our product, I read all the label
 names and values of every field from a text file. Instead of reading it each time from the
 file I am loading all the text entries in a View and in my code I use @DBLookup to
 get the values. The problem is if the view is not loaded and if the user is trying to open
 our forms then he/ she will get "Entry not Found in Index error" and the whole form won't have
 labels. I reload the view only if any modification are done to the text file. This is
 why I wanted to place my code in the database script.
 
 To load this view I have a script library and five other dependant script libraries which
 are used commonly in all the forms, agents, views, etc.. So I can't place this in
 bookmark.nsf either.
 
 The DLLs are used to contact our server and get user specific data. If these DLLs are
 Initialized multiple times, then it is crashing the Lotus Notes. The same applies to
 the Termination of the DLL.
 
 Hope I am clear this time and I have given the complete picture of what I am trying to do.
 
 Regarding the Hook DLL, I have created a Statically  Linked DLL in Visual C++ and put in Lotus Notes Directory. I have added the dll name to NSF_HOOKS variable in the notes.ini.
 
Can anyone please share some sample Hook DLL source code or provide some relevant links to
proceed further. I will be very grateful if someone could show some lights..
 
Eagerly awaiting for positive responses...
0
 
Sjef BosmanGroupware ConsultantCommented:
You seem to have multiple problems:
1. values in a text-file, to be used (config info??)
2. unwilling dll's

Re 1: MUST it be an external text file you put your config info in? Just because you want to use @DbLookup? There might be an alternative solution (one of my hobby horses): use a Profile Document. A Profile Document is a hidden document inside the Notes database, that is stored in memory when accessed. Subsequent accesses to this document always go to the in-mem version. So it is fast. Second advantage: it is a Notes document, and therefore replicated to all replica's of your db, so configuration information will be available to non-central users as well. You could even think of updating the profile document from your textfile every now and then. What I do not know if this could be a solution to the view-problem.

Re 2: I'm sorry to say that I never used NSF_HOOKS myself. There is a document about how to write a proper hook-dll:
http://www-10.lotus.com/ldd/46dom.nsf/55c38d716d632d9b8525689b005ba1c0/b760f505299a2a1c852568c100798ba4?OpenDocument&Highlight=0,nsf_hooks

Hope this helps!
0
 
HemanthaKumarCommented:
What does this txt file have ? Is this specific to user or global ?

If it is global ,then it can be in a seperate db and upload it once a day.. with simple LS
0
 
qwaleteeCommented:
You seem to have several misconceptions going on.

#1) Accessing a view for speed.  Text files are probably going to be faster than views, unless the files are very large, and you are looking up by index value.

#2) View needs to be open to do lookups.  You only say that because you get the error.  But the reason you get the error is probably that the view is out of date, not that it is open.  You don't load data into a view.  You load data into a database, and then build the view index.  Since your DLL seems to be what is loading the database, "behind the back" of the NOtes client, it does not know to automatically update the view index.  All you have to do is rebuild the view index, as follows:
>> Set view = someDB.getView("SomeName)
>> view.refresh
Once you do that, you should have no need to have the view window open

#3) You need a DLL to load the data.  Script can probably do this just as effectively, and just about as fast (I/O being thelimiter, not the optimization of the text processing loop code).

#4) You need to modify the DbScript on the fly.  What the heck for?  This is a retarded way of doing things, if it is just data driven.

#5) That replacing a script's code will make the script change.  Nuh-uh.  You need to recompile it.  Look at the API for compilation.  And agin, I repeat, once more, with feeling: THIS IS RETARDED.  You'll have to give a more clear expresion of WHAT ON EARTH YOUR CRAZY CODE IS SUPPOSED TO ACCOPLISH before I'll tae that back.  You haven't explained why you wish to do it; you've just explained why you wish to get your code working (i.e., you need to get this view to be used for lookups, none of which seems to have anything to do with your DLLs, timers, etc.)

I don't think you understand how the differences among REQUIREMENTS, SPECIFICATIONS, and DESIGN.
0
 
SavithaMohanAuthor Commented:
Hi sjef_bosman,
Thank you. I have implemented NSF_HOOKS dll and it works fine. But the problem is Hook runs
before the User Password Authentication. So Lotus Notes C++ API gives a Password Prompt.
I found out that this password prompt can be eliminated  by using an Extension Manager
dll.I tried the sample program (extpwd) given along with Lotus C++ API. But the solution
needs user's password to be stored in a physical file.  

Is there any other workaround to run the Hook DLL after the user login?.Wisdom Watch runs
on Lotus notes after the password authentication.

Can anybody suggest some links on Extension Manager / NSF_HOOKS topics?.
0
 
Sjef BosmanGroupware ConsultantCommented:
Hi,

Actually, You're way beyond my turf on this subject, but I might have a suggestion: is it possible to start your DLL, and make it try to register every n seconds or so, to find out if someone already started a session in the Notes client? In pseudo-code:

DLL_init:
   do {
      catch {
         reg= register_extension();
      } fail {
         sleep(2); /* is this allowed in a DLL?? */
      }
   } while(reg==FAILED);

Risk: the Notes-client could be opening the database BEFORE your DLL registers, but the user has to be pdq!

Just to be sure: there is absolutely NO OTHER WAY to solve your problem than to use a hook or extension manager DLL? This really surprises me...
0
 
qwaleteeCommented:
Sjef,

Stop encouraging him!!!!!  Savitha seems uninterested in doing things is a way that makes use of best practices in Notes,  He has his architecture, and won't hear hear anything else.
0
 
HemanthaKumarCommented:
BTW, Savitha is she not he !
0
 
qwaleteeCommented:
HemanthaKumar,
> BTW, Savitha is she not he !
Then Sjef should CERTAINLY stop encouarging him!

:)
0
 
HemanthaKumarCommented:
her
0
 
rafimailCommented:
The code below, register the EM_UPDATEMAILBOX event when it loads the server router task.

This dll runs on server.

To make it works, you must to put at middle of notes.ini the following line:

EXTMGR_ADDINS=your_dll.dll


To compile the code you need Visual C++ and write a "makefile" to compile it. I can't attach them. If you need it, I'll send you.



#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>

#include <lapiplat.h>

#include <addin.h>
#include <extmgr.h>
#include <mailserv.h>
#include <mail.h>
#include <nsf.h>
#include <mq.h>
//#include <osmem.h>


//      VARIABLES PARA EMHandler
WORD                        gRecursionID;
EMHANDLER                  hEventoUpdateMailBox;
HEMREGISTRATION            hrEventoUpdateMailBox;


//      VARIABLES PARA MainEntryPoint y DllMain
STATUS                        error_Perfil;
BOOL                        gHooksRegistrado=FALSE;
char                        sTarea[32] = "";
MQHANDLE                  h_colaTui;


#define DLL_EXPORT


STATUS LNPUBLIC DLL_EXPORT MainEntryPoint( void );
STATUS LNPUBLIC EMHandlerMensajes( EMRECORD FAR * pExRecord);
STATUS DeregisterEntry();


#if defined(NT)
/* Storage needed for synchronization under Windows NT */
CRITICAL_SECTION    gCriticalSection;
#endif


#if defined (NT)
/*===========================================================================
 
  Startup and Shutdown Function DllMain for Windows NT
  ----------------------------------------------------

   BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD fdwReason,
                                       LPVOID lpReserved )
   
  OVERVIEW:
  ---------
   Standard windows NT DLL entrypoint, does initialzation required to get the
   FARPROC for the Extension Manager callback function.
 
===========================================================================*/
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved )
{
      HMODULE            h_Modulo;
      HANDLE            h_Desc;

      WORD            nNumMensajesCola;


      switch(fdwReason)
      {
          case DLL_PROCESS_ATTACH:
                  {
                        InitializeCriticalSection(&gCriticalSection);
                        
                        hEventoUpdateMailBox = (EMHANDLER)MakeProcInstance( (FARPROC)EMHandlerMensajes, hInstance);

                        AddInQueryDefaults(&h_Modulo, &h_Desc);
                        OSLoadString(h_Modulo, PKG_ADDIN+0,sTarea,(sizeof(sTarea)-1));

                  break;
                  }

            case DLL_PROCESS_DETACH:
                  {
                        nNumMensajesCola = MQGetCount(h_colaTui);

                        (void) MQClose (h_colaTui, 0);

      //            <Free procedure instance>
                        FreeProcInstance( hEventoUpdateMailBox );
                        (void) DeregisterEntry();

                        gHooksRegistrado = FALSE;
                        DeleteCriticalSection(&gCriticalSection);
                        break;
                  }      
      }

  return( TRUE );

  UNREFERENCED_PARAMETER(lpReserved);
 
}

#endif


/* ========================================================== */
/* ==================== STARTUP FUNCTIONS =================== */
/* ========================================================== */
STATUS LNPUBLIC DLL_EXPORT MainEntryPoint( void )
{
      STATUS            error=NOERROR;
      

      char            sTareaRouter[32] = "Router";

                  
      
/*    When run on a server the dll is called multiple times. the flag
*    keeps the main code from being executed more than once.
*/
      if ( gHooksRegistrado )
      {
            return(NOERROR);
      }
      
      gHooksRegistrado = TRUE;

#if defined (NT)
/* Done in the DllMain function at startup. */
#else
hEventoUpdateMailBox = EMHandlerMensajes;
#endif

      if ( strcmp(sTareaRouter,sTarea) == 0 )
      {
            STATUS            error_Cola;
            char            nombreColaTui[36] = "MQ$nTui";

//            VARIABLE GLOBAL h_colaTui: Handle a la cola de mensajes
            error_Cola = MQOpen (nombreColaTui, MQ_OPEN_CREATE, &h_colaTui);
            
            switch(error_Cola)
            {
                  case NOERROR:
                  {
                        error_Perfil = EMCreateRecursionID( &gRecursionID );

                        if (error_Perfil)
                        {
                              printf("Error al crear RecursionID\n");
                        }else
                        {
//                        <REGISTRAR_HANDLE_DE_EVENTOS>      
                              error_Perfil = EMRegister(EM_NSFNOTEUPDATEMAILBOX, EM_REG_BEFORE, EMHandlerMensajes, gRecursionID, &hrEventoUpdateMailBox);
                        }

                        break;
                  }
            }
      }

    return( error );
}




STATUS LNPUBLIC EMHandlerMensajes( EMRECORD FAR * pExRecord)
{
      STATUS sError = NOERROR;

      switch ( pExRecord->EId )
      {
      /* Extension Manager hook EM_NSFNOTEUPDATEMAILBOX */
      case EM_NSFNOTEUPDATEMAILBOX:
            {
                  HANDLE      hNote;
                  WORD            wUpdateFlags;
                  VARARG_PTR      ap;

                  char *            szRoutingState = "HOLD";
                  WORD            lenSz = strlen( szRoutingState ) + 1;

                  char            error_text[MAXRECIPIENTNAME];
                  char *            autor;
                  WORD            autorLength;


                  /* check error code; has sense only for EM_AFTER */
                  if ( ( EM_AFTER == pExRecord->NotificationType ) && ( pExRecord->Status != NOERROR ) )
                  {
                        break;
                  }

                  /* get the arguments */
                  ap = pExRecord->Ap;
                  hNote = VARARG_GET( ap, HANDLE );
                  wUpdateFlags = VARARG_GET( ap, WORD );

                  if ( EM_BEFORE == pExRecord->NotificationType )
                  {
                        /* if wUpdateFlags has UPDATE_DELETED
                        then the note is already marked for deletion
                        and the handle must be ignored
                        */

                        printf("1\n\n");
                        sError = NSFNoteGetAuthor( hNote, autor, &autorLength, NULL);
                        printf("2\n\n");

//                        autor[autorLength] = '\0';
                        printf("3\n\n");
//                        printf("autor: %s\n", autor);

                        printf("4\n\n");

                        if (sError != NOERROR)
                        {
                              printf("5\n\n");
                              OSLoadString(NULLHANDLE, ERR(sError), error_text, MAXRECIPIENTNAME);
                              printf("6\n\n");
                              printf("Error: %s.\n", error_text);
                              printf("7\n\n");
                        }else
                        {
                              printf("No hay error !!\n");
                        }
                        printf("8\n\n");
                        
                        
                        if ( UPDATE_DELETED == ( UPDATE_DELETED & wUpdateFlags ) )
                        {
                              /* Note is marked for deletion and will be ignored */
                              printf("Exit 1\n");
                              goto Exit0;
                        }

                        /* mark the note as held (so it won't get out of the mailbox) */

                        printf("ANTES de RoutingState\n");

                        sError = MailReplaceHeaderItem( hNote,
                              MAIL_ROUTINGSTATE_ITEM_NUM,
                              szRoutingState,
                              lenSz );

                        printf("DESPUES de RoutingState\n");

                        if ( sError )
                        {
                              printf("ERROR al cambiar el valor de RoutingState\n");
                              goto Exit0;

                        }
                  } // if EM_BEFORE

                  break;

            } // case EM_NSFNOTEUPDATEMAILBOX

      } // switch

Exit0:
      printf("SALIENDO\n");
      return ( ERR_EM_CONTINUE );

} // EmHandlerProc




STATUS DeregisterEntry()
{
    STATUS error_Perfil = NOERROR;

    error_Perfil = EMDeregister(hrEventoUpdateMailBox);

    return(error_Perfil);
}

0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

  • 6
  • 5
  • 4
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now