using System;
using System.IO;
//==============================================================================================================
//
// cNetworkDrive - Map Network Drive API Class
// -----------------------------------------------
// Copyright (c)2006-2007 aejw.com
// http://www.aejw.com/
//
// Build: 0028 - March 2007
// Thanks To: "jsantos98", "FeLiZk" from CodeProject.com for there comments and help
// "MartinPreis" for reporting two bugs
// EULA: Creative Commons - Attribution-ShareAlike 3.0
// http://creativecommons.org/licenses/by-sa/3.0/
//
//==============================================================================================================
namespace MapDrives
{
public class NetworkDriveHelper
{
#region Public variables and properties
//---------------------------------------------------------------------------------------------------------------------------------------
private bool _saveCredentials = false;
private bool _persistent = false;
private bool _force = false;
private bool _promptForCredentials = false;
private bool _findNextFreeDrive = false;
private string _localDrive = null;
private string _shareName = "";
//---------------------------------------------------------------------------------------------------------------------------------------
// Option to save credentials on reconnection...
//---------------------------------------------------------------------------------------------------------------------------------------
public bool SaveCredentials
{
get
{
return _saveCredentials;
}
set
{
_saveCredentials = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Option to reconnect drive after log off / reboot...
//---------------------------------------------------------------------------------------------------------------------------------------
public bool Persistent
{
get
{
return _persistent;
}
set
{
_persistent = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Option to force connection if drive is already mapped...
// or force disconnection if network path is not responding...
//---------------------------------------------------------------------------------------------------------------------------------------
public bool Force
{
get
{
return _force;
}
set
{
_force = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Option to prompt for user credintals when mapping a drive
//---------------------------------------------------------------------------------------------------------------------------------------
public bool PromptForCredentials
{
get
{
return _promptForCredentials;
}
set
{
_promptForCredentials = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Option to auto select the 'LocalDrive' property to next free driver letter when mapping a network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public bool FindNextFreeDrive
{
get
{
return _findNextFreeDrive;
}
set
{
_findNextFreeDrive = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Drive to be used in mapping / unmapping (eg. 's:')
//---------------------------------------------------------------------------------------------------------------------------------------
public string LocalDrive
{
get
{
return _localDrive;
}
set
{
if (value == null || value.Length == 0)
{
_localDrive = null;
}
else
{
_localDrive = value.Substring(0, 1) + ":";
}
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Share address to map drive to. (eg. '\\Computer\C$')
//---------------------------------------------------------------------------------------------------------------------------------------
public string ShareName
{
get
{
return _shareName;
}
set
{
_shareName = value;
}
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Returns a string array of currently mapped network drives
//---------------------------------------------------------------------------------------------------------------------------------------
public string[] MappedDrives
{
get
{
System.Collections.ArrayList driveArray = new System.Collections.ArrayList();
foreach (string driveLetter in System.IO.Directory.GetLogicalDrives())
{
if (PathIsNetworkPath(driveLetter))
{
driveArray.Add(driveLetter);
}
}
return ((string[])driveArray.ToArray(typeof(string)));
}
}
#endregion
#region Public functions
//---------------------------------------------------------------------------------------------------------------------------------------
// Map network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void MapDrive()
{
mapDrive(null, null);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Map network drive (using supplied Username and Password)
//
// Username passed for permissions / credintals ('Username' may be passed as null, to map using only a password)
// Password passed for permissions / credintals
//---------------------------------------------------------------------------------------------------------------------------------------
public void MapDrive(string username, string password)
{
mapDrive(username, password);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Set common propertys, then map the network drive
//
// LocalDrive to use for connection
// Share name for the connection (eg. '\\Computer\Share')
// Option to force dis/connection
//---------------------------------------------------------------------------------------------------------------------------------------
public void MapDrive(string localDrive, string shareName, bool force)
{
_localDrive = localDrive;
_shareName = shareName;
_force = force;
mapDrive(null, null);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Set common propertys, then map the network drive
//
// Password passed for permissions / credintals
// Option to force dis/connection
//---------------------------------------------------------------------------------------------------------------------------------------
public void MapDrive(string localDrive, bool force)
{
_localDrive = localDrive;
_force = force;
mapDrive(null, null);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Unmap network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void UnMapDrive()
{
unMapDrive();
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Unmap network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void UnMapDrive(string localDrive)
{
_localDrive = localDrive;
unMapDrive();
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Unmap network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void UnMapDrive(string localDrive, bool force)
{
_localDrive = localDrive;
_force = force;
unMapDrive();
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Check / restore persistent network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void RestoreDrives()
{
restoreDrive(null);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Check / restore persistent network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public void RestoreDrive(string localDrive)
{
restoreDrive(localDrive);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Display windows dialog for mapping a network drive (using Desktop as parent form)
//---------------------------------------------------------------------------------------------------------------------------------------
public void ShowConnectDialog()
{
displayDialog(System.IntPtr.Zero, 1);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Display windows dialog for mapping a network drive
//
// Form used as a parent for the dialog
//---------------------------------------------------------------------------------------------------------------------------------------
public void ShowConnectDialog(System.IntPtr parentFormHandle)
{
displayDialog(parentFormHandle, 1);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Display windows dialog for disconnecting a network drive (using Desktop as parent form)
//---------------------------------------------------------------------------------------------------------------------------------------
public void ShowDisconnectDialog()
{
displayDialog(System.IntPtr.Zero, 2);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Display windows dialog for disconnecting a network drive
//
// Form used as a parent for the dialog
//---------------------------------------------------------------------------------------------------------------------------------------
public void ShowDisconnectDialog(System.IntPtr parentFormHandle)
{
displayDialog(parentFormHandle, 2);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Returns the share name of a connected network drive
//
// Drive name (eg. 'X:')
// Share name (eg. \\computer\share)
//---------------------------------------------------------------------------------------------------------------------------------------
public static string GetMappedShareName(string localDrive)
{
// collect and clean the passed LocalDrive param
if (localDrive == null || localDrive.Length == 0)
throw new System.Exception("Invalid 'localDrive' passed, 'localDrive' parameter cannot be 'empty'");
localDrive = localDrive.Substring(0, 1);
// call api to collect LocalDrive's share name
int i = 255;
byte[] bSharename = new byte[i];
int iCallStatus = WNetGetConnection(localDrive + ":", bSharename, ref i);
switch (iCallStatus)
{
case 1201:
throw new System.Exception("Cannot collect 'ShareName', Passed 'DriveName' is valid but currently not connected (API: ERROR_CONNECTION_UNAVAIL)");
case 1208:
throw new System.Exception("API function 'WNetGetConnection' failed (API: ERROR_EXTENDED_ERROR:" + iCallStatus.ToString() + ")");
case 1203:
case 1222:
throw new System.Exception("Cannot collect 'ShareName', No network connection found (API: ERROR_NO_NETWORK / ERROR_NO_NET_OR_BAD_PATH)");
case 2250:
throw new System.Exception("Invalid 'DriveName' passed, Drive is not a network drive (API: ERROR_NOT_CONNECTED)");
case 1200:
throw new System.Exception("Invalid / Malfored 'Drive Name' passed to 'GetShareName' function (API: ERROR_BAD_DEVICE)");
case 234:
throw new System.Exception("Invalid 'Buffer' length, buffer is too small (API: ERROR_MORE_DATA)");
}
// return collected share name
return System.Text.Encoding.GetEncoding(1252).GetString(bSharename, 0, i).TrimEnd((char)0);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Returns true if passed drive is a network drive
//
// Drive name (eg. 'X:')
// 'True' if the passed drive is a mapped network drive
//---------------------------------------------------------------------------------------------------------------------------------------
public static bool IsNetworkDrive(string localDrive)
{
// collect and clean the passed LocalDrive param
if (localDrive == null || localDrive.Trim().Length == 0)
throw new System.Exception("Invalid 'localDrive' passed, 'localDrive' parameter cannot be 'empty'");
localDrive = localDrive.Substring(0, 1);
// return status of drive type
return PathIsNetworkPath(localDrive + ":");
}
//---------------------------------------------------------------------------------------------------------------------------------------
// Returns the full path with the network drive letter replaced by the URL
//
// The Path that is to be modified(eg. 'h:\Documents')
// full path (eg. \\myserver\users\hans\Documents)
//---------------------------------------------------------------------------------------------------------------------------------------
public static string ReplaceDriveLetterWithURL(string ThePath)
{
string TheRoot = "";
string MappedDrive = "";
string TheFinalString = ThePath;
TheRoot = Path.GetPathRoot(ThePath);
if ((TheRoot.Length == 3) & (TheRoot.EndsWith(":\\")))
{
if (IsNetworkDrive(TheRoot))
{
MappedDrive =
GetMappedShareName(TheRoot) + "\\";
TheFinalString = ThePath.Replace(TheRoot, MappedDrive);
}
}
return TheFinalString;
}
public static double PathLatency(string ThePath)
{
DateTime Before;
DateTime After;
TimeSpan Elapsed;
bool Check;
double mylatency;
Before = DateTime.Now;
Check = Directory.Exists(ThePath);
After = DateTime.Now;
if (Check)
{
Elapsed = After - Before;
mylatency = Elapsed.TotalMilliseconds;
}
else
{
mylatency = -1;
}
return mylatency;
}
//---------------------------------------------------------------------------------------------------------------------------------------
#endregion
#region Private functions
//---------------------------------------------------------------------------------------------------------------------------------------
// map network drive
//---------------------------------------------------------------------------------------------------------------------------------------
private void mapDrive(string username, string password)
{
// if drive property is set to auto select, collect next free drive
if (_findNextFreeDrive)
{
_localDrive = nextFreeDrive();
if (_localDrive == null || _localDrive.Length == 0)
throw new System.Exception("Could not find valid free drive name");
}
// create struct data to pass to the api function
structNetResource stNetRes = new structNetResource();
stNetRes.Scope = 2;
stNetRes.Type = RESOURCETYPE_DISK;
stNetRes.DisplayType = 3;
stNetRes.Usage = 1;
stNetRes.RemoteName = _shareName;
stNetRes.LocalDrive = _localDrive;
// prepare flags for drive mapping options
int iFlags = 0;
if (_saveCredentials)
iFlags += CONNECT_CMD_SAVECRED;
if (_persistent)
iFlags += CONNECT_UPDATE_PROFILE;
if (_promptForCredentials)
iFlags += CONNECT_INTERACTIVE + CONNECT_PROMPT;
// prepare username / password params
if (username != null && username.Length == 0)
username = null;
if (password != null && password.Length == 0)
password = null;
// if force, unmap ready for new connection
if (_force)
{
try
{
this.unMapDrive();
}
catch
{
}
}
// call and return
int i = WNetAddConnection(ref stNetRes, password, username, iFlags);
if (i > 0)
throw new System.ComponentModel.Win32Exception(i);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// unmap network drive
//---------------------------------------------------------------------------------------------------------------------------------------
private void unMapDrive()
{
// prep vars and call unmap
int iFlags = 0;
int iRet = 0;
// if persistent, set flag
if (_persistent)
{
iFlags += CONNECT_UPDATE_PROFILE;
}
// if local drive is null, unmap with use connection
if (_localDrive == null)
{
// unmap use connection, passing the share name, as local drive
iRet = WNetCancelConnection(_shareName, iFlags, System.Convert.ToInt32(_force));
}
else
{
// unmap drive
iRet = WNetCancelConnection(_localDrive, iFlags, System.Convert.ToInt32(_force));
}
// if errors, throw exception
if (iRet > 0)
throw new System.ComponentModel.Win32Exception(iRet);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// check / restore a network drive
//---------------------------------------------------------------------------------------------------------------------------------------
private void restoreDrive(string driveName)
{
// call restore and return
int i = WNetRestoreConnection(0, driveName);
// if error returned, throw
if (i > 0)
throw new System.ComponentModel.Win32Exception(i);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// display windows dialog
//---------------------------------------------------------------------------------------------------------------------------------------
private void displayDialog(System.IntPtr wndHandle, int dialogToShow)
{
// prep variables
int i = -1;
int iHandle = 0;
// get parent handle
if (wndHandle != System.IntPtr.Zero)
iHandle = wndHandle.ToInt32();
// choose dialog to show bassed on
if (dialogToShow == 1)
i = WNetConnectionDialog(iHandle, RESOURCETYPE_DISK);
else if (dialogToShow == 2)
i = WNetDisconnectDialog(iHandle, RESOURCETYPE_DISK);
// if error returned, throw
if (i > 0)
throw new System.ComponentModel.Win32Exception(i);
}
//---------------------------------------------------------------------------------------------------------------------------------------
// returns the next viable drive name to use for mapping
//---------------------------------------------------------------------------------------------------------------------------------------
private string nextFreeDrive()
{
// loop from c to z and check that drive is free
string retValue = null;
for (int i = 67; i <= 90; i++)
{
if (GetDriveType(((char)i).ToString() + ":") == 1)
{
retValue = ((char)i).ToString() + ":";
break;
}
}
// return selected drive
return retValue;
}
//---------------------------------------------------------------------------------------------------------------------------------------
#endregion
#region API functions / calls
//---------------------------------------------------------------------------------------------------------------------------------------
[System.Runtime.InteropServices.DllImport("mpr.dll", EntryPoint = "WNetAddConnection2A", CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
private static extern int WNetAddConnection(ref structNetResource netResStruct, string password, string username, int flags);
[System.Runtime.InteropServices.DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2A", CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
private static extern int WNetCancelConnection(string name, int flags, int force);
[System.Runtime.InteropServices.DllImport("mpr.dll", EntryPoint = "WNetConnectionDialog", SetLastError = true)]
private static extern int WNetConnectionDialog(int hWnd, int type);
[System.Runtime.InteropServices.DllImport("mpr.dll", EntryPoint = "WNetDisconnectDialog", SetLastError = true)]
private static extern int WNetDisconnectDialog(int hWnd, int type);
[System.Runtime.InteropServices.DllImport("mpr.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true)]
private static extern int WNetRestoreConnection(int hWnd, string localDrive);
[System.Runtime.InteropServices.DllImport("mpr.dll", EntryPoint = "WNetGetConnection", SetLastError = true)]
private static extern int WNetGetConnection(string localDrive, byte[] remoteName, ref int bufferLength);
[System.Runtime.InteropServices.DllImport("shlwapi.dll", EntryPoint = "PathIsNetworkPath", SetLastError = true)]
private static extern bool PathIsNetworkPath(string localDrive);
[System.Runtime.InteropServices.DllImport("kernel32.dll", EntryPoint = "GetDriveType", SetLastError = true)]
private static extern int GetDriveType(string localDrive);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct structNetResource
{
public int Scope;
public int Type;
public int DisplayType;
public int Usage;
public string LocalDrive;
public string RemoteName;
public string Comment;
public string Provider;
}
// standard
private const int RESOURCETYPE_DISK = 0x1;
private const int CONNECT_INTERACTIVE = 0x00000008;
private const int CONNECT_PROMPT = 0x00000010;
private const int CONNECT_UPDATE_PROFILE = 0x00000001;
// ie4+
private const int CONNECT_REDIRECT = 0x00000080;
// nt5+
private const int CONNECT_COMMANDLINE = 0x00000800;
private const int CONNECT_CMD_SAVECRED = 0x00001000;
//---------------------------------------------------------------------------------------------------------------------------------------
#endregion
}
}