Netzwerklaufwerke verbinden mit VB6

Veröffentlicht: 19. Mai 2004 | Aktualisiert: 29. Nov 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.

Auf dieser Seite

 Aus der Visual Basic Newsgroup microsoft.public.de.vb:
 Vorüberlegung: Netzwerklaufwerk wirklich benötigt?
 Netzwerklaufwerke verbinden und trennen
 Verbindungen mit Benutzername und Kennwort

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

Wie kann ich programmatisch (ohne Aktion des Benutzers) ein freigegebenes Verzeichnis im Netzwerk als Netzwerklaufwerk verbinden? Ein Passwort möchte ich als Parameter mit übergeben können, falls das im Netzwerk freigegebene Verzeichnis kennwortgeschützt sein sollte.

 

Vorüberlegung: Netzwerklaufwerk wirklich benötigt?

Bedenken Sie: Beim Zugriff auf ein freigegebenes Verzeichnis im Netzwerk muss das Verzeichnis nicht unbedingt lokal als Netzwerklaufwerk eingerichtet werden (also einen virtuellen Laufwerksbuchstaben erhalten). Oft reicht es auch schon, auf Ressourcen im Netzwerk mithilfe der UNC-Notation zuzugreifen. Hierfür wird der Servername zwischen zwei Backslash-Zeichen und den entfernten Verzeichnispfad gesetzt, z.B. "\\SERVER\FREIGABENAME\DATEN\". Visual Basic selber hat bezüglich der Dateifunktionen keine Einschränkungen, was diese Notation angeht, und auch die meisten API-Funktionen sollten mit dieser Notation kooperieren.

Trotzdem kann es auch notwendig sein, ein freigegebenes Verzeichnis als Laufwerk einzubinden: Denken Sie nur etwa an Anwendungs- oder Hilfsprogramme, die bei selbst erzeugten Dateiauswahldialogen Datenquellen wie ein Netzwerk gar nicht erst berücksichtigen. Möchten Sie mit solchen Programmen im Netzwerk arbeiten, bleibt nur noch der Weg, durch das Erzeugen eines Netzwerklaufwerks vorzutäuschen, ein freigegebenes Verzeichnis im Netzwerk sei ein lokales Laufwerk. Windows kümmert sich um den Rest.

Erstellen Sie selber Anwendungen, die später zu solchen Problemen führen könnten, sollten Sie immer die Windows-Standarddialoge für Dateioperationen verwenden. Auf diesem Weg kann der Benutzer auch auf direktem Wege Netzwerkfreigaben auswählen und einsetzen.

 

Netzwerklaufwerke verbinden und trennen

Benötigen Sie wirklich ein virtuelles Laufwerk, das auf ein freigegebenes Verzeichnis im Netzwerk "gemappt" wird, können Sie (wie so oft, wenn die Grenzen von Visual Basic selbst erreicht sind) das Windows API nutzen.

Tipp: Dabei sollten Sie sich jedoch immer einer kleinen Besonderheit bewusst sein: Die möglichen Ursachen für Fehler sind bei dieser Art des Dateizugriffs vielfältiger. So kann die Netzwerkfreigabe für dass Verzeichnis vom Eigentümer jederzeit wieder aufgehoben werden. Auch das Netzwerk selber könnte schwächeln, Zugriffsrechte auf das Netzwerklaufwerk können eingeschränkter als angenommen sein, … Fazit: Verwenden Sie Netzwerklaufwerke, sollten Sie jeden Schritt, in dem auf diese Ressourcen zugegriffen werden soll, durch eine detaillierte Fehlerbehandlung schützen.

Zuständig für die gesuchte Funktionalität ist die Win32-API Funktion WNetAddConnection, hier gleich mit ihrem Gegenstück WNetCancelConnection aufgeführt:

' WNetAddConnection stellt Netzlaufwerksverbindungen her 
Private Declare Function WNetAddConnection _ 
  Lib "mpr.dll" Alias "WNetAddConnectionA" ( _ 
  ByVal NetworkPath As String, _ 
  ByVal Password As String, _ 
  ByVal LocalName As String _ 
  ) As Long 
   
' WNetCancelConnection trennt bestehende Netzlaufwerke 
Private Declare Function WNetCancelConnection _ 
  Lib "mpr.dll" Alias "WNetCancelConnectionA" ( _ 
  ByVal LocalName As String, _ 
  ByVal bForce As Long _ 
  ) As Long

Die Parameter der Funktionen sind schnell erklärt: WNetAddConnection erwartet als NetworkPath den Netzwerkpfad zum freigegebenen Netzwerkverzeichnis. Dieser besteht aus dem UNC-Freigabenamen, der Rechnernamen und Freigabepfad enthält (etwa "\\Server\Freigabe"). Wird für den Zugriff auf das Netzwerklauf ein Kennwort benötigt, so übergeben Sie dieses im Parameter Password. Bei ungesichert freigegebenen Verzeichnissen übergeben Sie hier einfach vbNullString oder einen leeren String. Letztlich definieren Sie in LocalName, welchen lokalen Laufwerksbuchstaben Sie für dieses Netzwerklaufwerk vorgesehen haben. Vergessen Sie dabei den nachfolgenden Doppelpunkt zur Kennzeichnung eines Laufwerksbuchstabens nicht.

Noch einfacher lässt sich WNetCancelConnection einsetzen, um die Netzwerkverbindung für ein Netzwerklaufwerk aufzuheben und das zugehörige virtuelle lokale Laufwerk zu entfernen: In LocalName übergeben Sie wie oben den lokalen Laufwerksbuchstaben inklusive des Doppelpunkts. In bForce geben Sie dann nur noch an, ob das Laufwerk unter Zwang getrennt werden soll - also auch dann, wenn sich diesem Ansinnen irgendein mögliches Problem in den Weg stellt. Um diesen Zwang auszuüben setzen Sie den Parameter auf 1, sonst auf 0.

So einfach lässt sich also ein freigegebenes Verzeichnis als Netzwerklaufwerk herstellen:

' Konstantenwert für Fehlerfreiheit: 
Private Const NO_ERROR As Long = 0& 
   
' WNetAddConnection stellt Netzlaufwerksverbindungen her 
Private Declare Function WNetAddConnection _ 
  Lib "mpr.dll" Alias "WNetAddConnectionA" ( _ 
  ByVal NetworkPath As String, _ 
  ByVal Password As String, _ 
  ByVal LocalName As String _ 
  ) As Long 
   
' WNetCancelConnection trennt bestehende Netzlaufwerke 
Private Declare Function WNetCancelConnection _ 
  Lib "mpr.dll" Alias "WNetCancelConnectionA" ( _ 
  ByVal LocalName As String, _ 
  ByVal bForce As Long _ 
  ) As Long 
   
   
Public Function MapNetworkDrive(ByVal UNCPath As String, _ 
                                ByVal LocalPath As String, _ 
                                Optional ByVal Password As String _ 
                                ) As Boolean 
' Versucht, ein freigegebenes Verzeichnis im Netzwerk (UNCPath) 
' als lokales Netzwerklaufwerk (LocalPath) einzubinden. Im Fall 
' kennwortgeschützter freigegebener Verzeichnisse im Netzwerk 
' kann im Parameter Password ein Kennwort übergeben werden. 
Dim lResult As Long 
   
  ' LocalPath muss ein Buchstabe plus Doppelpunkt sein: 
  LocalPath = Left$(LocalPath, 1) & ":" 
   
  ' Pfad als Netzwerklaufwerk einzubinden versuchen 
  lResult = WNetAddConnection(UNCPath, Password, LocalPath) 
   
  ' Prüfung auf Erfolg anhand des Rückgabewerts: 
  If lResult = NO_ERROR Then 
   
    ' Aktion erfolgreich 
    MapNetworkDrive = True 
   
  Else 
   
    ' Ausführung war nicht möglich. Den genauen Fehlergrund können 
    ' Sie als Fehlernummer dem Wert von Err.LastDllError entnehmen. 
    ' Diesen können Sie natürlichsprachlich auswerten wie im 
    ' folgenden MSDN Quickie gezeigt wird: 
    ' "API Fehlermeldungen im Klartext" 
   
  End If 
   
End Function 
   
   
Private Function UnmapNetworkDrive(ByVal Name As String, _ 
                                    Optional ByVal Force As Boolean = True _ 
                                    ) As Boolean 
' Versucht, ein Netzwerklaufwerk abzumelden. Wird Force zu True 
' gesetzt, werden mögliche Probleme ignoriert (ggf. "auf Kosten" 
' eines Netzwerkteilnehmers). 
Dim lResult As Long 
   
  ' Netzwerkverbindung aufheben: 
  lResult = WNetCancelConnection(Name, CLng(Force)) 
   
  ' Erfolgsauswertung: 
  If lResult = NO_ERROR Then 
   
    ' Aufruf verlief erfolgreich 
    UnmapNetworkDrive = True 
   
  Else 
   
    ' Ausführung war nicht möglich. Den Rückgabewert können Sie 
    ' auswerten wie im folgenden MSDN Quickie gezeigt wird: 
    ' "API Fehlermeldungen im Klartext" 
   
  End If 
   
End Function 
   
   
' ANWENDUNGSBEISPIEL: 
' ------------------- 
Private Sub Command1_Click() 
Dim UNCPath As String     ' UNC-Pfad im Netzwerk 
Dim LocalDrive As String  ' Lokaler Laufwerksbuchstabe 
   
  ' Parameter definieren 
  UNCPath = "\\MYSERVER\Public" 
  LocalDrive = "P" 
   
  ' Netzwerklaufwerk einzubinden versuchen 
  If MapNetworkDrive(UNCPath, LocalDrive) Then 
   
    ' MapNetworkDrive war erfolgreich. 
    ' Erfolg an den Anwender melden 
    MsgBox "Der Pfad " & _ 
            vbNewLine & UNCPath & vbNewLine & _ 
            "wurde erfolgreich als Laufwerk " & LocalDrive & _ 
            " eingebunden.", _ 
            vbCritical, _ 
            "Netzwerklaufwerk einbinden" 
   
  Else  ' MapNetworkDrive war nicht erfolgreich. 
   
    ' Fehlermeldung (hier exemplarisch nur mit Fehlernummer) 
    MsgBox "Beim Einbinden des Pfades " & _ 
            vbNewLine & UNCPath & vbNewLine & _ 
            "trat der Fehler Nr. " & _ 
            CStr(Err.LastDllError) & " auf.", _ 
            vbCritical, _ 
            "Netzwerklaufwerk einbinden" 
   
  End If 
   
End Sub

 

Verbindungen mit Benutzername und Kennwort

Die oben vorgestellte Methode, Netzwerkverbindungen herzustellen, hat ihre Vorzüge: Sie ist sehr einfach und übersichtlich. Allerdings weist sie auch ein deutliches Manko auf: Aus historischen Gründen berücksichtigt sie nicht, dass für den Zugriff auf ein Verzeichnis möglicherweise nicht nur ein Kennwort, sondern eventuell auch ein Benutzername angegeben werden muss, der sich vom Namen des angemeldeten Benutzers unterscheiden kann.

Die modernere Variante der aufgezeigten Funktionen findet sich daher in ihren Nachfolgern, die sich namentlich schlicht durch eine angehängte "2" unterscheiden: Sie heißen entsprechend WNetAddConnection2 und WNetCancelConnection2. Sie benötigen für die Nutzung ihrer umfangreicheren Möglichkeiten allerdings auch ein paar zusätzliche Deklarationen:

' Konstantenwert für Fehlerfreiheit: 
Private Const NO_ERROR As Long = 0& 
   
' Flags-Wert: Verbindung bei Neustart wieder herstellen 
Private Const CONNECT_UPDATE_PROFILE  As Long = &H1 
   
' Mögliche Konstante für NETRESOURCE 
Private Const RESOURCETYPE_DISK As Long = &H1 
Private Const RESOURCETYPE_PRINT As Long = &H2 
Private Const RESOURCETYPE_ANY As Long = &H0 
Private Const RESOURCE_CONNECTED As Long = &H1 
Private Const RESOURCE_REMEMBERED As Long = &H3 
Private Const RESOURCE_GLOBALNET As Long = &H2 
Private Const RESOURCEDISPLAYTYPE_DOMAIN  As Long = &H1 
Private Const RESOURCEDISPLAYTYPE_GENERIC  As Long = &H0 
Private Const RESOURCEDISPLAYTYPE_SERVER  As Long = &H2 
Private Const RESOURCEDISPLAYTYPE_SHARE  As Long = &H3 
Private Const RESOURCEUSAGE_CONNECTABLE  As Long = &H1 
Private Const RESOURCEUSAGE_CONTAINER  As Long = &H2 
   
' Fehlerkonstante für WNetAddConnection2: 
' Zugriff verweigert: 
Private Const ERROR_ACCESS_DENIED  As Long = 5& 
' Der lokale Gerätename wird bereits verwendet: 
Private Const ERROR_ALREADY_ASSIGNED  As Long = 85& 
' Der Netzwerkpfad wurde nicht gefunden: 
Private Const ERROR_BAD_NETPATH As Long = 53& 
' Der Typ der Netzwerkressource ist falsch: 
Private Const ERROR_BAD_DEV_TYPE  As Long = 66& 
' Der angegebene Gerätename ist unzulässig: 
Private Const ERROR_BAD_DEVICE As Long = 1200& 
' Der Netzwerkname wurde nicht gefunden 
Private Const ERROR_BAD_NET_NAME As Long = 67& 
' Das Profil mit den Netzwerkverbindungen ist fehlerhaft: 
Private Const ERROR_BAD_PROFILE As Long = 1206& 
' Der angegebene Name für einen Netzwerkdienstanbieter 
' ist unzulässig: 
Private Const ERROR_BAD_PROVIDER As Long = 1204& 
' Die angeforderte Ressource wird bereits verwendet: 
Private Const ERROR_BUSY As Long = 170& 
' Der Vorgang wurde durch den Benutzer abgebrochen: 
Private Const ERROR_CANCELLED As Long = 1223& 
' Das Profil mit den Netzwerkverbindungen konnte 
' nicht geöffnet werden: 
Private Const ERROR_CANNOT_OPEN_PROFILE As Long = 1205& 
' Es wurde versucht, eine bereits gespeicherte 
' Verbindung zu einem Gerät zu speichern: 
Private Const ERROR_DEVICE_ALREADY_REMEMBERED As Long = 1202& 
' Ein erweiterter Fehler ist aufgetreten: 
Private Const ERROR_EXTENDED_ERROR As Long = 1208& 
' Das angegebene Netzwerkkennwort ist falsch: 
Private Const ERROR_INVALID_PASSWORD As Long = 86& 
' Der angegebene Netzwerkpfad wurde von keinem 
' Netzwerkdienstanbieter angenommen: 
Private Const ERROR_NO_NET_OR_BAD_PATH As Long = 1203& 
     
' Netzwerkressourcentyp NETRESOURCE 
Private Type NETRESOURCE 
  dwScope As Long 
  dwType As Long 
  dwDisplayType As Long 
  dwUsage As Long 
  lpLocalName As String 
  lpRemoteName As String 
  lpComment As String 
  lpProvider As String 
End Type 
   
' WNetAddConnection2 stellt Netzlaufwerksverbindungen her 
Private Declare Function WNetAddConnection2 _ 
  Lib "mpr.dll" Alias "WNetAddConnection2A" ( _ 
  ByRef lpNetResource As NETRESOURCE, _ 
  ByVal Password As String, _ 
  ByVal Username As String, _ 
  ByVal Flags As Long _ 
  ) As Long 
   
' WNetCancelConnection2 trennt bestehende Netzlaufwerke 
Private Declare Function WNetCancelConnection2 _ 
  Lib "mpr.dll" Alias "WNetCancelConnection2A" ( _ 
  ByVal Name As String, _ 
  ByVal Flags As Long, _ 
  ByVal fForce As Long _ 
  ) As Long

Die Verwendung der Funktionen unterscheidet sich ein wenig von der der älteren Funktionsvarianten: Grundlage der Informationen über das freigegebene Verzeichnis und den lokalen Laufwerksbuchstaben ist eine NETRESOURCE-Struktur. Zunächst weisen Sie dem Parameter dwType die Konstante RESOURCETYPE_DISK zu, um zu dokumentieren, dass Sie ein freigegebenes Verzeichnis als Laufwerk einrichten möchten. Ihren Parameter lpLocalName versorgen Sie mit dem Laufwerksbuchstaben, lpRemoteName erhält den UNC-Pfad ins Netzwerk. Weitere Parameter benötigen Sie dafür nicht.

Diese Struktur übergeben Sie der Funktion WNetAddConnection2, der Sie außerdem Benutzernamen und Kennwort übergeben können (Parameter Password und Username). Verwenden Sie ein Password, aber keinen Benutzernamen, wird der Name des aktuell angemeldeten Benutzers verwendet.

Im letzten Parameter der Funktion, Flags, können Sie angeben, ob die Netzwerkverbindung nach einem Systemneustart wieder hergestellt werden soll (sofern sie nicht vorher beendet wurde). Möchten Sie das erreichen, übergeben Sie hier die Konstante CONNECT_UPDATE_PROFILE.

Im Erfolgsfall liefert die Funktion 0 (oder symbolisch: NO_ERROR) zurück. Jeder andere Rückgabewert macht auf ein Problem aufmerksam. In der obigen Deklaration finden Sie alle möglichen Fehlerwerte in den ERROR_*-Konstanten aufgeführt (auch hier können Sie den MSDN Quickie "API Fehlermeldungen im Klartext" zu Rate ziehen, um aus Fehlernummern Fehlertexte zu erzeugen).

Auch das Trennen einer bestehenden Netzwerkverbindung gestaltet sich mit WNetCancelConnection2 anders als mit der Vorgängerversion: Zunächst geben Sie im Parameter Name den lokalen Laufwerksbuchstaben an. Im Parameter Flags können Sie auch hier wieder die Konstante CONNECT_UPDATE_PROFILE angeben. Sie ist nur dann sinnvoll, wenn die Netzwerkverbindung mit der gleichen Konstante hergestellt wurde: In diesem Fall wird nach einem Systemneustart nicht erneut versucht, die Verbindung herzustellen.

Den Parameter Force kennen Sie bereits von WNetCancelConnection: Er sorgt dafür, möglicherweise auftretende Hinderungsgründe (etwa geöffnete Dateien, verbundene Benutzer etc.) zu ignorieren.

Die Vorgehensweise sei anhand einer Funktion aufgezeigt, die als MapNetworkDrive2 zusätzlich optional einen Benutzernamen und eine Option zur Wiederherstellung der Verbindung nach Systemneustart entgegennimmt. Natürlich finden Sie auch hier wieder ein gegensätzliches Äquivalent mit UnmapNetworkDrive2.

Public Function MapNetworkDrive2(ByVal UNCPath As String, _ 
                                 ByVal LocalPath As String, _ 
                                 Optional ByVal UserName As String, _ 
                                 Optional ByVal Password As String, _ 
                                 Optional ByVal Persistent As Boolean _ 
                                 ) As Boolean 
' Versucht, ein freigegebenes Verzeichnis im Netzwerk (UNCPath) 
' als lokales Netzwerklaufwerk (LocalPath) einzubinden. Im Fall 
' kennwortgeschützter freigegebener Verzeichnisse im Netzwerk 
' kann im Parameter Password ein Kennwort übergeben werden. 
' Wird in Username kein Benutzername übergeben, wird der Name 
' des angemeldeten Benutzers verwendet. Wird der Parameter 
' Persistent zu True gesetzt so wird nach einem Systemneu- 
' start versucht, die Verbindung erneut herzustellen. 
Dim NetR As NETRESOURCE 
Dim lResult As Long 
Dim lPersist As Long 
   
  ' LocalPath muss ein Buchstabe plus Doppelpunkt sein: 
  LocalPath = Left$(LocalPath, 1) & ":" 
   
  ' NETRESOURCE-Struktur belegen: 
  With NetR 
    .dwType = RESOURCETYPE_DISK 
    .lpRemoteName = UNCPath 
    .lpLocalName = LocalPath 
  End With 
   
  ' Persistenz-Parameter berücksichtigen: 
  If Persistent Then 
    lPersist = CONNECT_UPDATE_PROFILE 
  End If 
   
  ' Pfad als Netzwerklaufwerk einzubinden versuchen 
  lResult = WNetAddConnection2(NetR, Password, UserName, lPersist) 
   
  ' Prüfung auf Erfolg anhand des Rückgabewerts: 
  If lResult = NO_ERROR Then 
   
    ' Aktion erfolgreich 
    MapNetworkDrive2 = True 
   
  Else 
   
    ' Ausführung war nicht möglich. Den Rückgabewert können Sie 
    ' auswerten wie im folgenden MSDN Quickie gezeigt wird: 
    ' "API Fehlermeldungen im Klartext" 
   
  End If 
   
End Function 
   
   
Private Function UnmapNetworkDrive2(ByVal Name As String, _ 
                                    Optional ByVal Force As Boolean = True, _ 
                                    Optional ByVal Persistent As Boolean _ 
                                    ) As Boolean 
' Versucht, ein Netzwerklaufwerk abzumelden. Name ist dabei der 
' lokal vergebene Laufwerksbuchstabe. Wird Force zu True gesetzt, 
' werden mögliche Probleme ignoriert (ggf. "auf Kosten" eines 
' Netzwerkteilnehmers). Wird Persistent zu True gesetzt, wird 
' eine beim Anmelden vorgesehene Verbindungswiederherstellung 
' nach Neustart deaktiviert. 
Dim lPersist As Long 
Dim lResult As Long 
   
  ' Persistenz-Parameter berücksichtigen: 
  If Persistent Then 
    lPersist = CONNECT_UPDATE_PROFILE 
  End If 
   
  ' Netzwerkverbindung aufheben: 
  lResult = WNetCancelConnection2(Name, Persistent, CLng(Force)) 
   
  ' Erfolgsauswertung: 
  If lResult = NO_ERROR Then 
   
    ' Aufruf verlief erfolgreich 
    UnmapNetworkDrive2 = True 
   
  Else 
   
    ' Ausführung war nicht möglich. Den Rückgabewert können Sie 
    ' auswerten wie im folgenden MSDN Quickie gezeigt wird: 
    ' "API Fehlermeldungen im Klartext" 
   
  End If 
   
End Function 
   
   
' ANWENDUNGSBEISPIEL: 
' ------------------- 
Private Sub Command1_Click() 
Dim UNCPath As String     ' UNC-Pfad im Netzwerk 
Dim LocalDrive As String  ' Lokaler Laufwerksbuchstabe 
   
  ' Parameter definieren 
  UNCPath = "\\MYSERVER\Public" 
  LocalDrive = "Q" 
   
  ' Netzwerklaufwerk einzubinden versuchen 
  If MapNetworkDrive2(UNCPath, LocalDrive) Then 
   
    ' MapNetworkDrive war erfolgreich. 
    ' Erfolg an den Anwender melden 
    MsgBox "Der Pfad " & _ 
            vbNewLine & UNCPath & vbNewLine & _ 
            "wurde erfolgreich als Laufwerk " & LocalDrive & _ 
            " eingebunden.", _ 
            vbCritical, _ 
            "Netzwerklaufwerk einbinden" 
   
  Else  ' MapNetworkDrive war nicht erfolgreich. 
   
    ' Fehlermeldung (hier exemplarisch nur mit Fehlernummer) 
    MsgBox "Beim Einbinden des Pfades " & _ 
            vbNewLine & UNCPath & vbNewLine & _ 
            "trat der Fehler Nr. " & _ 
            CStr(Err.LastDllError) & " auf.", _ 
            vbCritical, _ 
            "Netzwerklaufwerk einbinden" 
   
  End If 
   
End Sub

Abschließend noch ein Tipp zum Thema: Wenn Sie wissen möchten, welche der lokalen Laufwerksbuchstaben Netzwerklaufwerke repräsentieren, hilft der MSDN Quickie "Vorhandene Laufwerke und Laufwerkstypen ermitteln".