190 lines
7.6 KiB
C#
190 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Sdaleo.Systems.SQLServer
|
|
{
|
|
/// <summary>
|
|
/// Summary description for SQLInfoEnumerator.
|
|
/// This class Enumerates a network for SQL Server instances and returns a list.
|
|
/// For a given SQL Server instance a list of all available databases is returned
|
|
/// For more information see
|
|
/// </summary>
|
|
/// <see cref="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcsqlbrowseconnect.asp"/>
|
|
/// <seealso cref="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp09192002.asp"/>
|
|
internal class SQLInfoEnumerator
|
|
{
|
|
#region ODBC32 external function definitions
|
|
|
|
[DllImport("odbc32.dll")]
|
|
private static extern short SQLAllocHandle(short handleType, IntPtr inputHandle, out IntPtr outputHandlePtr);
|
|
|
|
[DllImport("odbc32.dll")]
|
|
private static extern short SQLSetEnvAttr(IntPtr environmentHandle, int attribute, IntPtr valuePtr, int stringLength);
|
|
|
|
[DllImport("odbc32.dll")]
|
|
private static extern short SQLFreeHandle(short hType, IntPtr Handle);
|
|
|
|
[DllImport("odbc32.dll", CharSet = CharSet.Ansi)]
|
|
private static extern short SQLBrowseConnect(IntPtr handleConnection, StringBuilder inConnection, short stringLength, StringBuilder outConnection, short bufferLength, out short stringLength2Ptr);
|
|
|
|
#endregion
|
|
|
|
#region Constants
|
|
|
|
private const string SQL_DRIVER_STR = "DRIVER={SQL SERVER};";
|
|
private const short SQL_SUCCESS = 0;
|
|
private const short SQL_SUCCESS_WITH_INFO = 1;
|
|
private const short SQL_HANDLE_ENV = 1;
|
|
private const short SQL_HANDLE_DBC = 2;
|
|
private const int SQL_ATTR_ODBC_VERSION = 200;
|
|
private const int SQL_OV_ODBC3 = 3;
|
|
private const short SQL_NEED_DATA = 99;
|
|
private const short DEFAULT_RESULT_SIZE = 1024;
|
|
private const string START_STR = "{";
|
|
private const string END_STR = "}";
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Enumerate the SQL Servers returning a list (if any exist)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal static string[] EnumerateSQLServers()
|
|
{
|
|
return RetrieveInformation(SQL_DRIVER_STR);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate the specified SQL server returning a list of databases (if any exist)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal static string[] EnumerateSQLServersDatabases(string SQLServerNInstance)
|
|
{
|
|
return RetrieveInformation(SQL_DRIVER_STR + "SERVER=" + SQLServerNInstance + ";");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate the specified SQL server returning a list of databases (if any exist)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal static string[] EnumerateSQLServersDatabases(string SQLServerNInstance, string Username, string Password)
|
|
{
|
|
return RetrieveInformation(SQL_DRIVER_STR + "SERVER=" + SQLServerNInstance + ";" + "UID=" + Username + ";" + "PWD=" + Password + ";");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerate for SQLServer/Databases based on the passed information it the string
|
|
/// The more information provided to SQLBrowseConnect the more granular it gets so
|
|
/// if only DRIVER=SQL SERVER passed then a list of all SQL Servers is returned
|
|
/// If DRIVER=SQL SERVER;Server=ServerName is passed then a list of all Databases on the
|
|
/// servers is returned etc
|
|
/// </summary>
|
|
/// <param name="InputParam">A valid string to query for</param>
|
|
/// <returns></returns>
|
|
private static string[] RetrieveInformation(string InputParam)
|
|
{
|
|
IntPtr m_environmentHandle = IntPtr.Zero;
|
|
IntPtr m_connectionHandle = IntPtr.Zero;
|
|
|
|
StringBuilder inConnection = new StringBuilder(InputParam);
|
|
short stringLength = (short)inConnection.Length;
|
|
|
|
StringBuilder outConnection = new StringBuilder(DEFAULT_RESULT_SIZE);
|
|
|
|
short stringLength2Ptr = 0;
|
|
bool bConnectSuccessful = false;
|
|
|
|
try
|
|
{
|
|
// Prepare the SQL Environment Handles
|
|
if ((IsSQLSuccess(SQLAllocHandle(SQL_HANDLE_ENV, m_environmentHandle, out m_environmentHandle))) &&
|
|
(IsSQLSuccess(SQLSetEnvAttr(m_environmentHandle, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0))) &&
|
|
(IsSQLSuccess(SQLAllocHandle(SQL_HANDLE_DBC, m_environmentHandle, out m_connectionHandle))))
|
|
{
|
|
|
|
// Fetch the Data * First get the size of the buffer, then call it to get the buffer *
|
|
if (IsSQLDataSuccess(SQLBrowseConnect(m_connectionHandle, inConnection, stringLength, null, 0, out stringLength2Ptr)) &&
|
|
IsSQLDataSuccess(SQLBrowseConnect(m_connectionHandle, inConnection, stringLength, outConnection, stringLength2Ptr, out stringLength2Ptr))
|
|
)
|
|
{
|
|
bConnectSuccessful = true;
|
|
}
|
|
}
|
|
}
|
|
catch { /* ignore */ }
|
|
finally
|
|
{
|
|
FreeConnection(m_connectionHandle);
|
|
FreeConnection(m_environmentHandle);
|
|
}
|
|
|
|
if (bConnectSuccessful && outConnection.ToString() != "")
|
|
{
|
|
return ParseSQLOutConnection(outConnection.ToString());
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
#region Helper Functions
|
|
|
|
/// <summary>
|
|
/// For quick SQL Return value evaluation
|
|
/// </summary>
|
|
private static bool IsSQLSuccess(short SQL_VALUE)
|
|
{
|
|
if (SQL_VALUE == SQL_SUCCESS || SQL_VALUE == SQL_SUCCESS_WITH_INFO)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// For quick SQL Return value evaluation
|
|
/// </summary>
|
|
private static bool IsSQLDataSuccess(short SQL_VALUE)
|
|
{
|
|
if (SQL_VALUE == SQL_SUCCESS || SQL_VALUE == SQL_SUCCESS_WITH_INFO || SQL_VALUE == SQL_NEED_DATA)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse an outConnection string returned from SQLBrowseConnect
|
|
/// </summary>
|
|
/// <param name="outConnection">string to parse</param>
|
|
/// <returns>Parsed Server names, or Empty Array if none found</returns>
|
|
private static string[] ParseSQLOutConnection(string outConnection)
|
|
{
|
|
int m_Start = outConnection.IndexOf(START_STR) + 1;
|
|
int m_lenString = outConnection.IndexOf(END_STR) - m_Start;
|
|
if ((m_Start > 0) && (m_lenString > 0))
|
|
{
|
|
outConnection = outConnection.Substring(m_Start, m_lenString);
|
|
}
|
|
else
|
|
{
|
|
outConnection = string.Empty;
|
|
}
|
|
return outConnection.Split(",".ToCharArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Call this to Free a SQL handle
|
|
/// </summary>
|
|
private static void FreeConnection(IntPtr handleToFree)
|
|
{
|
|
if (handleToFree != IntPtr.Zero)
|
|
SQLFreeHandle(SQL_HANDLE_DBC, handleToFree);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|