@Command([ToolsUserLogoff]) in Lotus Script

Mit Hilfe der Windows API kann der Befehl @Command([ToolsUserLogoff]) in Lotus Script simuliert werden.

VK_F5 = &H74
Const KEYEVENTF_KEYDOWN = &H0000
Const KEYEVENTF_KEYUP = &H0002

Declare Sub WIN32_KeyBoardEvent Lib "User32" Alias "keybd_event" ( Byval bVirtualKey As Integer , Byval bScanCode As Integer , dwFlags As Long , dwExtraInfo As Long )
Sub Logoff ( )
  Dim ModuleName As String
  ModuleName = {Logoff}
  On Error Goto ErrorHandler

  WIN32_KeyBoardEvent VK_F5 , 0 , KEYEVENTF_KEYDOWN , 0
  WIN32_KeyBoardEvent VK_F5 , 0 , KEYEVENTF_KEYUP , 0
  Exit Sub

  ErrorHandler:
  Select Case fnErrorHandler ( Error$ , Err , Erl , ModuleName )
    Case 0
      Exit Sub
    Case 1
      Resume Next
    Case Else
      Resume Next
  End Select
End Sub

Function fnErrorHandler ( strErrorText As String , lngErrorNumber As Long , lngErrorLine As Long , strModuleName As String ) As Integer
Print ( {ERROR: } + strErrorText + { (Nr.: } + Cstr (lngErrorNumber ) + {, Line: } + Cstr (lngErrorLine ) + {, Module: } + strModuleName + {)} )
fnErrorHandler = 1
End Function

Und zum Testen folgender Aufruf

Sub Click(Source As Button)
  Call Logoff
End Sub 

Enumerating Local And Network Drives

Is there a way that I can return all available local drive letters ? Yes, there is a way !

Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsA" (Byval nBufferLength As Long, Byval lpBuffer As String) As Long
Function GetDrives() As String
  Dim tmp As String
  Dim iCount As Integer
  Dim strDrives As String

  strDrives = Space$(64)
  Call GetLogicalDriveStrings(Len(strDrives), strDrives)
       For iCount = 1 To Len(strDrives) Step 4
           tmp = tmp & " " + Mid$(strDrives, iCount, 1)
      Next iCount

     GetDrives = Trim(tmp)
End Function
Sub Click(Source As Button)
    Msgbox getdrives
End Sub

Using GetDocumentByKey with Numerical Values Returns Incorrect Document or No Document

When you use the LotusScript GetDocumentByKey method (of the NotesView class) with a numeric value for the key, either no documents are returned or the incorrect document is returned.You must convert both the column formula and key to string values in order to perform the lookup. You should edit the column formula, adding an @Text function call to the present formula. The key values passed to the GetDocumentByKey method can be converted to string values by using the Cstr function. The dimension, or Dim, statement for the key array must now be declared as a String or Variant.

Example:

Using the @Text function in a column formula. Given a formula which contained the entry ‘numfield’:

@Text(numfield)

Using the Cstr function to convert the desired key value:

keys(0)= cstr(doc.numfield(0))

Lotus Software KnowledgeBase Document# 1101037


DatabaseProperties Class

The DatabaseProperties class has been created to manage Notes databases in small to enterprise-wide domains using LotusScript and C API to set most Database settings on R5/R6 databases that you can set via client notes but pou don’t manage via LotusScript directly.

Its code has been built/expanded from the various Lotus Script/C API contributions over the years in the forums by many authors such as Normunds Kalnberzins and Rod Whitely as well as the dbdesign stuff by Damien Katz (and expanded dbdesign by Josh Jore).

This class is an extension of the “dbdesign” and a reorganization of the function that you can get in “R5 Database Manager” and my improvment. For the DBDesign a i made a fix in the method that update the document thant contain Template Name/Design Name/Category. Now the string store in the notes document does not contain a garbage Characters.


Let User Filter Any View

Here’s a great little Action (or Agent) that lets a user filter any categorized view based on whichever category they choose. I suggest putting it in a SmartIcon so that it will be available in any database or view. You may want to put it in an action button at the top of certain categorized views. It is super-fast (much like using an embedded single-category view). I have put error handling for everything that I encountered, so the user will always get a friendly message.

The @SetViewInfo function filters a view down to a single category. Calling it with a null value will reset the view to show all categories.

This is helpful because of an ugly side-effect of @SetViewInfo — filtering is retained even when the user changes to a different view. Sometimes this results in zero documents being shown. Clicking the action button again will show all docs.

By the way, I believe that the column choice does not work in @SetViewInfo( ). In my testing, it only works on the first categorized column.

REM { --- this action button filters a view based on the user's input --- };

tmpVName := @Subset( @ViewTitle; -1 );
@If( tmpVName = "";
   @Return( @Prompt( [Ok]; "Warning"; "This only works when a database
is opened to a view.") );
   @Success );
tmpCol := 1;

REM { produce a list of categories from the current view };
tmpList := @Unique( @DbColumn( "":""; "":""; tmpVName; tmpCol ) );

REM { handle common errors -- reset filtering in an inappropriate view };
warningText := "This action only works in a categorized view where the category
is the first column." + @Char(10) +
  "This will not work in a flat view or in a view where the first column is not
the category";
@If( @IsText( tmpList[1] );
   @Success;
   @Do( @SetViewInfo( [SetViewFilter]; ""; ""; 1); @Return( @Prompt(
[Ok]; "Warning"; warningText ) ) ) );

REM { Let the user pick one category };
tmpChoice := @Prompt( [OkCancelCombo];
"Select a Category for Filter"; "This will filter the view to a single
category." + @Char(13) + "   (specify blank for all)";
""; "" : tmpList );

REM { reminder: expand the view or it may appear empty };
@Command( [ViewExpandAll] ) ;

REM { Set the filter (or clear the filter) };
tmpCName := "sPOAreaName";
@SetViewInfo( [SetViewFilter]; tmpChoice; tmpCName; 1 )

Notes Client, POP3 und SPAM

In einem früheren Artikel hatte ich bereits beschrieben, wie man den heimischen Domino Server für den Einsatz des OpenSource Spamfilters kSpam konfiguriert. Nun wird nicht jeder einen Domino sein Eigen nennen. Die meisten Heimanwender werden hre Mails über den Notes Client mittels POP3 von ihren Provider abholen. Leider gibt es noch kein Produkt, das ähnlich wie kSpam in die Notes Installation eingebunden werden kann.
Für die meisten eMail Clients gibt es aber solche Spamfilter; sei es als PlugIn oder als Proxy. Ich werwende hier das Freeware Produkt Spamihilator von Michel Krämer. Spamihilator schaltet sich zwischen Ihre E-Mail-Software und das Internet und überprüft jede eingehende E-Mail auf Spam. Ã?berflüssige Werbenachrichten (Spam, Junk) werden herausgefiltert. Die Filterung läuft dabei vollständig im Hintergrund ab. Der neue lernfähige Filter (Bayesian Filter) arbeitet nach den Regeln von Thomas Bayes (englischer Mathematiker, 18. Jahrhundert) und errechnet für jede E-Mail eine bestimmte Spam-Wahrscheinlichkeit. Sie können diesen Filter trainieren! Dadurch stellt er sich auf Ihr persönliches Mailaufkommen ein und kann mit der Zeit immer bessere Ergebnisse liefern. Zusätzlich benutzt Spamihilator noch einen Wortfilter, der nach bekannten Schlüsselwörtern sucht. Natürlich unterstützt das Programm auch Plugins. Diese nützlichen Filter schützen Ihren Computer zusätzlich vor nervigen Werbenachrichten. Die Installation erfolgt über ein komfortables Setup-Programm. Spamihilator ist nach der Installation im SysTray zu finden.

Wenn der Notes Client bereits für den Abruf von Mails über POP3 eingerichtet ist, ist die restliche Konfiguration ein Kinderspiel. Es muÃ? lediglich erreicht werden, daÃ? die Mails nicht mehr direkt vom POP3 Konto abgeholt werden, sondern das Spamihilator die Mails abholt und an den Client zustellt


In das Feld “Server für dieses Benutzerkonto” wird localhost eingetragen. Damit wird erreicht, daÃ? der Mailabruf über Spamihilator erfolgt. Die Anmeldeinformationen im Feld “Anmeldename” wird um den POP3 Servernamen des Providers ergänzt. Jetzt noch das Dokument speichern und schlieÃ?en; FERTIG 😉

Spamihilator

POP3, SMTP, Virenscanner und Spamfilter

Wie man den Notes Client so konfiguriert, das Mail von unterschiedlichen POP3 Accounts abgeholt werden, wurde bereits mehrfach an anderer Stelle im Internet beschrieben. Die beschriebenen Konfigurationen verwenden dabei für die unterschiedlichen Accounts separate Arbeitsumgebungsdukumente und Dokumente f?r die Konfiguration der POP3 Konten. Der Nachteil dabei ist, daÃ? alle Mails in einer Maildatei landen; n?mlich der Datei, die in der aktuellen Arbeitsumgebung eingetragen ist.
Steht ein eigener Domino Server zur Verfügung, ergeben sich daraus ganz andere Möglichkeiten. Im Folgenden möchte ich beschreiben wie man den eigenen Domino so einrichten kann, da? Mails automatisch von unterschiedlichen POP3 Konten abgeholt werden können und in unterschiedlichen Mailboxen auf dem Server zugestellt werden. Auch in der Version 6.51 besitzt der Server leider immer noch nicht die Fähigkeit, sich bei einem Provider vor dem Versand von SMTP Mails zu authentizieren. Mit einem kleinen Freeware Programm lässt sich aber auch diese Hürde nehmen.
Auch wenn die meisten Provider eigene Virenprogramme einsetzen, empfielt es sich dennoch auf dem Domino mit einem eigenen Virenscanner zu arbeiten. Da gleiche gilt auch für den Einsatz eines SPAM Filters.

Der installierte Server ist ND 6.51 englisch auf einem Windows 2000 Advanced Server deutsch ( 3.2 GHz, 1.5 GB RAM, 0.75 TB HD ). Die Anbindung an das Internet erfolgt über DSL. Neben dem Domino Server kommt noch folgende Software zum Einsatz:

pullmail.exe Freeware zur Abfrage der POP3 Konten ( 7th wave )
SMTP AUTH 2.0.1 Freeware zum Versenden von SMTP-Mails
NOD32 für Windows Virenscanner ( keine Freeware )
kSpam für ND / WIndows Freeware SPAM Filter für Lotus Notes

1. Serverdokument bearbeiten

Zunächst einmal muss der Domino Server für das Routing von Mail und SMTP Mail konfiguriert werden. Dazu sind im Serverdokument die Routing-Funktionen “Mail-Routing” und “SMTP-Mail-Routing” zu aktivieren. Ebenso muss der SMTP-Listener-Task eingeschaltet werden, da pullmail die Mails an den Domino Server per SMTP übermittelt.

Unter “Anschlüsse -> Internet-Anschlüsse -> Mail” werden folgende Ports für POP3 und SMTP eingestellt

Mail (POP3) 110
SMTP-Eingang 25
SMTP-Ausgang 10025 (!)

Die Wahl des Port 10025 bei SMTP-Ausgang ( DEFAULT = 25 ) ist wichtig, damit der Domino Server mit dem Programm SMTP-AUTH auf der gleichen Maschine installiert werden kann.

2. POP3 Mails abrufen

Zum Abrufen der E-Mails wird das Programm pullmail.exe verwendet. Das Programm mu? nicht installiert werden; ein einfaches Kopieren z.B. in das Notes Programmverzeichnis reicht aus.

pullmail wird über die Kommandozeile aufgerufen; daher können wir die Parameter in einer BATCH-Datei speichern und hinterher über den Scheduler von WINDOWS 2000 ausf?hren.

Meine pullfreenet.cmd sieht dann beispielhaft so aus:

pullmail pop3.freenet.de webmaster@qualytec.de ThePasswort /S:192.168.xxx.xxx /to:ulrich.krause@eknori.local
pullmail pop3.freenet.de webmaster@eknori.de ThePasswort /S:192.168.xxx.xxx /to:ulrich.krause@eknori.local
pullmail pop3.freenet.de eknori@eknori.de ThePasswort /S:192.168.xxx.xxx /to:ulrich.krause@eknori.local
pullmail pop3.freenet.de ulrich.krause@eknori.de ThePasswort /S:192.168.xxx.xxx /to:ulrich.krause@eknori.local

In dem Beispiel werden 4 Konten von freenet.de abgefragt. Hier habe ich ein Intervall von 2 Minuten eingestellt. web.de z.B. erlaubt eine neuerliche Anmeldung erst nach 15 Minuten. Daher habe ich für unterschiedliche Provider je nach Gegebenheit und Notwendigkeit unterschiedliche Konfigurationen, die in einem getrennten geplanten Task im Scheduler aufgerufen werden.

3. SMTP AUTH

Grundsätzlich ist es natürlich möglich, Mails via SMTP ?ber den Domino zu versenden. Bei der gewählten AnschluÃ?art über DSL verfügt der Server aber über keine feste IP Adresse. Ebenso fehlt ein MX -Eintrag; daher würden Mails in der Regel von den Systemen der Empfänger zurückgewiesen werden, da der Server nicht authentiziert werden kann.
Ein direktes Versenden ist daher nur bei fester IP-Adresse und entsprechendem MX-Eintrag möglich.

SMTP-AUTH ist ein Freeware Programm, das es ermöglicht, SMTP Mail an einen Provider zu übermitteln und die notwendigen Anmeldeinformationen mitzuliefern. Die Installation erfolgt über ein Setupprogramm. SMTP AUTH bietet in der Version 2.00 Beta 3 die Möglichkeit, die Software als Dienst zu betreiben. Das ist natürlich ideal für unsere Zwecke.

Nach der Installation kann das Konto für den SMTP Mailversand konfiguriert werden. Hier wird dann auch die Portnummer eingetragen (10025) , die wir in das Serverdokument eingetragen haben. Die Anmeldemethode AUTH PLAIN funktioniert mit freenet.de und web.de. Mir wurde zugetragen, daÃ? die Methode auf AUTH LOGIN geändert werden muss, damit es auch mit einer Schlund und Partner Dom?ne funktioniert
Damit der Domino Server mit SMTP-AUTH kommunizieren kann, muÃ? in das Konfigurationsdokument des Servers noch ein Relay-Host eingetragen werden

Wichtig ist hier, daÃ? auch der Port 10025 mit angegeben wird, da sonst die Kommunikation auf dem DEFAULT Port 25 erfolgt; der Domino also quasi selber mit sich verbinden m?chte. Das mag er aus verständlichen Gr?nden aber nicht. Sind alle Einstellungen richtig, kann nun eine Testmail versendet werden. Die Console sollte dann sinngemäÃ? folgende Ausgaben zeigen

Der Domino Server sendet die Mail an den SMTP Proxy; dieser meldet sich mit den eingetragenen Daten beim Provider an und übermittelt die Mail.

4. Mails auf Viren scannen

Als Virenscanner kommt NOD32 der Firma ESET zu Einsatz. Einzelheiten zum Scanner können auf der Seite des Herstellers eingesehen werden. Das Windows-Portal WinTotal hat den Scanner 2003 getestet. Die Ergebnisse sind hier zu finden.
Der Scanner wird auf meinem Server sowohl als Schutz des Dateisystems eingesetzt (AMON) als auch zum scannen eingehender Mails (IMON).

Da NOD32 für Windows alle Mails direkt auf Winsock-Ebene abgreift und prüft, ist keine weitere Konfiguration nach der Installation notwendig. Lediglich der POP3-Port ist anzugeben; in unserem Fall 110.

NOD32 hat in meinen Tests alle Viren zuverlässig erkannt. Auch Viren im Archiven (zip, rar, ace) wurden erkannt und bereinigt.
Der Preis von ? 39,- umfasst einen Updateservice für 1 Jahr auf Programmupdates und die Online-Aktualisierung der Virensignaturen.

5. SPAM filtern mit kSpam

kSpam ist ein Open Source SPAM Filter (addin) für Lotus Notes/Domino und ist in einer Windows bzw. Linux Version erhältlich. Die neueste Version kann bei www.openntf.org heruntergeladen werden.
Die Installation und Konfiguration ist im Download beschrieben. Mitlerweile läuft kSpam bei mir mit einer Erkennungsrate von 90% bei einer false positive rate von < 2%.


Determine Drive Types and Next Available Drive Letter

When dealing with drive types and letters it is nice to have a simple function to give you that information. The function shown below will cycle through each of the valid drives on the system running the program and tell you what each type is. Once it is finished, it tells you what the next available drive letter is. In dealing with network applications, it is sometimes necessary to add a drive letter for a new connection.

The first thing you will need is an API declaration. This declaration looks like the following:

Declare Function GetDriveType  Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String)As Long

The next thing you will need is the function to actually perform the work for you. The function looks like the following:

Function FreeDrive() As String
	Dim DriveNum As String    'To cycle through drive letters in order
	Dim DriveType As Long     'To hold the type of drive it is
	DriveNum = 64             'Prime the variable to be used in the loop
	 Do
	 	DriveNum = DriveNum + 1   ' start at drive zero.
	 	DriveType = GetDriveType(Chr$(DriveNum) & ":")
	 		If DriveType = 1 And DriveNum > 67 Then Exit Do
	 			Select Case DriveType
	 				Case 0: MsgBox Chr$(DriveNum) + ": is An Unknown type"
	 				Case 1: MsgBox Chr$(DriveNum) + ": Does Not Exist"
	 				Case 2: MsgBox Chr$(DriveNum) + ": is a Removable Drive"
	 				Case 3: MsgBox Chr$(DriveNum) + ": is a Fixed Drive"
	 				Case 4: MsgBox Chr$(DriveNum) + ": is a Remote Drive"
	 				Case 5: MsgBox Chr$(DriveNum) + ": is a CD-ROM Drive"
	 				Case 6: MsgBox Chr$(DriveNum) + ": is a RAM Drive"
	 			End Select
	 Loop

	 FreeDrive = Chr$(DriveNum) + ":"  'Return the next available drive letter
	 End Function

Finally, you need to place the code in an event procedure or other routine to call the FreeDrive Function. In this case, we are simply calling the function by placing the return value into a message box.

Sub Click(Source As Button)
	Msgbox "Next Available Drive letter is " & FreeDrive()
End Sub

Distance Between 2 Points On Earth

Wie weit ist es von Mettmann nach Düsseldorf, oder von Mettmann nach Frankfurt ? Früher gab es mal so kleine Geräte, mit denen man in einer Karte die Entfernung zwischen zwei Städten dadurch bestimmen konnte, daÃ? man mit diesem Gerät die Strecke zwischen Start- und Zielort entlangfuhr. Die Entfernung lieÃ? sich dann auf einer analogen Scala ablesen; vorausgesetzt, man hatte den MaÃ?stab der verwendeten Karte richtig eingestellt.
Heute in digitalen Zeitalter stehen dazu weit bessere, genauere Methoden zur Verfügung. GPS z.B. ist eine davon. Viele Autos ( meines nicht ) haben bereits ein solches System eingebaut. Man kann Start- und Endpunkt eingeben und erfährt sogleich neben anderen Informationen die exakte zurückzulegende Strecke; auf den Meter genau (?).
Wie aber kann man auch Lotus Notes dazu bewegen, die Entfernung zwischen zwei Staedten zu berechnen ?
Im deutschen Notes Forum wurde diese Frage gestellt. Allerdings wurde hier nach einer Funktion gefragt, die z.B. Filialen in einem vorgegebenen Umkreis zum Standort anzeigt / auflistet.
Ich möchte mich hier zunächst einmal darauf beschränken, eine Funktion vorzustellen, die es ermöglicht, auf Grundlage vorgegebenen Ortskoordinaten die Entfernung zwischen zwei Orten zu berechnen.

die Originalformel von http://www.gumo.de/ ( Visual Basic-Funktion zur Berechnung der Entfernung zwischen zwei Punkten auf der Erdoberfläche ) habe ich nach Lotus Script portiert.

Die Koordinaten müssen folgendermaÃ?en aufgebaut sein:

Mettmann 06E59 51N15

das bedeutet Mettmann liegt 51°15’00″Nord und 06°59’00″Ost.
Die Koordinaten habe ich einer Auflistung entnommen, die unter http://www.themamundi.de/aws/tabel/tbmain.htm zu finden ist. Es werden gröÃ?tenteils die Sekunden bei den Koordinaten weggelassen; die Formel kann aber auch mit Koordinaten der Form 06E5922 51N1501 rechnen.

Hier ein Beispiel zum Funktionsaufruf.

Sub Click(Source As Button)
        'Mettmann    06E59      51N15
        'Düsseldorf   06E47      51N14
	Msgbox  dblDistanceBetween2PointsOnEarth ( "51N15" , "06E59" , "51N14 " , "06E47" )
End Sub
Function dblDistanceBetween2PointsOnEarth(  c1N As String, c1E As String, c2N As String, c2E As String ) As Double

'Die Funktion liefert die Entfernung zweier Punkte auf der Erdoberfl?che in km.
'Das Verfahren ber?cksichtigt die Erdabplattung und ist auch für sehr kleine Entfernungen genau.
'Keine Ber?cksichtigung der Höhe ?ber N.N.!
'Quelle: Jean Meeus - Astronomische Algorithmen (Auflage 1992, Verlag Johann Ambrosius Barth), Seite 93f, 118ff    '
	Dim phi1_rad As Double
	Dim lambda1_rad 	As Double
	Dim phi2_rad  As Double
	Dim lambda2_rad 	As Double
	Dim F 	As Double
	Dim sinF2 As Double
	Dim cosF2 As Double
	Dim G As Double
	Dim sinG2 As Double
	Dim cosG2 As Double
	Dim dl As Double
	Dim s 	As Double
	Dim C As Double
	Dim om As Double
	Dim R  As Double
	Dim cosD As Double
	Dim D As Double
	Dim H1  As Double
	Dim H2 As Double
	Dim DEG As String
	Dim MMSS As String
	'Needed constants Const
	Const RADIAN = Pi / 180
	' mittlerer Erdradius in km
	Const MEAN_RADIUS = 6371.299
	' Abplattung der Erde
	Const FLATTENING_FACTOR = 1 / 298.257
	' Ã?quatoradius in km
	Const EQUATOR_RADIUS = 6378.14

	'Convert to radians
	MMSS= atWord (c1N,"N",2)
	DEG = atWord (c1N,"N",1)

	If Len (MMSS) = 4 Then
		phi1_rad = (DEG + (Left$(MMSS,2)  / 60) + (Right$(MMSS,2)  / 3600)) * RADIAN
	Else
		phi1_rad = (DEG + (MMSS  / 60)) *RADIAN
	End If

	MMSS= atWord (c1E,"E",2)
	DEG = atWord (c1E,"E",1)
	If Len (MMSS) = 4 Then
		lambda1_rad = (DEG + (Left$(MMSS,2)  / 60) + (Right$(MMSS,2)  / 3600)) * RADIAN
	Else
		lambda1_rad = (DEG + (MMSS  / 60)) * RADIAN
	End If

	MMSS= atWord (c2E,"E",2)
	DEG = atWord (c2E,"E",1)
	If Len (MMSS) = 4 Then
		lambda2_rad = (DEG + (Left$(MMSS,2)  / 60) + (Right$(MMSS,2)  / 3600)) * RADIAN
	Else
		lambda2_rad = (DEG + (MMSS  / 60)) * RADIAN
	End If

	MMSS= atWord (c2N,"N",2)
	DEG = atWord (c2N,"N",1)
	If Len (MMSS) = 4 Then
		phi2_rad = (DEG + (Left$(MMSS,2)  / 60) + (Right$(MMSS,2)  / 3600)) * RADIAN
	Else
		phi2_rad = (DEG + (MMSS  / 60)) * RADIAN
	End If

	'Check on precise calculation
	cosD = Sin(phi1_rad) * Sin(phi2_rad) + Cos(phi1_rad) * Cos(phi2_rad) * Cos(lambda1_rad - lambda2_rad)
	If cosD < 0.999995 Then'Distance is long
		F = (phi1_rad + phi2_rad) / 2
		sinF2 = (Sin(F)) ^ 2
		cosF2 = (Cos(F)) ^ 2
		G = (phi1_rad - phi2_rad) / 2
		sinG2 = (Sin(G)) ^ 2
		cosG2 = (Cos(G)) ^ 2
		dl = (lambda1_rad - lambda2_rad) / 2
		s = sinG2 * (Cos(dl)) ^ 2 + cosF2 * (Sin(dl)) ^ 2
		C = cosG2 * (Cos(dl)) ^ 2 + sinF2 * (Sin(dl)) ^ 2
		om = Atn(Sqr(s / C))
		R = Sqr(s * C) / om
		H1 = (3 * R - 1) / (2 * C)
		H2 = (3 * R + 1) / (2 * s)
		dblDistanceBetween2PointsOnEarth = 2 * om * EQUATOR_RADIUS *_
		(1+ FLATTENING_FACTOR * H1 * sinF2 * cosG2  - FLATTENING_FACTOR * H2 * cosF2 * sinG2 )
	Else          'Distance is short
		dblDistanceBetween2PointsOnEarth = Sqr(((lambda2_rad - lambda1_rad) *_
		Cos((phi1_rad + phi2_rad) / 2)) ^ 2 + (phi2_rad - phi1_rad) ^ 2) * MEAN_RADIUS
	End If
End Function

Diese Formel gilt für Erdkoordinaten auf der nördlichen Erdhalbkugel und Werte die östlich von Greenwich liegen. Also Erdkoordinaten mit einem N und O. Die gleiche Formel kann man auch für alle anderen Koordianten benutzen, man muÃ? nur bei Süd- und Westwerten jeweils ein Minus davorstellen. Also S und W Werte mit -1 multiplizieren! Zum Splitten der Koordinatendaten wird die Funktion atWord verwendet. atWord ist das Lotus Script Ã?quivalent zu @Word

Function atWord ( sourceString As String, separator As String, number As Integer ) As String
	searchString$=SourceString & separator
' add one separator to catch also the last substring
	For i% = 1 To number
		pos%=Instr(searchString$, separator)
		If pos%=0 Then
			Exit For
			substring$=Left(searchString$,pos%-1)
			searchString$=Mid(searchString$, pos%+1)
		Next
		If pos% > 0 Then
			atWord=substring$
		Else
			atWord=""
		End If
End Function

DOWNLOAD


Dateihandling

Jeder kennt das Problem: Die User in einem Unternehmen erstellen verschiedenartige Dokumente, die im Filesystem gespeichert werden. Bedingt durch Sicherheitsrichtlinien haben nicht alle Mitarbeiter die gleichen Zugriffsrechte.
In den meisten Unternehmungen gibt es noch nicht einmal ein Transferlaufwerk, auf das ALLE Mitarbeiter Lese- und Schreibberechtigung haben. Daher wird vielfach der Dateiaustausch über das Medium email bewerkstelligt. Je nach den gewählten Benutzereinstellungen entstehen durch diese Methode Duplikate ( Original auf dem Filesystem, Kopie im Ordner “Gesendet” und noch eine Kopie beim Empfänger ).
Angeregt durch den Thread “Dateiauswahl in Mailmaske” im deutschen Notes Forum habe ich das Thema aufgegriffen und möchte hier meinen Lösungsvorschlag vorstellen.

Einen Lösungsansatz findet man z.B. in der Sandbox. Allerdings werden die Dateien beim Klicken auf die erzeugten Links nicht in der zugehörenden Applikation sondern im Browser geöffnet. Im ungünstigsten Fall wird statt des Dateiinhaltes lediglich der Downloaddialog angezeigt. Da drehen wir uns dann im Kreis, denn ein erneutes Speichern der Datei wollen wir ja gerade vermeiden.

Selbstverst?ndlich wäre es schön, wenn ein Link zu einer Datei ebenso wie die Links in diesem Beitrag im Kontext des Textes erzeugt werden k?nnen. Dazu müsste man dann die Notes API verwenden. Erste Versuche haben aber gezeigt, dass die Verwendung der Api in diesem Falle alles Andere als trivial ist.

Daher habe ich mir einen anderen Ansatz überlegt. Zwar wird auch hier in einer Funktion Gebrauch von der Windows API gemacht, ob die API aber unbedingt notwendig ist, ist im Einzelfall zu prüfen.

Die vorgeschlagene Lösung basiert auf einer Teilmaske; somit kann die gewünschte Funktionalität in jede beliebige Datenbank eingebaut werden. Die Teilmaske enthält alle erforderlichen Elemente. Zusätzliche Script Bibliotheken oder Agenten sind nicht erforderlich.

In der Teilmaske sind folgende Funktionen enthalten

  • Hinzufügen einer Datei ( Add File )
  • Enfernen einer Datei ( Remove File )
  • Entfernen aller Dateien ( Remove All )
  • Starten einer Datei ( Open File )

Die Auswahl der Dateien erfolgt über einen Dialog, wie er in Windows Anwendungen üblich ist. Notes stellt eine API Funktion zur Verfügung, die in Lotus Script verwendet werden kann.

Declare Function NEMGetFile Lib "nnotesws" (wUnk As Integer, Byval szFileName As String, Byval szFilter As String, Byval szTitle As String ) As Integer
Sub Click(Source As Button)
	Dim workspace As New NotesUIWorkspace
	Dim uidoc As NotesUIDocument
	Set uidoc = workspace.CurrentDocument
	Dim szFileName As String*256
	Dim szTitle As String
	Dim szFilter As String
	Dim session As New NotesSession
	szFilename = Chr(0)
	szTitle = session.Commonusername & ", select your database NOW"
	szFilter = "MS Word Documents|*.doc|Notes Databases|*.NSF|Notes Templates|*.NTF|Programs|*.EXE|All Files|*.*|"
	If NEMGetFile( 0, szFileName, szFilter, szTitle) <> 0 Then
		szFileName = szFileName & |"|
		Call uidoc.FieldAppendText ( "fList",  "," + GetShortFileName (szFileName) + "," )
	End If
End Sub

In einem früheren Code ( reattach ) habe ich beobachtet, daÃ? Notes manchmal Probleme bei langen Dateinamen hat. Diese Probleme treten besonders dann auf, wenn der Pfad oder die Datei selber Leerzeichen enthält. Daher habe ich die Function GetShortFileName eingebaut. Die Funktion bedient sich der Windows API

Declare Function GetShortPathName Lib "kernel32" Alias"GetShortPathNameA" (_
Byval lpszLongPath As String,Byval lpszShortPath As String, Byval cchBuffer As Long) As Long
Function GetShortFileName ( fileName As String ) As String
	Dim sBuffer As String , lLen As Long
	sBuffer = Space$ ( 512 )
	lLen = GetShortPathName  ( fileName , sBuffer , Len ( sBuffer ) )
	GetShortFileName = Left$(sBuffer, lLen )
End Function

Damit ist eigentlich auch schon der GroÃ?teil der Arbeit getan; ab hier geht es wieder ohne Lotus Script weiter.

btnRemoveFile

 _Names :=  fList ;
_Del :=  @Prompt([OkCancelList]:[NoSort] ;"Dateiauswahl";"Bitte wählen Sie die zu löschende Datei aus!"; "" ; _Names ) ;
@If( _Del != 1; "" ; @Return( "" ) ) ;
_Elems := @Elements( _Names ) ;
_Pos := @Member( _Del ; _Names ) ;
FIELD fList := @Trim( @If( _Pos = 1 ; "" ; @Subset( fList ; _Pos - 1 ) )  : @If( _Pos = _Elems ; "" ; @Subset( fList ; - ( _Elems - _Pos )  ) ) ) ;
@Command([ViewRefreshFields])

btnRemoveAll

FIELD fList:=@DeleteField;
@True

Damit wären wir schon am Ende; war doch gar nicht so schwer, oder? Ich bin mir darüber im Klaren, dass dies nur eine einfache Lösung ist. Selbstverständlich m?ssen die Empfänger einer Mail mit Dateilinks auch Zugriff auf die Dateien haben. Anwender, die ohne Netzanbindung arbeiten können nicht auf die Links zugreifen. Es sollte auch keine allumfassende Lösung vorgestellt werden. Es handelt sich, wie eingangs erwähnt lediglich um einen Ansatz. Möglicherweise ist dem Einen oder Anderen damit schon geholfen. Wenn dem so ist, würde ich mich ?ber ein kurzes Feedback freuen.

DOWNLOAD


Label mit Lotus Notes und Microsoft Word drucken

Sie können den Code ohne Anpassung in jeder beliebigen Adressdatenbank verwenden.
Dazu kopieren sie aus der Demo-DB die folgenden Designelemente

Maske ($lblConfig)
Ansichten ($lblConfig) und Config
ScriptBibliothek libLabel

Nachdem sie ihre Datenbank vorbereitet haben, können wir den Datenexport konfigurieren. Wechseln sie in die Ansicht Config und erstellen sie eine neue Konfiguration.

Sie können mehrere unterschiedliche Konfigurationen erstellen; wenn sie die Adressen drucken, wird ihnen eine Liste der mglichen Ausgabeformate angezeigt.

Generell ist der Ausdruck auf 5 Zeilen begrenzt. Welche Werte ausgedruckt werden, legen sie durch die Werte in den Feldern Row 1 – Row 5 fest. Tragen sie hier die Namen der Felder ein, die ausgedruckt werden sollen. Es können pro Zeile mehrere Felder ausgedruckt werden; die Feldnamen werden dann, wie im Beispiel duch ein Komma getrennt.

Das Feld Config ist ein Beschreibungsfeld; es wird ihnen in der Auswahl ebenso angezeigt wie des Feld Description.
In den Feldern Label und Rows legen sie die Werte des Formulas fest. Die korrekten Werte des zu verwendenden Labels erhalten sie, indem sie in Microsoft Word über “Extras – Umschläge und Etiketten” klicken.

Wechseln sie in der Reiter Etiketten und klicken auf Optionen

Jetzt können sie die gewünschte Vorlage auswählen

eine Besonderheit stellt das Feld Skip dar. Einige Formulare enthalten Zwischenr?ume. Dies müssen sie dem Programm durch das setzen des Feldes Skip auf den Wert Yes mitteilen, da sonst der Ausdruck in diese Zwischenräume erfolgt.

Darüber hinaus müssen sie in das Feld Rows die Gesamtzahl der Zellen einer Reihe eintragen, also Anzahl der Label plus Anzahl der Zwischenräume
Nachdem sie alle notwendigen Konfigurationsdokumente angelegt haben, können sie den Labeldruck starten; hierzu wählen sie die gewünschten Adressen in einer Ansicht aus und klicken auf “Print Label” Die gewählten Adressen werden dann über Microsoft Word ausgedruckt.

DOWNLOAD


Deutsche Sprache

Als ich noch Kind war benutzte man das Wort â??in’ nur vor Ortsbezeichnungen. Heute ist es â??in’, â??in’ zu sein. â??in’-Leute haben ihre Sprache mit amerikanischen Begriffen durchsetzt, die durch phonetische Hässlichkeit besonders auffallen.
Damit schaffen sie für sich selbst eine Aura des â??successfull’. Will sagen erfolgreich und überlegen. Überlegen meint, ‘über anderen zu liegen’. Viele Menschen fühlen sich oft unterlegen,sind es aber gar nicht sind.

Sie versuchen unbewusst durch perfekt korrekte Aussprache amerikanischer Bezeichnungen sich das Gefühl zu verschaffen, ‘über anderen zu liegen’, oder zu den Besseren dazu zugehören. Wenn die jeweils anderen dabei diese Ausdrucksweise dann gar nicht verstehen, umso besser. Steigt dann doch das Gefühl scheinbarer Ã?berlegenheit. Hauptsache sie bewegen sich im â??mainstream’, im Hauptstrom, und die Wirkung ist â??cool’. Anscheinend frieren sie in dieser Kühle nicht. Dabei reden sie oft viel und sagen nur wenig. ‘trendy’ zu sein ist alles. Es drängt sie, Zungenbrecher wie â??Massachusetts’ und ähnliches mit perfekter Andacht nur ja mit stark amerikanischer Slan-Färbung auch im Unterton vollendet auszusprechen.

Die Industrie geht darauf ein. Die Fernsehwerbung bei ntv verwendet deutsche Worte nur noch ausnahmsweise. Fast alle Werbebotschaften dort sind amerikanisch. Die Telekom kannte eine Zeit lang keine Ortsgespräche mehr; nur city-calls’. Vermutlich hat man das dann mal mit dem Computer-Schreibprogramm â??Word’ geschrieben und dabei diesen Unsinn bemerkt. Denn dieses aus den USA kommende Schreibprogramm erzeugt mit seiner automatischen Rechtschreibüberprüfung bei all diesen Vokabeln automatisch die Anzeige: ‘Keine Rechtschreibüberprüfung möglich’. Vermutlich haben Amerikaner uns da unterstellt, daÃ? wir nur in unserer eigenen Sprache schreiben und dieses ‘denglisch’ erst gar nicht in die Automatik mit einbezogen. Auf meiner Telefonrechnung ist jetzt von City- und Regional-Verbindungen die Rede. Welch ein Fortschritt ist doch dieser Rückschritt.

Die Nutzung des Frankfurter Flughafen ist ohne Englisch-Kenntnisse oder Wörterbuch nicht mehr möglich; in Düsseldorf geht das kaum noch ohne. Der Flughafen ‘Charles de Gaulle’ in Paris ist genauso international. Aber alle Schilder dort sind zweisprachig, französisch und englisch. Nicht englisch und französisch, oder nur englisch. Ã?ber Ausgängen auf spanischen Flughäfen steht nur ‘Salida’, nicht Exit.

Es schert uns nicht, wenn Amerikaner von Branswik, Kolloune, Hämbörg oder Mjunik reden, wenn sie Braunschweig, Köln, Hamburg oder München meinen.

Ein Offizier der englischen Armee erzählte mir vor Jahren, daß er in Deutschland schon seit langem bei ‘Dtschallitsch’ stationiert sei. Als ich das nicht verstand, zeigte er mir auf einer Autokarte: Jülich.

Die Franzosen fahren über Aix-La-Chapelle nach Collogne. Nicht über Aachen nach Köln. Die Italiener sprechen von Frankoforte und Amburgo, wenn sie Frankfurt und Hamburg meinen. Kommt jedoch der aufrechte Deutsche mit seiner Perfektion und 100%keit nach Italien, passt er sich sofort an. Dort spricht er dann auch von Mailand, Venedig, Genua und Neapel, wenn er Milano, Venezia, Genova und Napoli meint. Korrektes Italienisch scheint nicht das gleiche Ansehen bei anderen Zeitgenossen zu erzeugen wie perfektes Amerikanisch. Natürlich denkt man dabei nicht an das Ansehen, sondern an das image.

Es war in Burg-St.Moritz, einer Kleinstadt in den französischen Alpen. Die Leute dort sagen Bourg-St.Maurice. Ein Mann auf der Straße, nach dem Weg befragt, antwortete mir: “Hinter makdonnall links abbiegen”. Die französischen Bezeichnungen für ‘hinter’ und ‘links abbiegen’ verstand ich. Mit ‘makdonnall’ konnte ich jedoch gar nichts anfangen. Ich fuhr die StraÃ?e einfach weiter runter und sah eine Mc-Donalds-Filiale. Da war es dann klar. Dabei bemerkte ich zu meinem Entsetzen, daÃ? auch ich gar nicht anders mehr sagen kann als: Mäk Donnelds.

Früher machte man die Standesunterschiede an der Kleidung fest. Die Besseren waren leicht durch andere Kleidung von den Geringeren zu unterscheiden. Die Schirmmütze der Armen von damals ist als baseball-cap zurückgekehrt. Nicht als Zeichen von Armut, sondern als folgsame Anpassung an den Zeitgeist. Einige Jugendliche scheinen diese Caps nachts im Bett noch auf dem Kopf zu behalten. Weil sie wohl im Kopf so schönes Selbstwert-Gefühl verschaffen. Nachdem nicht einmal der Stern aus Stuttgart-Untertürkheim beim Prestige das mehr ist, was er einmal war, brauchten die Menschen einen Ersatz dafür. Vor allem einen, der nicht so teuer ist wie ein Mercedes. Nun übernehmen sie jede alberne Bezeichnung aus Amerika mit Eifer und Wonne. Die in den USA durchaus gängige Bezeichnung ‘name drop in’ jedoch nicht. Das ist auch verständlich. Würde es doch zuviel offen legen. ‘name drop in’ bedeutet: Durch Namen hinein kommen. (Im Kreis der Besseren dazu gehören). Es gibt wohl viele Menschen für die das überaus wichtig zu sein scheint.

Schon 200 Jahre vor Christus meinte Ben Akiba, damals ein weiser Mann im Orient,: “Es ist alles schon einmal da gewesen”. Recht hatte er. Denn vor 100 Jahren hatten wir in Deutschland das gleiche ‘name drop in’ in französischer Ausführung schon einmal. Was heute als cool gilt, war damals ‘en vogue’ und super trendy der ‘dernier crie’. Der Bürgersteig war das Trottoir, das Sofa das Chaiselongue, der kleine Schrank das Vertikot. Von damals erhalten geblieben ist uns nur die Geldbörse, das Portemonnaie. Daher glaube ich, daÃ? sich die gleiche Unsitte in amerikanischer Ausführung eines Tages, bis auf einige Reste, von selbst ‘canceln’ wird.


PING in LotusScript

Die Klasse PING enhält die Funktion Ping(), der die zu überpr?fende Adresse als Zeichenkette in der Form “127.0.0.1” übergeben wird. Ist der Ping erfolgreich wird true zurückgegeben,ansonsten false.

Die Konstante TIMEOUT gibt an, wie viele Millisekunden ( DEFAULT = 500 ms ) die Funktion versuchen soll, den Zielrechner zu erreichen. Zum Testen der Funktion erstellen sie einen Button und kopieren sie den folgenden Code in den Click Event der Schaltfläche

Read More


nKill – Restart Notes after a crash

Wer kennt das nicht. Der Notes Client ist mal wieder abgestürzt und läßt sich nun beim besten Willen nicht mehr zu einem Neustart bewegen. Schuld daran sind Prozesse, die nach einem Absturz im Speicher verbleiben und den Neustart verhindern.
Zwar gibt es bereits Tools auf dem Markt, die einem aus diesem Dilemma heraushelfen können. Aber in den meisten Fällen müssen diese Tools erst installiert und nach einem Crash erst aufgerufen werden.
Daher habe ich dieses Tool geschrieben. Für die Interessierten habe ich den Quelltext beigefügt. Das Tool lauft unter Win9.x/WinME/Win NT 3.x/Win NT 4.0/ Win 2000 und XP

#include "windows.h"
#include "tlhelp32.h"
#include "iostream."
#include "string.h"
#ifdef BORLANDC
#include "string.h"
#include "ctype.h"
#endif
int KILL_PROC_BY_NAME(const char *);
int main(int argc,char *argv[])
{
int iRes;
char string[] = "ldapsearch.exe, nadminp.exe, naldaemn.exe, namgr.exe, 
napdaemn.exe, nchronos.exe, ncollect.exe,nconvert.exe, ndiiop.exe, 
ndyncfg.exe, nhldaemn.exe, nhttp.exe, nhttpcgi.exe, nimapcl.exe, 
nlnotes.exe,nlogasio.exe, nminder.exe, nnntpcl.exe, nnotesmm.exe, 
stringn.exe, npop3.exe, nupdall.exe, nupdate.exe, nweb.exe,
nwrdaemn.exe, nxpcdmn.exe, rtfcnvt.exe, CLHAP32.EXE, ntaskldr.exe";
char separator[] = ",";
char *token;
token = strtok(string, separator);
while( token != NULL )
{
iRes=KILL_PROC_BY_NAME(token);
cout < < token << " Result code=" << iRes << endl;
token = strtok(NULL, separator);
}
    return 0;
}
int KILL_PROC_BY_NAME(const char *szToTerminate)
//   Return codes are as follows:
//   0   = Process was successfully terminated
//   603 = Process was not currently running
//   604 = No permission to terminate process
//   605 = Unable to load PSAPI.DLL
//   602 = Unable to terminate process for some other reason
//   606 = Unable to identify system type
//   607 = Unsupported OS
//   632 = Invalid process name
//   700 = Unable to get procedure address from PSAPI.DLL
//   701 = Unable to get process list, EnumProcesses failed
//   702 = Unable to load KERNEL32.DLL
//   703 = Unable to get procedure address from KERNEL32.DLL
//   704 = CreateToolhelp32Snapshot failed
{
BOOL bResult,bResultm;
DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0;
DWORD iCbneeded,i,iFound=0;
char szName[MAX_PATH],szToTermUpper[MAX_PATH];
HANDLE hProc,hSnapShot,hSnapShotm;
OSVERSIONINFO osvi;
HINSTANCE hInstLib;
int iLen,iLenP,indx;
HMODULE hMod;
PROCESSENTRY32 procentry;
MODULEENTRY32 modentry;
iLenP=strlen(szToTerminate);
if(iLenP<1 || iLenP>MAX_PATH) return 632;
for(indx=0;indx    szToTermUpper[indx]=toupper(szToTerminate[indx]);
szToTermUpper[iLenP]=0;
// PSAPI Function Pointers.
BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
DWORD, LPDWORD );
DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
LPTSTR, DWORD );
// ToolHelp Function Pointers.
HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;
// First check what version of Windows we're in
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bResult=GetVersionEx(&osvi);
if(!bResult)     // Unable to identify system version
return 606;
if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
(osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS))
return 607;
if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
{
hInstLib = LoadLibraryA("PSAPI.DLL");
if(hInstLib == NULL)
return 605;
// Get procedure addresses.
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
GetProcAddress( hInstLib, "EnumProcesses" ) ;
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
DWORD, LPDWORD)) GetProcAddress( hInstLib,
"EnumProcessModules" ) ;
lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE,
LPTSTR, DWORD )) GetProcAddress( hInstLib,
"GetModuleBaseNameA" ) ;
if(lpfEnumProcesses == NULL ||
lpfEnumProcessModules == NULL ||
lpfGetModuleBaseName == NULL)
{
FreeLibrary(hInstLib);
return 700;
}
bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
if(!bResult)
{
// Unable to get process list, EnumProcesses failed
FreeLibrary(hInstLib);
return 701;
}

// How many processes are there?
iNumProc=iCbneeded/sizeof(DWORD);

// Get and match the name of each process
for(i=0;i    {
// Get the (module) name for this process

strcpy(szName,"Unknown");
// First, get a handle to the process
hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
aiPID[i]);
// Now, get the process name
if(hProc)
{
if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) )
{
iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
}
}
CloseHandle(hProc);
// We will match regardless of lower or upper case
#ifdef BORLANDC
if(strcmp(strupr(szName),szToTermUpper)==0)
#else
if(strcmp(_strupr(szName),szToTermUpper)==0)
#endif
{
// Process found, now terminate it
iFound=1;
// First open for termination
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]);
if(hProc)
{
if(TerminateProcess(hProc,0))
{
// process terminated
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 0;
}
else
{
// Unable to terminate process
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 602;
}
}
else
{
// Unable to open process for termination
FreeLibrary(hInstLib);
return 604;
}
}
}
}

if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
{
// Win/95 or 98 or ME

hInstLib = LoadLibraryA("Kernel32.DLL");
if( hInstLib == NULL )
return 702;

lpfCreateToolhelp32Snapshot=
(HANDLE(WINAPI *)(DWORD,DWORD))
GetProcAddress( hInstLib,
"CreateToolhelp32Snapshot" ) ;
lpfProcess32First=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32First" ) ;
lpfProcess32Next=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
GetProcAddress( hInstLib, "Process32Next" ) ;
lpfModule32First=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
GetProcAddress( hInstLib, "Module32First" ) ;
lpfModule32Next=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
GetProcAddress( hInstLib, "Module32Next" ) ;
if( lpfProcess32Next == NULL ||
lpfProcess32First == NULL ||
lpfModule32Next == NULL ||
lpfModule32First == NULL ||
lpfCreateToolhelp32Snapshot == NULL )
{
FreeLibrary(hInstLib);
return 703;
}

hSnapShot = lpfCreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS, 0 ) ;
if( hSnapShot == INVALID_HANDLE_VALUE )
{
FreeLibrary(hInstLib);
return 704;
}

// Get the first process' information.
procentry.dwSize = sizeof(PROCESSENTRY32);
bResult=lpfProcess32First(hSnapShot,&procentry);

// While there are processes, keep looping and checking.
while(bResult)
{
// Get a handle to a Toolhelp snapshot of this process.
hSnapShotm = lpfCreateToolhelp32Snapshot(
TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
if( hSnapShotm == INVALID_HANDLE_VALUE )
{
CloseHandle(hSnapShot);
FreeLibrary(hInstLib);
return 704;
}
// Get the module list for this process
modentry.dwSize=sizeof(MODULEENTRY32);
bResultm=lpfModule32First(hSnapShotm,&modentry);

// While there are modules, keep looping and checking
while(bResultm)
{
if(strcmp(modentry.szModule,szToTermUpper)==0)
{
// Process found, now terminate it
iFound=1;
// First open for termination
hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID);
if(hProc)
{
if(TerminateProcess(hProc,0))
{
// process terminated
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 0;
}
else
{
// Unable to terminate process
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
CloseHandle(hProc);
FreeLibrary(hInstLib);
return 602;
}
}
else
{
// Unable to open process for termination
CloseHandle(hSnapShotm);
CloseHandle(hSnapShot);
FreeLibrary(hInstLib);
return 604;
}
}
else
{  // Look for next modules for this process
modentry.dwSize=sizeof(MODULEENTRY32);
bResultm=lpfModule32Next(hSnapShotm,&modentry);
}
}

//Keep looking
CloseHandle(hSnapShotm);
procentry.dwSize = sizeof(PROCESSENTRY32);
bResult = lpfProcess32Next(hSnapShot,&procentry);
}
CloseHandle(hSnapShot);
}
if(iFound==0)
{
FreeLibrary(hInstLib);
return 603;
}
FreeLibrary(hInstLib);
return 0;
}

DOWNLOAD


Lotus Script Klasse “Systeminformationen”

Lotus Script Klasse mit folgenden Funktionen:

    kleine/ grosse Schriftarten installiert
    Ist eine Soundkarte installiert
    Anzahl Farben
    Tastatur Typ
    Anzahl Funktionstasten
    Hostname
    IP Adresse des Host
    aktuelle Bildschirmaufloesung
    CPU Taktfrequenz
    Anzahl Processoren
    Prozessor Typ
    Prozessor Build Level
    Prozessor Revision
    Betriebssystem
    Windows Systemverzeichnis
    Notes Verzeichnis
    Welche COM Ports sind verfuegbar
    Dateisystem, Label und
    Seriennummer der Festplatte
    Neustart von Windows ( auch Windows 2000 !!
    LockWorkstation
    Internet – Verbindungsstatus

DOWNLOAD