2 using System
.Collections
.Generic
;
4 using System
.Runtime
.InteropServices
;
6 using System
.Windows
.Forms
;
13 /// Gets a list of machines and open shares on LAN. Uses DllImport of Netapi32.dll.
15 public sealed class NetworkBrowser
: INetworkBrowser
17 private static NetworkBrowser _instance
;
19 private IEnumerable
<string> _windowsNetworks
;
21 private NetworkBrowser()
25 public static NetworkBrowser Instance
29 if ( _instance
== null )
31 _instance
= new NetworkBrowser();
40 /// Netapi32.dll : Get list of servers on the network.
42 [DllImport( "Netapi32", CharSet
= CharSet
.Auto
, SetLastError
= true ), SuppressUnmanagedCodeSecurity
]
43 private static extern int NetServerEnum(
44 string ServerNane
, // must be null
48 out int dwEntriesRead
,
49 out int dwTotalEntries
,
51 string domain
, // null for login domain
52 out int dwResumeHandle
56 /// Netapi32.dll : Get list of shares on given machine.
58 /// <returns></returns>
59 [DllImport( "Netapi32", CharSet
= CharSet
.Auto
, SetLastError
= true ), SuppressUnmanagedCodeSecurity
]
60 private static extern int NetShareEnum(
72 /// Netapi32.dll : The NetApiBufferFree function frees the memory
73 /// that the NetApiBufferAllocate function allocates.
74 /// Call NetApiBufferFree to free the memory that other network management functions return.
76 [DllImport( "Netapi32", SetLastError
= true ), SuppressUnmanagedCodeSecurity
]
77 private static extern int NetApiBufferFree(
81 /// ServerInfo structure holds information on network servers returned by <see cref="NetServerEnum"/>.
83 [StructLayout( LayoutKind
.Sequential
)]
84 private struct _SERVER_INFO_100
86 internal int sv100_platform_id
;
87 [MarshalAs( UnmanagedType
.LPWStr
)] internal string sv100_name
;
91 /// ShareInfo1 structure hold share infomation as returned by <see cref="NetShareEnum"/> level 1.
93 [StructLayout( LayoutKind
.Sequential
)]
94 private struct _SHARE_INFO_1
96 [MarshalAs( UnmanagedType
.LPWStr
)] internal string shi1_netname
;
98 internal uint shi1_type
;
99 [MarshalAs( UnmanagedType
.LPWStr
)] internal string shi1_remark
;
102 [DllImport( "Mpr.dll", EntryPoint
= "WNetOpenEnumA", CallingConvention
= CallingConvention
.Winapi
)]
103 private static extern ErrorCodes
WNetOpenEnum( ResourceScope dwScope
, ResourceType dwType
, ResourceUsage dwUsage
,
104 NETRESOURCE p
, out IntPtr lphEnum
);
106 [DllImport( "Mpr.dll", EntryPoint
= "WNetCloseEnum", CallingConvention
= CallingConvention
.Winapi
)]
107 private static extern ErrorCodes
WNetCloseEnum( IntPtr hEnum
);
109 [DllImport( "Mpr.dll", EntryPoint
= "WNetEnumResourceA", CallingConvention
= CallingConvention
.Winapi
)]
110 private static extern ErrorCodes
WNetEnumResource( IntPtr hEnum
, ref uint lpcCount
, IntPtr buffer
,
111 ref uint lpBufferSize
);
117 private const int MAX_PREFERRED_LENGTH
= -1;
119 private const int SV_TYPE_WORKSTATION
= 1;
120 private const int SV_TYPE_SERVER
= 2;
122 private const uint STYPE_PRINTQ
= 1;
123 private const uint STYPE_DEVICE
= 2;
124 private const uint STYPE_IPC
= 3;
126 private const uint STYPE_SPECIAL
= 0x80000000;
127 private const uint STYPE_TEMPORARY
= 0x40000000;
131 #region Public Methods
134 /// Gets Microsoft Windows Networks.
136 public IEnumerable
<string> WindowsNetworks
140 if ( _windowsNetworks
== null )
142 NETRESOURCE netRoot
= new NETRESOURCE();
143 IEnumerable
<string> networkObjects
144 = EnumerateServers( netRoot
, ResourceScope
.RESOURCE_GLOBALNET
, ResourceType
.RESOURCETYPE_DISK
,
145 ResourceUsage
.RESOURCEUSAGE_ALL
,
146 ResourceDisplayType
.RESOURCEDISPLAYTYPE_NETWORK
, "" );
148 _windowsNetworks
= from nwo
in networkObjects
149 where nwo
.EndsWith( "|RESOURCEDISPLAYTYPE_DOMAIN" )
150 select nwo
.Remove( nwo
.LastIndexOf( '|' ) );
153 return _windowsNetworks
;
158 /// Get public shares defined in network given.
160 /// <param name="networkName"></param>
161 /// <returns></returns>
162 public IEnumerable
<string> GetNetworkShares( string networkName
)
164 IEnumerable
<string> shares
= null;
166 if ( WindowsNetworks
.Contains( networkName
) )
168 NETRESOURCE netRoot
= new NETRESOURCE();
169 IEnumerable
<string> machines
170 = EnumerateServers( netRoot
, ResourceScope
.RESOURCE_GLOBALNET
, ResourceType
.RESOURCETYPE_DISK
,
171 ResourceUsage
.RESOURCEUSAGE_ALL
, ResourceDisplayType
.RESOURCEDISPLAYTYPE_SERVER
,
174 shares
= from share
in machines
175 where share
.Count( '\\' ) >= 3
184 /// List network ResourceScope using Mpr.dll functions.
186 /// <param name="pRsrc"></param>
187 /// <param name="scope"></param>
188 /// <param name="type"></param>
189 /// <param name="usage"></param>
190 /// <param name="displayType"></param>
191 /// <param name="kPath"></param>
192 /// <returns></returns>
193 private static IEnumerable
<string> EnumerateServers( NETRESOURCE pRsrc
, ResourceScope scope
, ResourceType type
,
194 ResourceUsage usage
, ResourceDisplayType displayType
,
197 List
<string> aData
= new List
<string>();
199 uint bufferSize
= 16384;
200 IntPtr buffer
= Marshal
.AllocHGlobal( (int) bufferSize
);
203 bool serverenum
= false;
205 ErrorCodes result
= WNetOpenEnum( scope
, type
, usage
, pRsrc
, out handle
);
207 if ( result
== ErrorCodes
.NO_ERROR
)
211 result
= WNetEnumResource( handle
, ref cEntries
, buffer
, ref bufferSize
);
213 if ( ( result
== ErrorCodes
.NO_ERROR
) )
215 Marshal
.PtrToStructure( buffer
, pRsrc
);
217 if ( String
.Compare( kPath
, "" ) == 0 )
219 if ( ( pRsrc
.dwDisplayType
== displayType
) ||
220 ( pRsrc
.dwDisplayType
== ResourceDisplayType
.RESOURCEDISPLAYTYPE_DOMAIN
) )
222 aData
.Add( pRsrc
.lpRemoteName
+ "|" + pRsrc
.dwDisplayType
);
225 if ( ( pRsrc
.dwUsage
& ResourceUsage
.RESOURCEUSAGE_CONTAINER
) ==
226 ResourceUsage
.RESOURCEUSAGE_CONTAINER
)
228 if ( ( pRsrc
.dwDisplayType
== displayType
) )
230 aData
.AddRange( EnumerateServers( pRsrc
, scope
, type
, usage
, displayType
, kPath
) );
236 if ( pRsrc
.dwDisplayType
== displayType
)
238 aData
.Add( pRsrc
.lpRemoteName
);
239 aData
.AddRange( EnumerateServers( pRsrc
, scope
, type
, usage
, displayType
, kPath
) );
245 if ( pRsrc
.dwDisplayType
== ResourceDisplayType
.RESOURCEDISPLAYTYPE_SHARE
)
247 aData
.Add( pRsrc
.lpRemoteName
+ "-share" );
254 if ( ( kPath
.IndexOf( pRsrc
.lpRemoteName
) >= 0 ) ||
255 ( String
.Compare( pRsrc
.lpRemoteName
, "Microsoft Windows Network" ) == 0 ) )
257 aData
.AddRange( EnumerateServers( pRsrc
, scope
, type
, usage
, displayType
, kPath
) );
261 else if ( result
!= ErrorCodes
.ERROR_NO_MORE_ITEMS
)
266 while ( result
!= ErrorCodes
.ERROR_NO_MORE_ITEMS
);
268 WNetCloseEnum( handle
);
271 Marshal
.FreeHGlobal( buffer
);
277 public enum ResourceScope
279 RESOURCE_CONNECTED
= 1,
286 public enum ResourceType
291 RESOURCETYPE_RESERVED
295 public enum ResourceUsage
297 RESOURCEUSAGE_CONNECTABLE
= 0x00000001,
298 RESOURCEUSAGE_CONTAINER
= 0x00000002,
299 RESOURCEUSAGE_NOLOCALDEVICE
= 0x00000004,
300 RESOURCEUSAGE_SIBLING
= 0x00000008,
301 RESOURCEUSAGE_ATTACHED
= 0x00000010,
302 RESOURCEUSAGE_ALL
= ( RESOURCEUSAGE_CONNECTABLE
| RESOURCEUSAGE_CONTAINER
| RESOURCEUSAGE_ATTACHED
),
305 internal enum ErrorCodes
308 ERROR_NO_MORE_ITEMS
= 259
311 public enum ResourceDisplayType
313 RESOURCEDISPLAYTYPE_GENERIC
,
314 RESOURCEDISPLAYTYPE_DOMAIN
,
315 RESOURCEDISPLAYTYPE_SERVER
,
316 RESOURCEDISPLAYTYPE_SHARE
,
317 RESOURCEDISPLAYTYPE_FILE
,
318 RESOURCEDISPLAYTYPE_GROUP
,
319 RESOURCEDISPLAYTYPE_NETWORK
,
320 RESOURCEDISPLAYTYPE_ROOT
,
321 RESOURCEDISPLAYTYPE_SHAREADMIN
,
322 RESOURCEDISPLAYTYPE_DIRECTORY
,
323 RESOURCEDISPLAYTYPE_TREE
,
324 RESOURCEDISPLAYTYPE_NDSCONTAINER
327 [StructLayout( LayoutKind
.Sequential
)]
328 internal class NETRESOURCE
330 public ResourceScope dwScope
= 0;
331 public ResourceType dwType
= 0;
332 public ResourceDisplayType dwDisplayType
= 0;
333 public ResourceUsage dwUsage
= 0;
334 public string lpLocalName
;
335 public string lpRemoteName
;
336 public string lpComment
;
337 public string lpProvider
;
346 /// Get list of share names available on given server.
348 /// <param name="serverName">Network machine name.</param>
349 /// <returns>List of shares on server.</returns>
350 public IEnumerable
<string> GetShares( string serverName
)
352 IntPtr buffer
= IntPtr
.Zero
;
354 List
<string> shares
= new List
<string>();
355 int sizeofInfo
= Marshal
.SizeOf( typeof( _SHARE_INFO_1
) );
362 int ret
= NetShareEnum( serverName
, 1, ref buffer
, MAX_PREFERRED_LENGTH
, out entriesRead
,
368 for ( int i
= 0; i
< totalEntries
; i
++ )
370 // Get next pointer to share info structure
371 IntPtr tmpBuffer
= new IntPtr( (int) buffer
+ ( i
* sizeofInfo
) );
373 // Get structure from pointer
374 _SHARE_INFO_1 shareInfo
=
375 (_SHARE_INFO_1
) Marshal
.PtrToStructure( tmpBuffer
, typeof( _SHARE_INFO_1
) );
377 // Skipe special types of shares
378 if ( ( shareInfo
.shi1_type
& STYPE_TEMPORARY
) == STYPE_TEMPORARY
379 || ( shareInfo
.shi1_type
& STYPE_IPC
) == STYPE_IPC
380 || ( shareInfo
.shi1_type
& STYPE_DEVICE
) == STYPE_DEVICE
381 || ( shareInfo
.shi1_type
& STYPE_PRINTQ
) == STYPE_PRINTQ
382 || ( shareInfo
.shi1_type
& STYPE_SPECIAL
) == STYPE_SPECIAL
383 || shareInfo
.shi1_remark
== "Printer Drivers" )
388 shares
.Add( @"\\" + serverName
+ @"\" + shareInfo
.shi1_netname
);
392 catch ( Exception ex
)
394 MessageBox
.Show( "Problem with acessing " +
395 "remote shares in NetworkBrowser " +
396 "\r\n\r\n\r\n" + ex
.Message
,
397 "Error", MessageBoxButtons
.OK
,
398 MessageBoxIcon
.Error
);
403 // Free allocated memory
404 NetApiBufferFree( buffer
);
411 /// Get the list of network machine of types serves and workstation.
413 /// <returns>List of machines in network.</returns>
414 public IEnumerable
<string> GetNetworkComputers()
416 IntPtr buffer
= IntPtr
.Zero
;
417 int sizeofInfo
= Marshal
.SizeOf( typeof( _SERVER_INFO_100
) );
418 string[] networkComputers
= null;
421 // Get list of machines
425 int ret
= NetServerEnum( null, 100, ref buffer
, MAX_PREFERRED_LENGTH
, out entriesRead
, out totalEntries
,
426 SV_TYPE_WORKSTATION
| SV_TYPE_SERVER
, null, out resHandle
);
430 networkComputers
= new string[totalEntries
];
431 for ( int i
= 0; i
< totalEntries
; i
++ )
433 // Get next pointer to server info structure
434 IntPtr tmpBuffer
= new IntPtr( (int) buffer
+ ( i
* sizeofInfo
) );
436 // Get structure from pointer
437 _SERVER_INFO_100 svrInfo
=
438 (_SERVER_INFO_100
) Marshal
.PtrToStructure( tmpBuffer
, typeof( _SERVER_INFO_100
) );
440 networkComputers
[ i
] = svrInfo
.sv100_name
;
444 catch ( Exception ex
)
446 MessageBox
.Show( "Problem with acessing " +
447 "network computers in NetworkBrowser " +
448 "\r\n\r\n\r\n" + ex
.Message
,
449 "Error", MessageBoxButtons
.OK
,
450 MessageBoxIcon
.Error
);
455 // Free allocated memory
456 NetApiBufferFree( buffer
);
459 return networkComputers
;