Solved

Running Lotusscript code on start up of Lotus Notes

Posted on 2003-11-18
23
2,536 Views
Last Modified: 2013-12-18
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
Comment
Question by:SavithaMohan
  • 6
  • 5
  • 4
  • +3
23 Comments
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 9770783
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
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 9770816
0
 
LVL 31

Expert Comment

by:qwaletee
ID: 9771032
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
 
LVL 24

Expert Comment

by:HemanthaKumar
ID: 9771220
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
 
LVL 31

Expert Comment

by:qwaletee
ID: 9771317
It might beuseful if you described what you are really trying to accomplish (think more in requirements or business terms).
0
 

Expert Comment

by:David777
ID: 9776950
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
 

Author Comment

by:SavithaMohan
ID: 9776996
Thanks for the quick replies.I 'll try all the alternatives and get back.
0
 

Author Comment

by:SavithaMohan
ID: 9795697
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
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 9795988
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
 

Author Comment

by:SavithaMohan
ID: 9796365
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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 46

Accepted Solution

by:
Sjef Bosman earned 43 total points
ID: 9796492
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
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 9796559
0
 
LVL 24

Expert Comment

by:HemanthaKumar
ID: 9797413
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
 
LVL 31

Assisted Solution

by:qwaletee
qwaletee earned 41 total points
ID: 9805001
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
 

Author Comment

by:SavithaMohan
ID: 9848484
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
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 9849396
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
 
LVL 31

Expert Comment

by:qwaletee
ID: 9854819
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
 
LVL 24

Expert Comment

by:HemanthaKumar
ID: 9859057
BTW, Savitha is she not he !
0
 
LVL 31

Expert Comment

by:qwaletee
ID: 9872428
HemanthaKumar,
> BTW, Savitha is she not he !
Then Sjef should CERTAINLY stop encouarging him!

:)
0
 
LVL 24

Expert Comment

by:HemanthaKumar
ID: 9875395
her
0
 

Assisted Solution

by:rafimail
rafimail earned 41 total points
ID: 11214306
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

IBM Notes offer Encryption feature using which the user can secure its NSF emails or entire database easily. In this section we will discuss about the process to Encrypt Incoming and Outgoing Mails in depth.
Article by: Rob
Notes 8.5 Archiving Steps and Tips This article covers setting up a Notes archive, and helps understand some of the menu choices making setting up and maintaining a Notes archive file easier.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now