Всем привет! Уже задавал такой вопрос здесь, но так ни кто и не ответил... Как можно средствами .NET просканировать окрытые шары на SMB ресурсах в локальной сети(причем как и обычные так и системные — которые заканчиваюся на $)? Пишу на С#.
Здравствуйте, Trex_0, Вы писали:
T_>Всем привет! Уже задавал такой вопрос здесь, но так ни кто и не ответил... Как можно средствами .NET просканировать окрытые шары на SMB ресурсах в локальной сети(причем как и обычные так и системные — которые заканчиваюся на $)? Пишу на С#.
Вот этот API поможет тебе в твоей задаче, как пользоваться вызовами можно узнать в
MSDN.
NativeMethods.cs
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
namespace Scanner
{
[HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
internal static class NativeMethods
{
#region Constants
internal static readonly HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
internal const uint ERROR_SUCCESS = 0;
internal const uint ERROR_ACCESS_DENIED = 5;
internal const uint ERROR_NOT_ENOUGH_MEMORY = 8;
internal const uint ERROR_REM_NOT_LIST = 51;
internal const uint ERROR_BAD_NETPATH = 53;
internal const uint ERROR_NETNAME_DELETED = 64;
internal const uint ERROR_INVALID_PARAMETER = 87;
internal const uint ERROR_MORE_DATA = 234;
internal const uint ERROR_INVALID_COMPUTER_NAME = 2351;
internal const uint ERROR_NO_BROWSER_SERVERS_FOUND = 6118;
internal const uint MAX_PREFERRED_LENGTH = UInt32.MaxValue;
[Flags]
internal enum FORMAT_MESSAGE: uint
{
NONE = 0x00000000,
ALLOCATE_BUFFER = 0x00000100,
IGNORE_INSERTS = 0x00000200,
FROM_STRING = 0x00000400,
FROM_HMODULE = 0x00000800,
FROM_SYSTEM = 0x00001000,
ARGUMENT_ARRAY = 0x00002000,
MAX_WIDTH_MASK = 0x000000FF
}
[Flags]
internal enum SV_TYPE: uint
{
NONE = 0x00000000,
WORKSTATION = 0x00000001,
SERVER = 0x00000002,
SQLSERVER = 0x00000004,
DOMAIN_CTRL = 0x00000008,
DOMAIN_BAKCTRL = 0x00000010,
TIME_SOURCE = 0x00000020,
AFP = 0x00000040,
NOVELL = 0x00000080,
DOMAIN_MEMBER = 0x00000100,
PRINTQ_SERVER = 0x00000200,
DIALIN_SERVER = 0x00000400,
XENIX_SERVER = 0x00000800,
SERVER_UNIX = 0x00000800,
NT = 0x00001000,
WFW = 0x00002000,
SERVER_MFPN = 0x00004000,
SERVER_NT = 0x00008000,
POTENTIAL_BROWSER = 0x00010000,
BACKUP_BROWSER = 0x00020000,
MASTER_BROWSER = 0x00040000,
DOMAIN_MASTER = 0x00080000,
SERVER_OSF = 0x00100000,
SERVER_VMS = 0x00200000,
WINDOWS = 0x00400000,
DFS = 0x00800000,
CLUSTER_NT = 0x01000000,
TERMINALSERVER = 0x02000000,
CLUSTER_VS_NT = 0x04000000,
DCE = 0x10000000,
ALTERNATE_XPORT = 0x20000000,
LOCAL_LIST_ONLY = 0x40000000,
DOMAIN_ENUM = 0x80000000,
ALL = 0xFFFFFFFF
}
internal enum PLATFORM_ID
{
DOS = 300,
OS2 = 400,
NT = 500,
OSF = 600,
VMS = 700
}
internal enum SERVER_INFO_LEVEL
{
_100 = 100,
_101 = 101
}
internal enum STYPE: uint
{
DISKTREE = 0,
PRINTQ = 1,
DEVICE = 2,
IPC = 3,
TEMPORARY = 0x40000000,
SPECIAL = 0x80000000
}
internal enum SHARE_INFO_LEVEL
{
_0 = 0,
_1 = 1,
_2 = 2,
_50 = 50,
_502 = 502
}
[Flags]
internal enum SUPPORTS: uint
{
NONE = 0x00000000,
REMOTE_ADMIN_PROTOCOL = 0x00000002,
RPC = 0x00000004,
SAM_PROTOCOL = 0x00000008,
UNICODE = 0x00000010,
LOCAL = 0x00000020,
ANY = 0xFFFFFFFF
}
#endregion
#region Data Structures
[StructLayout(LayoutKind.Sequential)]
internal struct SERVER_INFO_100
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal PLATFORM_ID sv100_platform_id;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string sv100_name;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SERVER_INFO_101
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal PLATFORM_ID sv101_platform_id;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string sv101_name;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal uint sv101_version_major;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal uint sv101_version_minor;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal uint sv101_type;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string sv101_comment;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SHARE_INFO_0
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string shi0_netname;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SHARE_INFO_1
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string shi1_netname;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
internal STYPE shi1_type;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
internal string shi1_remark;
}
#endregion
#region API Entries
[DllImport("netapi32.dll", EntryPoint="NetApiBufferFree")]
internal static extern int NetApiBufferFree(IntPtr buffer);
[DllImport("netapi32.dll", CharSet=CharSet.Unicode, EntryPoint="NetServerEnum")]
internal static extern uint NetServerEnum(
[MarshalAs(UnmanagedType.LPWStr)]
string serverName,
SERVER_INFO_LEVEL level,
out IntPtr bufPtr,
uint prefMaxLen,
ref uint entriesRead,
ref uint totalEntries,
SV_TYPE serverType,
[MarshalAs(UnmanagedType.LPWStr)]
string domain,
IntPtr resumeHandle);
[DllImport("netapi32.dll", CharSet=CharSet.Unicode, EntryPoint="NetShareEnum")]
internal static extern uint NetShareEnum(
[MarshalAs(UnmanagedType.LPWStr)]
string serverName,
SHARE_INFO_LEVEL level,
out IntPtr bufPtr,
uint prefMaxLen,
ref uint entriesRead,
ref uint totalEntries,
IntPtr resumeHandle);
#if false
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetRemoteComputerSupports")]
internal static extern uint NetRemoteComputerSupports(
[MarshalAs(UnmanagedType.LPWStr)]
string uncServerName,
SUPPORTS optionsWanted,
out SUPPORTS optionsSupported);
#endif
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true)]
internal static extern int FormatMessage(
FORMAT_MESSAGE flags,
HandleRef source,
uint messageId,
uint languageId,
StringBuilder buffer,
int bufferSize,
IntPtr arguments);
#endregion
}
}
DomainComputerCollection.cs (пример использования NetServerEnum, работа с другими вызовами NetApi32 похожая):
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Scanner
{
public class DomainComputerCollection: ResourceWrapper, IEnumerable<string>
{
public DomainComputerCollection(string domain)
{
this.domain = domain;
serverInfoPtr = new IntPtr();
uint status = NativeMethods.NetServerEnum(null,
NativeMethods.SERVER_INFO_LEVEL._100, out serverInfoPtr,
NativeMethods.MAX_PREFERRED_LENGTH, ref entriesReadNo,
ref entriesTotalNo, NativeMethods.SV_TYPE.ALL, domain, IntPtr.Zero);
if (status != NativeMethods.ERROR_SUCCESS)
throw new NetApiException("NetServerEnum", status);
}
public uint TotalCount
{
get { return entriesTotalNo; }
}
public uint ReadCount
{
get { return entriesReadNo; }
}
public string Domain
{
get { return domain; }
}
#region IEnumerable<string> Members
public IEnumerator<string> GetEnumerator()
{
int ptr = serverInfoPtr.ToInt32();
for (uint entry = 0; entry != entriesReadNo; ++entry) {
NativeMethods.SERVER_INFO_100 serverInfo =
(NativeMethods.SERVER_INFO_100)Marshal.PtrToStructure(new IntPtr(ptr),
typeof(NativeMethods.SERVER_INFO_100));
ptr += Marshal.SizeOf(serverInfo);
yield return serverInfo.sv100_name;
}
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
protected override void DisposeUnmanagedResources()
{
NativeMethods.NetApiBufferFree(serverInfoPtr);
}
private string domain;
private IntPtr serverInfoPtr;
private uint entriesReadNo;
private uint entriesTotalNo;
}
}
Вспомогательные полезные классы:
NetApiException.cs:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Scanner.Properties;
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace Scanner
{
[Serializable]
public class NetApiException: Exception
{
public NetApiException()
: base(Resources.NetApiNoDetails)
{
}
public NetApiException(string message)
: base(message)
{
}
public NetApiException(string message, Exception innerException)
: base(message, innerException)
{
}
protected NetApiException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
if (info != null) {
api = info.GetString("Api");
errorCode = info.GetUInt32("ErrorCode");
}
}
public NetApiException(string api, uint win32ErrorCode)
: base(GetErrorMessage(win32ErrorCode))
{
this.api = api;
this.errorCode = win32ErrorCode;
HResult = HResultFromWin32(win32ErrorCode);
}
public string Api
{
get { return api; }
}
public uint ErrorCode
{
get { return errorCode; }
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
return;
base.GetObjectData(info, context);
info.AddValue("Api", api);
info.AddValue("ErrorCode", errorCode);
}
private static string GetErrorMessage(uint errorCode)
{
StringBuilder message = new StringBuilder(256);
int length = NativeMethods.FormatMessage(NativeMethods.FORMAT_MESSAGE.IGNORE_INSERTS | NativeMethods.FORMAT_MESSAGE.FROM_SYSTEM, NativeMethods.NullHandleRef, errorCode, 0, message, message.Capacity + 1, IntPtr.Zero);
if (length > 0)
return message.ToString(0, length);
return String.Format(Resources.Culture, Resources.NetApiUnknownError, Convert.ToString(errorCode, 0x10));
}
private static int HResultFromWin32(uint x)
{
return ((int)(x) <= 0 ? ((int)(x)) : ((int)(((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)));
}
private string api;
private uint errorCode;
private const int FACILITY_WIN32 = 7;
}
}
ResourceWrapper.cs:
using System;
namespace Scanner
{
public abstract class ResourceWrapper: IDisposable
{
~ResourceWrapper()
{
// Call our helper method.
// Specifying "false" signifies that
// the GC triggered the clean up.
Dispose(false);
}
public void Dispose()
{
// Call our helper method.
// Specifying "true" signifies that
// the object user triggered the clean up.
Dispose(true);
// Now suppress finalization.
GC.SuppressFinalize(this);
}
protected virtual void DisposeManagedResources()
{
}
protected abstract void DisposeUnmanagedResources();
private void Dispose(bool disposing)
{
// Be sure we have not already been disposed!
if (!disposed) {
// If disposing equals true, dispose all
// managed resources.
if (disposing) {
// Dispose managed resources.
DisposeManagedResources();
}
// Clean up unmanaged resources here.
DisposeUnmanagedResources();
}
disposed = true;
}
// Used to determine if Dispose()
// has already been called.
private bool disposed;
}
}
Сегодня я проснулся рано — вчера утром.