DevTips.NET
Maak of verbreek een verbinding met een netwerkstation

Maak of verbreek een verbinding met een netwerkstation

Het kan soms heel handig zijn om een share te benaderen als netwerkstation. U kunt hierbij bijvoorbeeld denken aan het consolideren van databases die op verschillende lokale computers staan. Helaas zijn er voor het maken van deze zogenaamde schijfkoppelingen (drivemappings) geen standaard .NET-klassen beschikbaar. In dit geval moeten we dus terugvallen op de API’s die in Windows DLL’s beschikbaar zijn.

We beginnen met het declareren van de functies, eventuele structuren en mogelijke foutcodes. Om de gewenste functionaliteit bij elkaar te houden, wordt alles ondergebracht in de klasse Netwerk. using System.Runtime.InteropServices;

 

public class Netwerk {
// Importeer de functies uit de Windows API
[ DllImport( "mpr.dll", SetLastError = true ) ]
static extern int WNetAddConnection2( ref NETRESOURCE lpNetResource, 
string lpPassword, string lpUserName, uint dwFlags );




[ DllImport( "mpr.dll", SetLastError = true ) ]
static extern int WNetCancelConnection2( string lpName, uint dwFlags, bool fForce );




// Structuur voor WNet*-functies
struct NETRESOURCE {
public int intScope;
public int intType;
public int inyDisplayType;
public int inyUsage;
public string strLocalname;
public string strRemotename;
public string strComment;
public string strProvider;
}




// Constanten Resource Type
public const short RESOURCETYPE_DISK = 0x1;




// Constanten Error codes
public const short ERROR_SUCCESS = 0;
public const short ERROR_ACCESS_DENIED = 5;
public const short ERROR_OUTOFMEMORY = 14;
public const short ERROR_BAD_NETPATH = 53;
public const short ERROR_BAD_NET_NAME = 67;
public const short ERROR_TOO_MANY_SESS = 69;
public const short ERROR_ALREADY_ASSIGNED = 85;
public const short ERROR_INVALID_PASSWORD = 86;
public const short ERROR_BUSY = 170;
public const short ERROR_ALREADY_EXISTS = 183;
public const short ERROR_CONNECTION_UNAVAIL = 1201;
public const short ERROR_DEVICE_ALREADY_REMEMBERED = 1202;
public const short ERROR_NO_NET_OR_BAD_PATH = 1203;
public const short ERROR_NO_NETWORK = 1222;
public const short ERROR_INVALID_PASSWORDNAME = 1216;
public const short ERROR_INTERNAL_ERROR = 1359;
public const short ERROR_BAD_USERNAME = 2202;
public const short ERROR_DEVICE_IN_USE = 2404;

We gaan ons nu concentreren op het toepassen van de API’s. Voor het maken van een netwerkstation hebben we een aantal variabelen nodig. Ten eerste moet het netwerkstation een vrije stationsletter krijgen. Daarnaast staat de gedeelde map op een bepaald werkstation of server en heeft die share zelf natuurlijk ook een naam. U kunt een gedeelde map alleen benaderen indien u hiervoor voldoende rechten heeft.

Dat is de reden waarom u in de methode MaakNetwerkStation() ook een tweetal argumenten kunt meegeven voor de gebruikersnaam en het wachtwoord. Deze functie retourneert een true indien het netwerkstation aangemaakt is. Indien de methode een false teruggeeft, is de actie blijkbaar niet gelukt. Om de gebruiker op de hoogte te stellen van de reden van het mislukken, kunt u als laatste argument een string ‘ref’ meegeven. Na aanroep van deze functie bevat deze variabele de foutomschrijving.

public bool MaakNetwerkStation( string stationsLetter, string serverNaam, 
string shareNaam, string gebruikersNaam, 
string wachtwoord, ref string status ) {
int resultaat = 0;
NETRESOURCE netResource = new NETRESOURCE();




// Stationsletter moet eindigen op ':' --> anders toevoegen
if ( stationsLetter.EndsWith( ":" ) == false ) {
stationsLetter += ":";
}




{
netResource.intType = RESOURCETYPE_DISK;
netResource.strLocalname = stationsLetter;
netResource.strRemotename = "\\\\" + serverNaam + "\\" + shareNaam;
netResource.strProvider = "";
}




// Maak een verbinding met de opgegeven argumenten
resultaat = WNetAddConnection2( ref netResource, wachtwoord, gebruikersNaam, 0 );




// Bepaal status: True gelukt, False niet --> bekijk strStatus
return BepaalStatus( resultaat, ref status );
}

In deze functie wordt eerst getest of de opgegeven stationsletter wel eindigt op een dubbele punt. Wanneer dit niet het geval is, dan wordt dat karakter alsnog toegevoegd. De functie WNetAddConnection2() verwacht als eerste argument een variabele van het type NETRESOURCE. Deze structuur bevat de variabelen zoals de gewenste stationsletter en de locatie en de naam van de netwerkmap. Daarnaast bevat het nog een aantal andere velden waarmee u het gedrag van de functie nog wat meer preciezer kunt beïnvloeden. Op de website msdn.microsoft.com staan deze structuur en de andere velden uitgebreid beschreven. Het tweede en derde argument van deze functie bestaan uit de gebruikersnaam en het wachtwoord.

 

De functie retourneert een van de mogelijke foutcodes. Dit is een van de constanten die beginnen met ERROR_. Indien de returnwaarde ERROR_SUCCESS is, dan is een share aangemaakt. Elke andere returncode duidt op een fout. In de functie BepaalStatus() wordt deze waarde omgezet in een voor de gebruiker begrijpelijke omschrijving. Tevens bepaalt de returnwaarde van deze functie of het verbinden of verbreken gelukt is.

private bool BepaalStatus( int resultaat, ref string status )
{
if ( resultaat == ERROR_SUCCESS ) {
status = "";
return true;
}
else {
// Bepaal status
switch ( resultaat ) {
case ERROR_OUTOFMEMORY:
status = "Out of memory.";
break;
case ERROR_BAD_NET_NAME:
status = "No valid net name.";
break;
case ERROR_INVALID_PASSWORD:
status = "Invalid Password";
break;
case ERROR_ACCESS_DENIED:
status = "Access Denied.";
break;
case ERROR_ALREADY_EXISTS:
status = "Already connected.";
break;
case ERROR_CONNECTION_UNAVAIL:
status = "Unable to connect to share.";
break;
case ERROR_ALREADY_ASSIGNED:
status = "The drive is already assigned.";
break;
case ERROR_BAD_USERNAME:
status = "No valid Username.";
break;
case ERROR_INTERNAL_ERROR:
status = "Internal error.";
break;
case ERROR_BUSY:
status = "Router or server still busy.";
break;
case ERROR_DEVICE_IN_USE:
status = "Device in use";
break;
case ERROR_BAD_NETPATH:
status = "Cannot find the requested share";
break;
case ERROR_DEVICE_ALREADY_REMEMBERED:
status = "Drive already reconnected";
break;
case ERROR_NO_NET_OR_BAD_PATH:
status = "Cannot find the path or the network";
break;
case ERROR_NO_NETWORK:
status = "No network";
break;
case ERROR_TOO_MANY_SESS:
status = "No more sessions available try later!";
break;
default:
status = "Unknown Error: " + resultaat.ToString();
break;
}
return false;
}
}

We hebben nu alle benodigde code geschreven. Wat rest is het aanroepen van de methode MaakShare(). In dit voorbeeld gaan we ervan uit dat er een vijftal tekstvakken is waarin de gebruiker de gewenste stationsletter, de naam van de server, de naam van de share, de gebruikersnaam en het wachtwoord kan invoeren.

private void buttonMaakShare_Click( object sender, EventArgs e )
{
// De methoden voor het maken van een share zitten in de klasse Netwerk
Netwerk netwerk = new Netwerk();
string status = "";




// Probeer het netwerkstation aan te maken
if ( netwerk.MaakNetwerkStation( textBoxStationsLetter.Text, textBoxServerNaam.Text,
textBoxShareNaam.Text, textBoxGebruikersNaam.Text,
textBoxWachtwoord.Text, ref status ) == false ) {
// Niet gelukt
MessageBox.Show( "Share is niet gemaakt: " + status );
}
else {
// Wel gelukt
MessageBox.Show( "Share is gemaakt." );
}
}




Natuurlijk is het ook mogelijk om de koppeling met een bestaand netwerkstation te verbreken. Dit kunt u doen, zoals u in de methode VerbreekNetwerkStation()ziet, door gebruik te maken van WNetCancelConnection2(). De methode VerbreekNetwerkStation() verwacht twee argumenten. Als eerste geeft u de letter op van het station dat u wilt verbreken. Als tweede geeft u een argument mee waarin u, indien het verbreken van de verbinding mislukt is, nadere informatie afvangt over de aard van het probleem.

public bool VerbreekNetwerkStation( string stationsLetter, ref string status )
{
int resultaat = 0;




// Stationsletter moet eindigen op ':' --> anders toevoegen
if ( stationsLetter.EndsWith( ":" ) == false ) {
stationsLetter += ":";
}




// Verbreek de verbinding met de opgegeven stations
resultaat = WNetCancelConnection2( stationsLetter, 0, false );




// Bepaal status: True gelukt, False niet --> bekijk strStatus
return BepaalStatus( resultaat, ref status );
}

Om het verhaal helemaal rond te maken treft u hieronder ook de code aan die de methode VerbreekNetwerkStation() aanroept.

private void buttonVerbreekShare_Click( object sender, EventArgs e )
{
Netwerk netwerk = new Netwerk();
string status = "";




// Verbreek het netwerkstation
if ( netwerk.VerbreekNetwerkStation( textBoxStationsLetter.Text, ref status ) == 
false ) {
// Niet gelukt
MessageBox.Show( "Share niet verbroken: " + status );
}
else {
// Wel gelukt
MessageBox.Show( "Share is verbroken." );
}
}
comments powered by Disqus