Mail Rules Extended

I recently posted an idea on IdeaJam to enhance the mail rules dialog on a Domino server to overcome the restriction of only use the “hard coded” conditions. There have been several attemps to enhance the dialog in the past ( Chris Linfoot for example ), but none of them adresses the use of a formula as a condition.

I’ve modified Chris’s sample db and added the requested functionality. You can download it here. To use it in your environment, replace the (RulesDlg) form and the Rules Script Lib in your names.nsf with the according design elements in the download.
Keep in mind that modifying the Domino Directory is dangerous if you are not sure of what your doing.


Is User A Member Of A (Nested) Group ?

Working with nested groups, it can be hard to determine if a user is member of the “base” group. The following class contains a method to do the job.

IsGroupMember ( GroupName, UserName ) calls method ExplodeGroup, which fills an array with all members of the group. It also resolves nested groups.

IsGroupMember now checks if the username is a member of this array using Lotusscript function ArrayGetIndex.

Class NotesDominoDirectory

	Private strServer As String

	Public Sub new (server As String )
		strServer = server
	End Sub

	Public Function ExplodeGroup (GroupName As String) As Variant

		Dim s As New Notessession
		Dim db As New NotesDatabase ( Me.strServer, "names.nsf" )
		Dim doc As NotesDocument
		Dim view As NotesView
		Dim i As Integer, j As Integer, k As Integer
		Dim arrGrp1, arrGrp2 As Variant

		Set view=Db.GetView ("($VIMGroups)")
		Set doc=View.GetDocumentByKey (GroupName)
		Redim arrMembers (1) As Variant
		j = 0

		If Not (doc Is Nothing) Then
			arrGrp1= Doc.GetItemValue ("Members")
			For i= 0 To Ubound (arrGrp1)
				arrGrp2= Me.ExplodeGroup (arrGrp1 (i))
				Redim Preserve arrMembers (Ubound (arrGrp2) + j) As Variant
				For k= 0  To Ubound (arrGrp2)
					arrMembers (j) = arrGrp2 (k)
					j = j + 1
				Next
			Next
		Else
			Redim arrMembers (0) As Variant
			arrMembers (0) = GroupName
		End If

		ExplodeGroup= Arrayunique (arrMembers)

	End Function 

	Public Function IsGroupMember ( strGroup As String, strUser As String ) As Boolean

		IsGroupMember = False

		If (Arraygetindex (Me.ExplodeGroup (strGroup), strUser , 5))  Then
			IsGroupMember = True
		End If

	End Function

	Public Function IsGroupMemberExt ( strGroup As String, strUser As String ) As Boolean
		' uses undocumented function
		Dim arrMembers As Variant
		IsGroupMemberExt = False
		arrMembers =
            Evaluate(|@ExpandNameList("|& strServer & |":"names.nsf";"|& strGroup &|")| )
		If (Arraygetindex ( arrMembers, strUser, 5)) Then
			IsGroupMemberExt = True
		End If
	End Function

End Class

Here is a sample of how to check if Ulrich Krause is member of group “Everybody”

Sub Click(Source As Button)
	Dim res As Variant
	Dim dd As New NotesDominoDirectory ("serv01/singultus")
	Msgbox dd.IsGroupMember ( "Everybody" , "CN=Ulrich Krause/O=singultus")
End Sub

There is also an undocumented @formula @ExpandNameList to expand a group and all nested groups to all the names.

Function IsGroupMemberExt ( strGroup As String, strUser As String ) As Boolean
	' uses undocumented function
	Dim arrMembers As Variant
	IsGroupMemberExt = False
	arrMembers =
         Evaluate(|@ExpandNameList("|& strServer &|":"names.nsf";"|& strGroup &|")| )
	If (Arraygetindex ( arrMembers, strUser, 5))  Then
	     IsGroupMemberExt = True
	End If
End Function

WordPress Plugin For LotusScript And Formula Syntax Highlighting

I’m using wordpress for blogging and have wp-syntax installed for quite a while as a syntax colour code/highlighter. wp-syntax supports many languages. But it does not support Lotus Script or @Formula language out of the box.

You can easily add support for these languages by adding a file to GeSHi, the Generic Syntax Highlighter, which is used in wp-syntax and some other plugins for wordpress.

I had done this a year ago for Notes 7. Now Richard Civil posted a new version for Notes 8. If your blog is based on wordpress and you are looking for an easy to implement, easy to use syntax colour code/highlighter to prettify your Lotus Script or formula code, jump over to RichardCivil.net.


Programmatically Change The Design Of A Local Database

From the Lotus Notes KnowledgeBase (#1280243)

You want to programmatically change or update the design of a local Lotus Notes® database from a template. For your particular scenario, replication is not an option. The database is local to the client, and there is no server replica to pull the design changes from. So you would like to use LotusScript to programmatically change the design.

First of all, the template with which you want to update the database design much also be local to this Notes client. If that is true, one way to accomplish this task is to use the LotusScript Shell command to call the convert program located on the Notes client.
The convert program takes the same commands as the server-based convert task. For example, if you want to update the local names.nsf database with the latest personal address book template, you could use the following code on a Microsoft® Windows® platform because the name of the program on Windows is nconvert.exe:

Sub Initialize
Dim result As Variant
result = Shell("nconvert -d names.nsf * pernames.ntf")
End Sub

When you call the convert program, it reads the notes.ini file and retrieves the ID value form the KeyFileName entry. The convert program runs under the authority of that ID.
You will be prompted to enter the password for that ID before the task continues if

  • the Notes client is not running, or
  • the Notes client is running and you have not selected “Don’t prompt for a password from other Notes-based programs” in your User Security preferences. (If you check that option, you are not prompted for a password if the Notes client is running.)

Get A JSONReader And JSONWriter For FREE

JSONTroy Reimer of SNAPPS donates LotusScript JSONWriter and JSONReader to the community.
You can download Version 1.0 of JSONReader and JSONWriter here.

The database (json.nsf) contains LotusScript classes for parsing and creating JSON text.
These classes are contained in five script libraries: ls.snapps.JSONArray, ls.snapps.JSONObject, ls.snapps.JSONReader, ls.snapps.JSONWriter, and ls.snapps.JSONWrapperConverters.

The JSONArray and JSONObject classes are wrapper classes that are used by the JSONReader class. Additional information can be found in the “Help – About This Database” document.

The JSON LotusScript Classes are also available on OpenNTF.


SnTT: @ServerAccess in LotusScript

SnTT

You can use @ServerAccess to check if a specified user has a specified administrative access level to a server. For a list of keywords to represent the access level you want to check for take a look at the designer help either on your local client or on the web.

But what to do if you want to check the server access level using Lotus Script? The help document does not give you a cross reference to Lotusscript.

In this case, the Evaluate statement is your friend.
For further information about how to use Evaluate I recommend to read the following article on DeveloperWorks: “Simplifying your LotusScript with the Evaluate statement

The following function uses evaluate and @ServerAccess to make the @function available in LotusScript.

Function atServerAccess ( 
sAction As String, sUserName As String, sServerName As String ) As Boolean
  Dim vAccess As Variant
  vAccess = 
   Evaluate(|@ServerAccess(| + sAction + |; "| + sUserName_
                + |"; "| + sServerName + |")|)	atServerAccess = Cbool(vAccess(0))
End Function

Here is a sample of how to call the function

Sub Click(Source As Button)
  Dim sUser As String
  Dim sServer As String
  Dim sAction As String
  sUser = "Bill Gates/Microsoft"
  sServer = "MyServer/foo"
  sAction = "[RemoteAccess]"

  ' returns TRUE of FALSE
  Msgbox atServerAccess ( sAction, sUser, sServer )
End Sub


What Is Wrong With Year 1700?

2008 is a leap year again. The Gregorian calendar, the current standard calendar in most of the world, adds a 29th day to February in 97 years out of every 400, a closer approximation than once every four years. This is implemented by making every year divisible by 4 a leap year unless that year is divisible by 100. If it is divisible by 100 it can only be a leap year if that year is also divisible by 400.

So, in the last millennium, 1600 and 2000 were leap years, but 1700, 1800 and 1900 were not. In this millennium, 2100, 2200, 2300, 2500, 2600, 2700, 2900 and 3000 will not be leap years, but 2400 and 2800 will be. You can find numerous examples in almost every programming language of how to determine if a year is a leap year or not.

In LotusScript as well as with @Formula you can “adjust” a given date to another date depending on the parameters you use. So the easiest method to determine a leap year is to set the date to March, 1st of the given year and “substract” one day. If the resulting date is Feb., 29th, the year is a leap year.

Here is my @Formula

_date:=[01.03.1700];
@Prompt([Ok];"Last Day";@Text( @Day( @Adjust( _date; 0;0;-1;0;0;0 ) ) ) )

I expected a 28 in the message box, but it prompted 29 ! Oups …

I tried the same using LotusScript and the NotesDateTime class

Sub Click(Source As Button)
	Set dt = New NotesDateTime( Datenumber( 1700 ,3, 1) )
	Call dt.AdjustDay (-1)
        Msgbox dt.Localtime
End Sub

Guess what it returns. 29.02.1700 ! Another oups …

Seems that IBM / Lotus uses another calender than the Gregorian calendar. No surprise is that 🙂

You might want to try the next piece of code and watch what happens …

Sub Click(Source As Button)
	Set dt = New NotesDateTime( Datenumber( 1700 ,3, 1) )
	Call dt.AdjustDay (-1)
	Msgbox Day (dt.Localtime)
End Sub

An error message occurs, stating that there is a “Type mismatch”. I guess that some subroutines deep in the core code are not sure which calendar to use; Gregorian or IBM calendar. By the way, you get the same error when replacing the 1700 by 1500, 1400, 1300, 1100 and 1000.

If you happen to travel to the year 1700 using a time machine, be careful when planning a meeting at the end of February …


Display Date Range As Bar In Notes Views

You can find a lot of stuff on the internet like Chris Blatnick’s ” Using Color Columns To Make A Gantt Chart” to display column values either as color or as picture ( you might take a look at “A Splash of Color” as well ).
Today I would like to share my solution on how to build a view to display a date range like it is used in group calendar applications.

Display Calendar Entries

I tried to keep the view design as simple as possible to avoid performance impacts. As you can see in the sample database there are no formulas in the columns. All necessary information is stored in a “collector” document.

Form Design

The form contains one field for each day in a month ( Day_1 … Day_31 ). All fields are of type text with multiple values enabled. To colorize Day_1 ( and all subsequent colums ) simply put 0 : 255 : 255 into Day_1 which results in an aquamarine color.
Surfing the web for more information about view column colors I found this article on breakingpar.com.
Instead of using 6 decimal numbers for foreground and background color, you can use hexadecimal values as well. This would make it easier to handle the data when passing it via LotusScript to the collector document.

We can now build a list of colorcodes.

' Declaration

Dim ColorCode List As String

Sub Initialize
	ColorCode("Alice_Blue") = "F0F8FF"
	ColorCode("Antique_White") = "FAEBD7"
	ColorCode("Aqua") = "00FFFF"
	ColorCode("Aquamarine") = "7FFFD4"
	ColorCode("Azure") = "F0FFFF"
	ColorCode("Beige") = "F5F5DC"
	ColorCode("Bisque") = "FFE4C4"
	ColorCode("Black") = "000000"
	ColorCode("Blanched_Almond") = "FFEBCD"
	ColorCode("Blue") = "0000FF"
	ColorCode("Blue_Violet") = "8A2BE2"

...
End Sub

You can call the following function and pass a colorcode from the list as a parameter. You can use any hexadecimal value that is not in the list as well.

Function SetMarker ( doc As NotesDocument, user As String,_
DateFrom As NotesDateTime, DateTo As NotesDateTime, color As String ) As Integer

	On Error Goto ERR_HANDLE
	SetMarker = 0
	Dim item As NotesItem
	Dim i As Integer
	Dim MarkerBegin As Integer
	Dim MarkerEnd As Integer
	Dim MarkerColor (1) As String

	If Iselement(ColorCode( color)) Then
		MarkerColor(0) = ColorCode( color)
		MarkerColor(1) = ColorCode( color)
	Else
		MarkerColor(0) = color
		MarkerColor(1) = color
	End If

	MarkerBegin = Day ( DateFrom.DateOnly )
	MarkerEnd = Int ( Day ( DateTo.DateOnly )) + 1

	Set Item = doc.ReplaceItemValue ( DAY_FLD_PREFIX + Cstr( MarkerBegin ), MarkerColor)
	If MarkerEnd - MarkerBegin > 1 Then
		For i = (MarkerBegin +1) To (MarkerEnd -1)
			Set Item = doc.ReplaceItemValue ( DAY_FLD_PREFIX + Cstr ( i ), "" )
		Next
	End If
	If Not ( MarkerEnd > 31 ) Then
		Set Item = doc.ReplaceItemValue ( DAY_FLD_PREFIX + Cstr ( MarkerEnd ), "FFFFFFF" )
	End If
	Call doc.Save ( False, False )

EXITPOINT:
	Exit Function
ERR_HANDLE:
	SetMarker=1
End Function

The function writes the necessary values to the document. It translates the DateFrom and DateTo parameters and writes the according colorcodes. As you can see in the next screenshot, only two fields are needed to build a bar for a date range.

Values

Notes colorizes the column displaying the colorcode from the document and subsequent columns as long as you do not set the column to another color. Any hexadecimal value longer than 6 will reset the column color to default.

DOWNLOAD Sample Database


Instance member…does not exist’ when enabling Out Of Office

Today I had a lot of calls in our helpdesk regarding Out Of Office. Users complained that the had enabled the agent before Christmas and it worked fine but when they tried to disable the agent it does not disable. Instead the Out Of Office profile shows the following message:

Even it is in German, I think I do not have to translate the blue text as you might know that this is the message that is displayed when a user has editor access to his mail file and tries to enable / disable the Out Of Office agent.
With editor access an administration request is created that will enable / disable the agent on behalf of the user.

Well, nothing special so far. Except the fact that this message is displayed to the user all day long and I could not find any administration request on the server.

I tried to reproduce the error on my workstation but failed. I opened the users desktop remotely and there it was. An error message occurred in the statusbar stating that there is a

Notes error: 182 Instance member CONFIGUREMAILAGENTTEXT does not exist.

I searched the Knowledge Base for CONFIGUREMAILAGENTTEXT and found this technote

In Lotus Notes®, you attempt to enable the Out Of Office (OOO) agent in your mail file. The agent does not enable and you notice the following error message in the status bar of the Notes client:

“Notes error: 182 Instance member CONFIGUREMAILAGENTTEXT does not exist.”

This issue only occurs for users with Editor access to their mail file and only occurs in Notes, regardless of the mail template design being used. The issue does not occur when using Lotus Domino® Web Access (DWA) mail.

So, what has happened?

On December, 29th, 2007 I did a mass change on the users mail files to ensure that all ACL only have editor access with all options set except ‘Can Create personal agents’.

We use Domino server version 7.0.3 and Notes Client version 7.0.2 with a slightly modified dwa7.ntf mail template. The changes do not touch the Out Of Office profile !

Reading the technote mentioned before, I found the following hint:

NOTE: The DWA7 client that ships with the Notes/Domino 7.0.2 release is incompatible with all previous versions of Notes.

All previous versions of Notes? Does this mean version 7.0.1, too ?
To make a long story short; yes it means that version 7.0.1 is not compatible with dwa7.ntf shipped with client version 7.0.2.

And yes, we have some clients still using this version. Exactly the same users who are not able to disable the Out of Office agent are on this ‘old’ client version.

To solve the puzzle, I will have to update the clients ASAP J

Another option ( according to the technote ) is to grant designer access. I used the following code to do the changes out of the Domino Directory.

Create a new agent in the DD ( Select from menue, All selected documents ) and copy the following code into the agent.

Option Public
Option Declare

'Use "OpenLogFunctions"
Sub Initialize
	'On Error Goto Errorhandler
	Dim ws As New NotesUIWorkspace
	Dim session As New NotesSession
	Dim db As NotesDatabase
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Dim total As Long
	Dim docnum As Long

	Set db = session.CurrentDatabase

	Set dc = db.UnprocessedDocuments
	total = dc.Count
	docnum = 0

	Set doc = dc.GetFirstDocument
	While Not doc Is Nothing
		docnum = docnum + 1
		Call UpdateStatusBar(docnum, total)
		Call ProcessPersonDoc(doc)
		Set doc = dc.GetNextDocument(doc)
	Wend

	Call ws.ViewRefresh
	'Exit Sub

Errorhandler:
	'Call LogError
	'Exit Sub

End Sub

Sub UpdateStatusBar(x As Long, total As Long)
	'This will display the percentage complete in the status bar as the agent runs

	Print "Working..." & Cstr(Round((x / total), 2)*100) & "% done"

End Sub

Sub ProcessPersonDoc(doc As NotesDocument)
	'On Error Goto stackError
	Dim s As New NotesSession
	Dim profile As NotesDocument
	Dim owner As String
	Dim ACL As NotesACL
	Dim ACLEntry As NotesACLEntry
	Dim nn As NotesName

	Dim Maildb As New NotesDatabase( doc.MailServer(0), doc.MailFile(0) )
	If Maildb.IsOpen Then
		Print( "Succesfully opened " & Maildb.Title )
		Set profile = Maildb.GetProfileDocument("CalendarProfile")
		Set nn = s.CreateName ( profile.Owner(0) )

		Set ACL = MailDB.ACL
		Set ACLEntry = ACL.GetEntry ( profile.Owner(0) )
		If Not ( ACLEntry Is Nothing ) Then
			ACLEntry.Remove
			ACL.Save
		End If

		'Set OWNER access to DESIGNER
		Set ACLENtry = New NotesACLEntry ( ACL, profile.Owner(0), 5 )
		ACLENtry.CanDeleteDocuments = True
		ACLENtry.CanCreateLSOrJavaAgent = True
		ACLENtry.IsPerson = True
		ACL.Save

	End If

EXITPOINT:
	'Exit Sub
stackError:
	'Call LogError()
	'Resume EXITPOINT
End Sub

Now you can select one or more persons and run the agent against their mail file. The agent will read the calendar profile to determine the mail file owner and then changes the ACL.


Compare Two Arrays

For one of my projects I needed a function to compare two arrays. The following function returns true if both array have the same elements (regardless of their position in arrays).

Function ArraysAreEqual (vA As Variant, vB As Variant) As Variant

	Dim IsEqual As Variant
	ArraysAreEqual = True

	Forall a In vA
		IsEqual = False
		Forall b In vB
			If a = b Then
				IsEqual = True
				Exit Forall
			End If
		End Forall
		If Not IsEqual Then
			ArraysAreEqual = False
			Exit Function
		End If
	End Forall

	Forall b In vB
		IsEqual = False
		Forall a In vA
			If b = a Then
				IsEqual = True
				Exit Forall
			End If
		End Forall
		If Not IsEqual Then
			ArraysAreEqual = False
			Exit Function
		End If
	End Forall

End Function

To execute your code only when both array are different simply use

	If Not (ArraysAreEqual ( mBefore, mAfter )) Then
	   ' your code goes here
           ' ...

	End If

Mail Archivierung – Ein Praxisproblem

Eigentümer einer Maildatei können Zugriffe auf Mails und Kalender über “Werkzeuge – Vorgaben – Zugriff und Delegierung” selbstständig steuern.
Bei der geplanten Archivierung von Mails ergeben sich daraus aber Probleme beim Zugriff auf archivierte Dokumente.

Ein Archivsystem sichert neben den eigentlichen Inhalten der Mail auch die zu diesem Zeitpunkt existierende ACL.

ACL

Lt. der abgebildeten ACL darf also neben dem Eigentümer der Maildate auch der Administrator lesend auf die Mails zugreifen und somit auch auf archivierte Mails.
Wird der Zugriff für den Leser Administrator wieder entfernt, so kann er weder auf die Datenbank noch auf Mails zugreifen, die nach diesem Zeitpunkt archiviert wurden. Sehr wohl kann er aber noch über die Archivrecherche auf Mails zugreifen, die vor dem Zeitpunkt der Löschung seines Zugriffs aus der ACL in das Archiv gespeichert wurden.

Die Probleme, die sich daraus ergeben können, sollen hier nicht weiter erläutert werden.

Ein in der Praxis wohl häufiger auftretendes Problem erfordert aber unbedingte AUfmerksamkeit; eine Lösung muss VOR Beginn der Mailarchivierung implementiert werden.

Dabei geht es um folgendes Szenario:

Ein Vorgesetzter delegiert den Zugriff auf seine Mails an eine Assistentin, die namentlich in die ACL eingetragen wird. Ã?ber einen gewissen Zeitraum werden nun Mails mit diesen Zugriffsberechtigungen archiviert.
Die bisherige Assistentin wird dann einem neuen Vorgesetzten zur Seite gestellt, oder vertritt eine Kollegin.

In Variante 1 hat dann die neue Assistentin keinen Zugriff auf die bisher archivierten Mails, weil sie bisher ja keinen Zugriff auf die Datenbank ihres Vorgesetzen hatte.
In Variante 2 kann nicht auf die archivierten Mails der zusätzlichen Datenbank zugegriffen werden, weil es an den nötigen Berechtigungen zum Zeitpunk der Archivierung fehlt.

Lösen lässt sich dieses Dilemma, wenn man in die ACL der Datenbank eine Gruppe einfügt, die auf die Datenbank Lesezugriff hat.

Hier stösst man aber zugleich auf ein weiteres Problem. Alle Einträge, die in der ACL nicht als MANAGER oder ENTWICKLER eingetragen sind, können vom Eigentümer der Datenbank über die Vorgaben geändert werden. Das betrifft sowohl die Art des Zugriffs als auch das Löschen des Eintrags.

Zugriff und Delegierung

Da wir aber der Gruppe keine Berechtigung als Manager geben wollen, müssen wir anderweitig sicherstellen, daÃ? der MailBox Eigentümer die Rechte der Gruppe nicht ändern kann.
Das kann am Einfachsten dadurch erreicht werden, daÃ? die Gruppe für den Eigentümer gar nicht sichtbar ist.

versteckte Gruppe

Mit einem kleinen Eingriff in die Gestaltung der Maildatei kommt man zum Ziel. Bei Einführung einer Mailarchivierung wird man in der Regel sowieso die Maildatei modifizieren müssen; bei der einen Lösung mehr, bei einer anderen weniger.
Die Modifikation zum Verstecken der Gruppe(n) sind so minimal, daÃ? sie im Prinzip nicht ins Gewicht fallen. Trotzdem sollten die Codeänderungen dokumentiert werden. 🙂

In der Script Bibliothek “ACLManagement” wird der Code ab Zeile 578 ( +/- 2 Zeilen ) folgendermaÃ?en geändert

alt:

Case ACLLEVEL_READER
    x = Ubound(Me.ReadMail)
    Me.ReadMail(x) = Me.aclentry.Name
    Redim Preserve Me.ReadMail(x+1)
    Call IsPublicReader()
    Call IsPublicWriter()

neu:

Case ACLLEVEL_READER
    x = Ubound(Me.ReadMail)
    '############## 26.10.2007,Ulrich Krause ################
    If ( Not Instr(Me.aclentry.Name, "#Arc" ) > 0 ) Then
     Me.ReadMail(x) = Me.aclentry.Name
     Redim Preserve Me.ReadMail(x+1)
     Call IsPublicReader()
     Call IsPublicWriter()
   End If

Durch diese einfache Ã?nderung ist es nun möglich, in die ACL der Maildatenbanken Gruppen einzufügen, die mit dem Prefix “#Arc” beginnen. Der Eintrag in das Domino Directory und die Pflege der Gruppenmitglieder erfolgt dann bei Bedarf manuell.
Der Name der Gruppe wird aus dem Prefix und z.B. den Namen des Mail Box Eigentümers gebildet. Damit lässt sich dann der Zugriff datenbankspeziefisch steuern. Eine weitere Gruppe “#ArcDefaultReaders” mit ACLLEVEL_READER kann dann in gleicher Weise zur datenbankübergreifenden Recherche verwendet werden.

Dies ist die aus meiner Sicht einfachste Lösung um sicherzustellen, daÃ? unterschiedliche Personen auf archivierte Mails zugreifen können.


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


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