Win 32 API netapi 32を呼び出す.dll UNC(ネットワーク共有)接続の管理を実現(一)
本章ではWin 32 API netapi 32を使用する.dllはUNCの接続許可を実現し、接続を切断し、UNCの接続状態の3つの機能を取得する.
一.まずDLLファイルをインポートします.
一.まずDLLファイルをインポートします.
#region Register Win32 DLL File netapi32.dll // NetUseAdd [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseAdd( string UncServerName, // not used int Level, // use info struct level 1 or 2 IntPtr Buf, // Buffer ref int ParmError ); // NetUseDel [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseDel( string UncServerName, //not used string UseName, //Network Resource what do you want to disconnect; uint ForceCond //disconnect mode; ); // Get NetUseGetInfo [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseGetInfo( string UncServerName, string UseName, int Level, ref IntPtr BufPtr);
パラメータタイプを変換したC#用のコードですが、関数のプロトタイプについてはMSDNを参照してください.
次に、上記のパラメータについて簡単に説明します.この章で説明した内容に対応するには十分です(詳細はMSDNを参照してください):
(上から順に紹介)
string UncServerName:
このパラメータは使わないで、Callの時に空にします.
int Level:
そのstructを使用してパラメータを関数に入力し、1はUSE_を表します.INFO_1または2はUSEを表します.INFO_2、知能は両者の間で一つを選択する.
IntPtr Buf,
上の対応する構造を指すポインタ(C#にはポインタはありませんが、この役割はポインタに似ていて、もっと専門的な教法を知っている友达に知らせることができます).
ref int ParmError:
これはあまり使われていないようなので、よく研究していないので、SourceCodeの使い方を直接見てください
uint ForceCond:
接続解除時のモードは、3種類あります.
private const uint USE_NOFORCE = 0; //Do not fail the disconnection if open files exist son the connection. private const uint USE_FORCE = 1; //Fail the disconnection if open files exists on the connection. private const uint USE_LOTS_OF_FORCE = 2; //Close any open files and delete the connection.
ref IntPtr BufPtr:
GetNetUseInfoに伝達するStruct IntPrtオブジェクトは、取得した情報を持ち出す責任を負う.
3つの機能を実現するための完全なSource Codeについて説明します.
class WinNet { #region Define netapi32.dll need data structure [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct _USE_INFO_2 { internal string ui2_local; internal string ui2_remote; //internal IntPtr ui2_password; // don't pass a string or StringBuilder here!! internal string ui2_password; internal uint ui2_status; internal uint ui2_asg_type; internal uint ui2_refcount; internal uint ui2_usecount; internal string ui2_username; internal string ui2_domainname; } const uint USE_WILDCARD = 0xFFFFFFFF; private const uint USE_NOFORCE = 0; //Do not fail the disconnection if open files exist son the connection. private const uint USE_FORCE = 1; //Fail the disconnection if open files exists on the connection. private const uint USE_LOTS_OF_FORCE = 2; //Close any open files and delete the connection. private const uint USE_OK = 0; //The connection is valid. private const uint USE_PAUSED = 1; // Paused by local workstation. private const uint USE_SESSLOST = 2;// Disconnected. private const uint USE_DISCONN = 3;// An error occurred. private const uint USE_NETERR = 4;// A network error occurred. private const uint USE_CONN = 5;// The connection is being made. private const uint USE_RECONN = 6;// Reconnecting. private static WinNet _instance = new WinNet(); public static WinNet Instance { get { return _instance; } } #endregion #region Register Win32 DLL File netapi32.dll [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseAdd( string UncServerName, // not used int Level, // use info struct level 1 or 2 IntPtr Buf, // Buffer ref int ParmError ); [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseDel( string UncServerName, //not used string UseName, //Network Resource what do you want to disconnect; uint ForceCond //disconnect mode; ); [DllImport("netapi32", CharSet = CharSet.Auto, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern int NetUseGetInfo( string UncServerName, string UseName, int Level, ref IntPtr BufPtr); #endregion /// /// Establish a use record /// /// /// /// /// public static bool UseRecord(string resource, string user, string password, string domain) { bool RtnValue = false; int ret = 1; int paramError = 0; _USE_INFO_2 use2 = new _USE_INFO_2(); IntPtr pBuf = IntPtr.Zero; //use2.ui2_password = IntPtr.Zero; try { pBuf = Marshal.AllocHGlobal(Marshal.SizeOf(use2)); use2.ui2_local = null; use2.ui2_asg_type = USE_WILDCARD; use2.ui2_remote = resource; //use2.ui2_password = Marshal.StringToHGlobalAuto(password); use2.ui2_password = password; use2.ui2_username = user; use2.ui2_domainname = domain; Marshal.StructureToPtr(use2, pBuf, true); ret = NetUseAdd(null, 2, pBuf, ref paramError); if (ret != 0) { throw new Exception(ErrorCodeHandler(ret)); } RtnValue = true; } catch (Exception e) { throw e; } finally { Marshal.FreeHGlobal(pBuf); } return RtnValue; } /// /// Destroy a use record /// /// public static void DeleteRecord(string resource) { int ret = 1; try { ret = NetUseDel(null, resource, USE_LOTS_OF_FORCE); if (ret != 0) { throw new Exception(ErrorCodeHandler(ret)); } } catch (Exception e) { throw e; } } public static _USE_INFO_2 GetUseInfo(string resource) { int ret = 1; _USE_INFO_2 ui2 = new _USE_INFO_2(); IntPtr pBuf = IntPtr.Zero; try { pBuf = Marshal.AllocHGlobal(Marshal.SizeOf(new _USE_INFO_2())); ret = NetUseGetInfo(null, resource, 2, ref pBuf); if (ret != 0) { throw new Exception(ErrorCodeHandler(ret)); } ui2 = (_USE_INFO_2)Marshal.PtrToStructure(pBuf, typeof(_USE_INFO_2)); } catch { //throw e; } finally { Marshal.FreeHGlobal(pBuf); } return ui2; } #region Win32 ErrorCode Handler Code public static string ErrorCodeHandler(int Win32ErrorCode) { string RtnMessage = string.Empty; switch (Win32ErrorCode) { case 67: RtnMessage = " ."; break; case 1219: RtnMessage = " 。 , ... "; break; case 2250: RtnMessage = " ."; break; default: RtnMessage = "Unkown Error Code."; break; } return RtnMessage + "/r/nWin32 Error Code:" + Win32ErrorCode; } #endregion }
API呼び出し異常の処理については、コードをデバッグするときに出会ったバグでもあります.ついでに、これを共有します.
通常、Api呼び出しに異常が発生した場合、GetLastError()メソッドで最後のエラーが取得されますが、私が実際に実行している間にN(N>10)回のエラーが発生し、GetLastError()で得られたエラー情報はすべて「オーバーラップI/O操作が進行中」であり、あちこち助けを求めても答えが得られませんでしたが、その後、各APIが終了した後にintタイプの戻り値:0が実行成功を表していることに気づきました.本章でよく用いられるErrorCodeHandler()法について説明した.
次に暇があれば、Windows UNC共有管理のウィジェットを書く予定です.その中には、現在のすべての共有の様々な状態と、すべての共有に対する操作がリストされます.
Remark:
上の取得共有状態は現在connection or disconnectionのみと判断でき、私のプロジェクトにはこれに対してこの2つの状態のみを要求すべきであるため、詳細な分類は行われていない.