共有フォルダ一覧を取得。
Directory.GetFiles()では共有フォルダの一覧が取れない。(共有フォルダの中身は取れる)
共有フォルダの一覧を取るには NetShareEnum を使う。
public class NetShare { const int NERR_Success = 0; const uint MAX_PREFERRED_LENGTH = 0xFFFFFFFF; enum DataInformationLevel { /// <summary> /// 共有の名前を取得します。関数から制御が返ると、bufptr パラメータが指すバッファに、複数の 構造体からなる 1 つの配列が格納されます。 /// </summary> Level0 = 0, /// <summary> /// リソースの名前、タイプ、リソースに関連付けられているコメントなど、共有リソースに関する情報を取得します。 /// 関数から制御が返ると、bufptr パラメータが指すバッファに、複数の 構造体からなる 1 つの配列が格納されます。 /// </summary> Level1 = 1, /// <summary> /// リソースの名前、タイプ、アクセス許可、パスワード、接続の数など、共有リソースに関する情報を取得します。関数から制御が返ると、bufptr パラメータが指すバッファに、複数の 構造体からなる 1 つの配列が格納されます。 /// </summary> Level2 = 2, /// <summary> /// リソースの名前、タイプ、アクセス許可、接続の数、他の固有情報など、共有リソースに関する情報を取得します。関数から制御が返ると、bufptr パラメータが指すバッファに、複数の 構造体からなる 1 つの配列が格納されます。 /// </summary> Level502 = 502, } /// <summary> /// 特定のサーバー上の各共有資源に関する情報を取得します。Windows 95/98 では使用できません。 /// </summary> /// <param name="ServerName">この関数を実行するリモートサーバーの名前を表す、Unicode 文字列へのポインタを指定します。この文字列の先頭は "\\" でなければなりません。このパラメータで NULL を指定すると、ローカルコンピュータが使われます。</param> /// <param name="level">データの情報レベルを指定します。次の値のいずれかを指定します。</param> /// <param name="bufPtr">1 個のバッファへのポインタを指定します。関数から制御が返ると、このバッファに、指定したデータが格納されます。このデータの形式は、level パラメータの値によって異なります。このバッファはシステムによって割り当てられたものであり、NetApiBufferFree 関数を使って解放しなければなりません。この関数が失敗して ERROR_MORE_DATA が返った場合でも、このバッファを解放しなければならないことに注意してください。</param> /// <param name="prefmaxlen">取得するべきデータの最大の長さ(上限)をバイト単位で指定します。このパラメータが MAX_PREFERRED_LENGTH の場合、この関数はデータが必要とする量のメモリを割り当てます。このパラメータで他の値を指定すると、その値は、この関数が返すバイト数に制限を加えることがあります。バッファサイズが不足して一部のエントリを格納できない場合は、ERROR_MORE_DATA が返ります。詳細については、MSDN ライブラリの「Network Management Function Buffers」と「Network Management Function Buffer Lengths」を参照してください。</param> /// <param name="entriesread">1 つの DWORD 値へのポインタを指定します。関数から制御が返ると、この値に、実際に列挙された要素の数が格納されます。</param> /// <param name="totalentries">1 つの DWORD 値へのポインタを指定します。関数から制御が返ると、この値に、現在のレジューム位置以降で列挙できるはずのエントリの総数が格納されます。</param> /// <param name="resume_handle">引き続き既存の共有を検索するために使われるレジュームハンドルを保持している、1 つの DWORD 値へのポインタを指定します。このハンドルは最初の呼び出しのときに 0 であるべきで、それ以降の呼び出しでも変更しないでください。resume_handle パラメータで NULL を指定すると、レジュームハンドルは格納されません。</param> /// <returns>関数が成功すると、NERR_Success が返ります。関数が失敗すると、Win32 API のエラーコードが返ります。エラーコードのリストについては、MSDN ライブラリの「System Error Codes」を参照してください。</returns> /// <remarks>特定の共有が、DFS ルート内の DFS リンクであるかどうかを示す値を取得するには、情報レベル 1005 を指定して NetShareGetInfo 関数を呼び出してください。</remarks> [DllImport( "Netapi32.dll", CharSet = CharSet.Unicode )] static extern int NetShareEnum( StringBuilder serverName, DataInformationLevel level, ref IntPtr bufPtr, uint prefmaxlen, out int entriesread, out int totalentries, ref int resume_handle ); /// <summary> /// NetApiBufferAllocate が割り当てたメモリを解放します。Windows NT/2000 上で他のネットワーク管理関数が返したメモリを解放するには、この関数を使ってください。 /// </summary> /// <param name="Buffer">既に他のネットワーク管理関数が返したバッファへのポインタを指定します。</param> /// <returns>関数が成功すると、NERR_Success が返ります。</returns> [DllImport( "Netapi32.dll", SetLastError = true )] static extern int NetApiBufferFree( IntPtr Buffer ); /// <summary> /// The SHARE_INFO_1 structure contains information about the shared resource, including the name and type of the resource, and a comment associated with the resource. /// </summary> [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )] public struct SHARE_INFO_1 { /// <summary> /// Pointer to a Unicode string specifying the share name of a resource. Calls to the NetShareSetInfo function ignore this member. /// </summary> public string shi1_netname; /// <summary> /// A bitmask of flags that specify the type of the shared resource. Calls to the NetShareSetInfo function ignore this member. /// </summary> public uint shi1_type; /// <summary> /// Pointer to a Unicode string specifying an optional comment about the shared resource. /// </summary> public string shi1_remark; public SHARE_INFO_1( string sharename, uint sharetype, string remark ) { shi1_netname = sharename; shi1_type = sharetype; shi1_remark = remark; } public override string ToString() { return shi1_netname; } } /// <summary> /// サーバ上の共有ファイル一覧を取得。 /// </summary> /// <param name="Server">対象サーバ。</param> /// <returns></returns> public static List<SHARE_INFO_1> GetNetShares( string server ) { int entriesread; IntPtr bufPtr = GetBufPtr( server, out entriesread ); try { return GetShareInfos( bufPtr, entriesread ); } finally { NetApiBufferFree( bufPtr ); } } private static List<SHARE_INFO_1> GetShareInfos( IntPtr bufPtr, int entriesread ) { IntPtr currentPtr = bufPtr; List<SHARE_INFO_1> shareInfos = new List<SHARE_INFO_1>(); int nStructSize = Marshal.SizeOf( typeof( SHARE_INFO_1 ) ); for (int i = 0; i < entriesread; i++) { SHARE_INFO_1 shi1 = (SHARE_INFO_1)Marshal.PtrToStructure( currentPtr, typeof( SHARE_INFO_1 ) ); shareInfos.Add( shi1 ); currentPtr = new IntPtr( currentPtr.ToInt32() + nStructSize ); } return shareInfos; } private static IntPtr GetBufPtr( string server, out int entriesread ) { int totalentries; int resume_handle = 0; IntPtr bufPtr = IntPtr.Zero; int result = NetShareEnum( new StringBuilder( server ), DataInformationLevel.Level1, ref bufPtr , MAX_PREFERRED_LENGTH, out entriesread, out totalentries, ref resume_handle ); if (result != NERR_Success) { throw new Win32Exception( result ); } return bufPtr; } }
コメントめちゃめちゃみ難いな。firefoxは仕様。というかむしろもっとも意図した表示に近い。
■使い方
/// <summary> /// 指定されたパスのファイル一覧を取得します。 /// </summary> /// <param name="path">ファイル一覧取得対象のパス。</param> /// <returns>取得されたファイル一覧。</returns> public List<string> GetFileList( string path ) { List<string> list = new List<string>(); if (IsNetworkRoot( path )) { var sharelist = NetShare.GetNetShares( path ); foreach (NetShare.SHARE_INFO_1 shareInfo in sharelist) { list.Add( shareInfo.ToString() ); } } else { AddlocalPath(list, path ); } return list; } private static void AddlocalPath( ICollection<string> list, string path ) { foreach (string dir in Directory.GetDirectories( path )) { list.Add( "[" + dir + "]" ); } foreach (string file in Directory.GetFiles( path )) { list.Add( file ); } } private static bool IsNetworkRoot( string path ) { return Regex.IsMatch( path, @"^(\\\\[^\\]+([^\\]|\\))$" ); }