C# mount / unmount UNC (network folder / drive) 連結網路磁碟機

有些時候為了 security 問題或者想要詳細紀錄使用者存取網路磁碟機或目錄中資料的情況, 所以會另外建立帳號並透過程式來存取網路磁碟機, 而不讓使用者直接用他的帳號密碼來存取, 這時候就需要讓程式可以建立網路磁碟機與中斷連線.

我自己比較喜歡第一個方式, 相對來說簡單許多.

Approach 1

using IWshRuntimeLibrary;	//Add "Windows Script Host Object Model" COM reference

private WshNetwork _networkShell = new WshNetwork();

//UNC is the network folder/drive path, e.g. \\server\folder1
public void MapDrive(string driveLetter, string UNC, bool isPersistent, string userName, string password)
{
	// Disconnect the drive first, forcing a permanent change.
	if (driveLetter != "")
	{
		DisconnectDrive(driveLetter, true, true);
	}
	else
	{
		DisconnectDrive(UNC, true, true);
	}

	// Map the drive to the path.
	object persistent = isPersistent;
	object user = userName;
	object pwd = password;

	_networkShell.MapNetworkDrive(driveLetter, UNC, ref persistent, ref user, ref pwd);
}

public void DisconnectDrive(string UNC_or_DriveName, bool willForce, bool isPersistent)
{
	try
	{
		object force = willForce;
		object updateProfile = isPersistent;

		_networkShell.RemoveNetworkDrive(UNC_or_DriveName, ref force, ref updateProfile);
	}
	catch
	{
	}
}

Approach 2

using BOOL = System.Boolean;
using DWORD = System.UInt32;
using LPWSTR = System.String;
using NET_API_STATUS = System.UInt32;


[DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern NET_API_STATUS NetUseAdd(
	LPWSTR UncServerName,
	DWORD Level,
	ref USE_INFO_2 Buf,
	out DWORD ParmError);

[DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern NET_API_STATUS NetUseDel(
	LPWSTR UncServerName,
	LPWSTR UseName,
	DWORD ForceCond);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct USE_INFO_2
{
	internal LPWSTR ui2_local;
	internal LPWSTR ui2_remote;
	internal LPWSTR ui2_password;
	internal DWORD ui2_status;
	internal DWORD ui2_asg_type;
	internal DWORD ui2_refcount;
	internal DWORD ui2_usecount;
	internal LPWSTR ui2_username;
	internal LPWSTR ui2_domainname;
}


private void Mount(string drive, string networkPath, string id, string pw)
{
	if (drive != "")
	{
		NetUseDel("", drive, 2);
	}
	else
	{
		NetUseDel("", networkPath, 2);
	}

	USE_INFO_2 useInfo = new USE_INFO_2();
	useInfo.ui2_local = drive;
	useInfo.ui2_remote = networkPath;
	useInfo.ui2_password = pw;
	useInfo.ui2_asg_type = 0;    //disk drive
	useInfo.ui2_usecount = 1;
	useInfo.ui2_username = id;
	//useInfo.ui2_domainname = "";

	uint paramErrorIndex;
	uint returnCode = NetUseAdd(null, 2, ref useInfo, out paramErrorIndex);
	if (returnCode != 0)
	{
		throw new Win32Exception((int)returnCode);
	}
}

private void UnMount(string networkPath_or_Drive)
{
	NetUseDel("", networkPath_or_Drive, 2);
}