Nachrichten im NT-Netzwerk verschicken

Veröffentlicht: 09. Okt 2003 | Aktualisiert: 27. Jun 2004

Von Mathias Schiffer

Die Microsoft Newsgroups sind eine Quelle schier unerschöpflichen Wissens, das nahezu auf Knopfdruck abrufbar ist: Hunderte deutschsprachige Entwickler vom Einsteiger bis zum Profi treffen sich hier täglich virtuell, um Fragen zu stellen oder zu beantworten. Auch themennahe Probleme, Ansichten und Konzepte werden miteinander diskutiert. Sie kennen die Microsoft Newsgroups noch nicht? Detaillierte Information für Ihre Teilnahme finden Sie auf der Homepage der Microsoft Support Newsgroups.

Diese Kolumne greift regelmäßig ein besonders interessantes oder häufig nachgefragtes Thema aus einer der Entwickler-Newsgroups auf und arbeitet es aus.

Aus der Visual Basic Newsgroup microsoft.public.de.vb:

Frage: Von der Kommandozeile aus kann ich mit "NET SEND" Kurznachrichten im Netzwerk versenden. Wie kann ich dieses Ziel auch mit Visual Basic 5 oder Visual Basic 6 erreichen?

Mit Hilfe von "NET SEND" können Sie Kurznachrichten zwischen Rechnern in einem Netzwerk versenden. Dabei ist keine Magie im Spiel, sondern allein die Unicode-basierende API-Funktion NetMessageBufferSend.

Newsgroups0903.gif

Die "NET SEND"-Messagebox in gutartiger Aktion

Voraussetzungen
Damit der Nachrichtenversand auf diese Weise funktioniert, sind zwei Voraussetzungen notwendig:

Zum einen müssen sendender und empfangender Rechner der Windows NT-Familie angehören, also als Betriebssysteme Windows NT 3.51 oder 4.0, Windows 2000, Windows XP oder Windows Server 2003 einsetzen.

Weiterhin muss der Windows-Dienst "Nachrichtendienst" gestartet worden sein. Letzteres ist nach einer Standard-Windowsinstallation gegeben. Nachdem sich jedoch seit gut einem Jahr auch Spammer diesen Dienst räuberisch zu Nutze gemacht haben, um ihre lästigen Werbenachrichten aufzuzwingen, werden sie ihn bei vielen Rechnern, die direkt an das Internet angeschlossen sind, deaktiviert finden (und falls Sie Opfer solcher Werbefenster sind und ihre Herkunft bisher nicht verstanden - deaktivieren Sie diesen Dienst auf Ihrem Rechner).

Schließlich bedarf es unter bestimmten Konstellationen hinreichender Rechte, um die Funktion erfolgreich aufrufen zu können. Diese Szenarien finden Sie in der Dokumentation zur Funktion NetMessageBufferSend im Detail beschrieben. Im einfachsten Fall ist kein bestimmtes Recht notwendig, um die Funktion auf der lokalen Maschine ausführen zu können.

Implementation
Der Aufbau der Funktion NetMessageBufferSend bereitet weiter keine Schwierigkeiten. Im Platform SDK ist sie wie folgt beschrieben:

NET_API_STATUS NetMessageBufferSend( 
  LPCWSTR servername,   
  LPCWSTR msgname,   
  LPCWSTR fromname,  
  LPBYTE buf,  
  DWORD buflen    
);

Die notwendige Umsetzung in einen Declare-Prototyp für Visual Basic ist entsprechend sehr einfach:

Private Declare Function NetMessageBufferSend _ 
  Lib "netapi32" ( _ 
  ByVal servername As String, _ 
  ByVal msgname As String, _ 
  ByVal fromname As String, _ 
  ByVal buf As String, _ 
  ByVal buflen As Long _ 
  ) As Long

Klären wir kurz die Bedeutung der einzelnen Parameter ab:

servername: Hier wird der Name des Computers im Netzwerk angegeben, auf dem die Funktion ausgeführt werden soll. Im Windows-Netzwerk muss er mit zwei Backslash-Zeichen ("\\") beginnen. Wird dieser Parameter mit einem Nullstring (vbNullString) bedient, wird der lokale Computer als Nachrichtenüberbringer verwendet.

msgname: In diesem Parameter wird der Empfänger der Nachricht angegeben.

fromname: In diesem Parameter geben Sie den Absender an. Wird dieser Parameter mit einem Nullstring (vbNullString) bedient, so wird der Name des lokalen Computers als Absenderangabe verwendet.

buf: Dieser String enthält den Text der Nachricht, die den bzw. die Empfänger erreichen soll.

buflen: In diesem Parameter wird übergeben, wie viele Bytes der Parameter buf enthält.

Bei der Anwendung der Funktion ist es notwendig zu berücksichtigen, dass sie ausschließlich in einer Unicode-Version existiert. Daher müssen alle String-Parameter ausdrücklich in Unicode-Notation übergeben werden. Hierfür ist kein größerer Aufwand notwendig als die Umwandlung der Strings mithilfe der VB-eigenen StrConv-Funktion.

Beispielcode Im folgenden Beispielcode finden Sie ein Anwendungsbeispiel für die Funktion NetMessageBufferSend inklusive aller notwendiger API-Deklarationen und Fehlerauswertungen. Weiterhin wird vor dem Aufruf der Funktion geprüft, ob die Betriebssystem-Voraussetzung senderseitig erfüllt ist. Verwenden Sie diesen Beispielcode in einem Standardmodul, um die Nutzung der Funktion auszuprobieren.

Tipp: Kopieren Sie den gesamten Quelltext zunächst in WRITE.EXE und erst von dort aus in Ihre Entwicklungsumgebung, um den Verlust von Zeilenumbrüchen zu vermeiden.

Option Explicit ' Standardmodul 
' ------------------------------------------------------ 
' - Nachrichten im NT-Netzwerk verschicken - 
' ------------------------------------------------------ 
' - Beispiel zum Aufruf der API-Funktion NetMessage-   - 
' - BufferSend unter Windows NT/2000/XP/Server 2003.   - 
' - (c) 2003 by Mathias Schiffer / <A href="mailto:Schiffer@mvps.org">Schiffer@mvps.org</A>   - 
' ------------------------------------------------------ 
'   
' Beispielaufruf: 
' --------------- 
' If Send(Recipient:="Arbeitsbiene", _ 
'   Sender:="Cheffe", _ 
'   Message:="Schluss mit Arbeit: Umtrunk " & _ 
'   "mit Grillgut im Dachgarten!") Then 
'   MsgBox "Die frohe Botschaft wurde verbreitet!" 
' Else 
'   MsgBox "Doch lieber nochmal anrufen..." 
' End If 
' ------------------------------------------------------ 
' Fehlerkonstante für NetMessageBufferSend: 
Private Const NERR_SUCCESS   As Long = 0& 
Private Const ERROR_ACCESS_DENIED  As Long = 5& 
Private Const ERROR_NOT_SUPPORTED  As Long = 50& 
Private Const ERROR_INVALID_PARAMETER As Long = 87& 
Private Const NERR_BASE   As Long = 2100& 
Private Const NERR_NETWORKERROR As Long = (NERR_BASE + 36&) 
Private Const NERR_NAMENOTFOUND As Long = (NERR_BASE + 173&) 
' Ermittlung des Betriebssystems (hier: Prüfung auf NT) 
Private Const VER_PLATFORM_WIN32_NT As Long = 2& 
Private Type OSVERSIONINFO 
  OSVSize As Long 
  dwVerMajor As Long 
  dwVerMinor As Long 
  dwBuildNumber As Long 
  PlatformID As Long 
  szCSDVersion  As String * 128 
End Type 
Private Declare Function GetVersionEx _ 
  Lib "kernel32" Alias "GetVersionExA" ( _ 
  ByRef VersionInformation As OSVERSIONINFO _ 
  ) As Long 
' NET SEND-Funktionalität per NetMessageBufferSend 
Private Declare Function NetMessageBufferSend _ 
  Lib "netapi32" ( _ 
  ByVal Servername As String, _ 
  ByVal msgname As String, _ 
  ByVal fromname As String, _ 
  ByVal buf As String, _ 
  ByVal buflen As Long _ 
  ) As Long 
' ------------------------------------------------------ 
Public Function Send(Optional ByVal Recipient As String, _ 
   Optional ByVal Message As String, _ 
   Optional ByVal Sender As String, _ 
   Optional ByVal Servername As String) _ 
   As Boolean 
  ' Prfe, ob ein NT-Betriebssystem vorliegt: 
  If Not IsWinNT Then ' Funktion nicht ausführbar 
 MsgBox "Die Send-Funktion kann nur auf Rechnern mit einem " & _ 
  "Betriebssystem der Windows NT-Familie verwendet " & _ 
  "werden.", _ 
  vbCritical, "Send-Funktion" 
 Exit Function 
  End If 
  ' Wurde ein Servername übergeben, muss die 
  ' UNC-Konvention eingehalten werden: <A href="file://SERVERNAME/">\\SERVERNAME</A> 
  If Len(Servername) > 0 Then 
 If Left$(Servername, 1) <> "\" Then 
   Servername = "\" & Servername 
 End If 
 If Left$(Servername, 2) <> "\\" Then 
   Servername = "\" & Servername 
 End If 
  End If 
  ' Umwandeln der Angaben in Unicode-Strings: 
  If Len(Recipient) > 0 Then 
 Recipient = StrConv(Recipient, vbUnicode) 
  Else 
 Recipient = vbNullString 
  End If 
  If Len(Message) > 0 Then 
 Message = StrConv(Message, vbUnicode) 
  Else 
 Message = vbNullString 
  End If 
  If Len(Sender) > 0 Then 
 Sender = StrConv(Sender, vbUnicode) 
  Else 
 Sender = vbNullString 
  End If 
  If Len(Servername) > 0 Then 
 Servername = StrConv(Servername, vbUnicode) 
  Else 
 Servername = vbNullString 
  End If 
  ' Gibt NetMessageBufferSend 0 zurück, war der Aufruf 
  ' erfolgreich. 
  Select Case NetMessageBufferSend(Servername, Recipient, _ 
  Sender, Message, _ 
  Len(Message)) 
 Case 0  ' Der Aufruf war erfolgreich 
   Send = True 
 ' Alle anderen Rückgaben signalisieren Fehler: 
 Case ERROR_ACCESS_DENIED 
   MsgBox "Zugriff verweigert.", _ 
 vbCritical, "Send-Funktion" 
 Case ERROR_INVALID_PARAMETER 
   MsgBox "Ein übergebener Parameter ist ungültig.", _ 
 vbCritical, "Send-Funktion" 
 Case ERROR_NOT_SUPPORTED 
   MsgBox "Netzwerkanfrage wird nicht unterstützt.", _ 
 vbCritical, "Send-Funktion" 
 Case NERR_NAMENOTFOUND 
   MsgBox "Benutzername wurde nicht gefunden.", _ 
 vbCritical, "Send-Funktion" 
 Case NERR_NETWORKERROR 
   MsgBox "Allgemeiner Netzwerkfehler.", _ 
 vbCritical, "Send-Funktion" 
 Case Else 
   MsgBox "Unbekannter Fehler.", _ 
 vbCritical, "Send-Funktion" 
  End Select 
End Function 
Private Function IsWinNT() As Boolean 
' Gibt zurück, ob es sich um ein Betriebssystem der 
' Windows NT-Familie handelt (Windows NT, Windows 2000, 
' Windows XP, Windows Server 2003) oder nicht. 
Dim OSV As OSVERSIONINFO 
  OSV.OSVSize = Len(OSV) 
  If GetVersionEx(OSV) <> 0 Then 
 IsWinNT = (OSV.PlatformID = VER_PLATFORM_WIN32_NT) 
  End If 
End Function 
' ------------------------------------------------------