|
|
Comments and Discussions
|
|
 |

|
Thanks very useful was not able to find any good way to discover SQL Servers on the local subnet.
|
|
|
|

|
Great, simple code, well written and still useful years later
|
|
|
|

|
Thank you very much!
|
|
|
|

|
I am a newbie and was wondering.. How do I run this script? What do I use?
Thanks for any help offered..
|
|
|
|

|
Sorry, I'am spanish and dont speak englis very well, and your text in the post dont translate well
I don't understand how to search intances across local network, I supose that your app send a generic ping to port 1433 to all machines on network by using brodcast that reply the signal of ping to all computers, ad them response when have a SQL listening to port 1433
¿This explanation it's correct? I understand well the app?
Thaks lot
|
|
|
|

|
While trying to figure this problem out for our company, I ran into your article. I converted it into vb.net and used some newer types such as List(Of ) instead of arrays. But, then in running your code, it didnt find all the instances we had on our development servers. Thought it might be the vb code vs the c# code, but your raw code didnt work either. We run both SQL 2000 and SQL 2005, and your code would not find the 2005 stuff. So I started to research MS for sql stuff and found the DataSourceEnumerator (which I sadly have to say if I would have just read other comments, it would have saved me HOURS!!... live and learn).
Much easier to allow Windows to retrieve. Although MS has a disclaimer that states this method may "not" retrieve all the servers(data sources) and catalogs, we have never run into a time where it wasn't accurate.
Dim instance As SqlDataSourceEnumerator = _
SqlDataSourceEnumerator.Instance
table = instance.GetDataSources()
Once it is in the datatable you can use the datasources stored in the table and use your GetCatalogs method (very nice) and retrieve the catalogs easily and store those in a datatable to present in a treeview datagridview or even list or combo box controls.
Private Function GetCatalogs() As StringCollection
Dim restrictions As Object()
Dim Catalogs As New StringCollection
restrictions = Nothing
Try
Dim myConnection = GetConnection()
myConnection.Open()
Dim schemaTable As DataTable = myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Catalogs, restrictions)
myConnection.Close()
For Each dr As DataRow In schemaTable.Rows
Dim CatName As String = dr(0).ToString
Catalogs.Add(CatName)
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return Catalogs
End Function
Private Function GetConnection() As OleDbConnection
Dim myConnString As String
myConnString = String.Format("Provider=SQLOLEDB;Data Source={0};Integrated Security=SSPI;Connect Timeout={1}", DataSource, Timeout)
Return New OleDbConnection(myConnString)
End Function
|
|
|
|
|

|
Instead of using SMO since there are DLL problems if Sql server isn't installed on the machine you can use SqlDataSourceEnumerator
DataTable dt = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources();
foreach (System.Data.DataRow row in dt.Rows)
{
string serverName = row["servername"] as string;
string serverInstance = row["instancename"] as string;
}
there are more things you can get like the version number as well.
Enjoy.
|
|
|
|

|
I have an instance of SQL Server 2005 running on my own machine (where I ran this code snippet) and it shows all other SQL servers on our network except the one on localhost. Any ideas?
http://www.PanamaSights.com/
http://www.coralys.com/
http://www.virtual-aviation.info/
|
|
|
|

|
Check if the following services are enabled and running locally:
Computer Browser
Server
Sql Browser
Greetz....
|
|
|
|

|
Thx. This was just what I needed. I tried using SMO but it wouldn't see another machine on my network as the guest account is turned off. While trying to solve this I found your post which seemed better than SMO to me for discovering SQL servers.
Thx Again!
Penguin power
|
|
|
|

|
Is there something wrong with SqlDataSourceEnumerator.Instance.GetDataSources()? why not just use that?
|
|
|
|

|
First of all, great work. This code helped me a lot.
I used your code, and then modified it as "Member 1053820" had posted to make sure I had all of the instances of SQL Server in my list. Then I worked on getting the IP Address to correctly function instead of being null.
I came up with the following fix to the Address Public Property.
|
|
|
|

|
First I added new fields: Collation and Authentication Mode, couse, well, I needed them.
private string oCollation;
private string oAuthMode;
then I made public properties for them:
Then I modified TestConnection() method to use native connection provider and to get collation and authentication mode while testing the connection:
public bool TestConnection()
{
SqlConnection conn = this.GetConnection();
bool success = false;
try
{
conn.Open();
SqlCommand command = new SqlCommand("SELECT CONVERT (varchar, SERVERPROPERTY('collation'))");
command.Connection = conn;
oCollation = (string)command.ExecuteScalar();
command.CommandText = "SELECT CONVERT (int, SERVERPROPERTY('IsIntegratedSecurityOnly'))";
switch ((int)command.ExecuteScalar())
{
case 1: oAuthMode = "Windows only"; break;
case 0: oAuthMode = "Mixed mode"; break;
default: oAuthMode = "Greska"; break;
}
conn.Close();
success = true;
}
catch { }
return success;
}
and GetConnection():
private SqlConnection GetConnection()
{
string myConnString = this.IntegratedSecurity ?
String.Format("Data Source={0};Integrated Security=SSPI;Connect Timeout={1}", this, this.TimeOut)
: String.Format("Data Source={0};User Id={1};Password={2};Connect Timeout={3}",
this, this.UserId, this.Password, this.TimeOut);
return new SqlConnection(myConnString);
}
I also changed Seek method because there was this thing where test machine had two instances default and named and they were returned in same string, well it may not be the most elegant of solutions, but it works.
static public SqlServerInfo[] Seek()
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.EnableBroadcast = true; socket.ReceiveTimeout = 3000;
ArrayList servers = new ArrayList();
try
{
byte[] msg = new byte[] { 0x02 };
IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 1434);
socket.SendTo(msg, ep);
int cnt = 0;
byte[] bytBuffer = new byte[1024];
do
{
cnt = socket.Receive(bytBuffer);
servers.Add(new SqlServerInfo(null, bytBuffer));
string info = System.Text.ASCIIEncoding.ASCII.GetString(bytBuffer, 3, BitConverter.ToInt16(bytBuffer, 1));
if (info.Contains(";;") & (info.Length > info.IndexOf(";;") + 12))
{
if (info.Substring(info.IndexOf(";;") + 2, 10).ToLowerInvariant().Equals("servername"))
{
info = info.Substring(info.IndexOf(";;") + 2);
servers.Add(new SqlServerInfo(null, info));
}
}
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 300);
} while (cnt != 0);
}
catch (SocketException socex)
{
const int WSAETIMEDOUT = 10060; const int WSAEHOSTUNREACH = 10065;
if (socex.ErrorCode == WSAETIMEDOUT || socex.ErrorCode == WSAEHOSTUNREACH)
{
}
else
{
throw;
}
}
finally
{
socket.Close();
}
SqlServerInfo[] aServers = new SqlServerInfo[servers.Count];
servers.CopyTo(aServers);
return aServers;
}
|
|
|
|

|
You can also use:
DataTable availableServers;
DataTable availableLocalServers;
availableServers = SmoApplication.EnumAvailableSqlServers(false); // local and Network SQL instances
availableLocalServers = SmoApplication.EnumAvailableSqlServers(true); // only local SQL instances
enjoy.
|
|
|
|

|
SMO is not all fun and games, it fails to find all servers, it fails to work unless you include some dlls which are version specific, in a word: It worked slow but reliable on development machine but it had problems on some test machines, and you need to create an installer, you can't just use .exe file because of aforementioned dlls.
|
|
|
|

|
Hi,
It identifies the local server in the first loop and when it receives in the second loop it gets an exception ofTime out,. Please help me
|
|
|
|

|
Anyone else getting the issue where this times out every time? I am not getting any servers to respond. Thank you.
- G
static void Main(string[] args)
{
// Many thanks to CodeProject and James Curran
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.EnableBroadcast = true;
socket.ReceiveTimeout = 30000;
List<string> servers = new List<string>();
try
{
byte[] msg = new byte[] { 0x02 };
IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 1434);
socket.SendTo(msg, ep);
int count = 0;
byte[] buffer = new byte[1024];
do
{
count = socket.Receive(buffer);
Console.WriteLine(count);
Console.WriteLine(buffer.ToString());
socket.ReceiveTimeout = 30000;
} while (count != 0);
}
catch(SocketException ex)
{
const int WSAETIMEDOUT = 10060; // Connection timed out.
const int WSAEHOSTUNREACH = 10065; // No route to host.
Console.WriteLine("ErrorCode: " + ex.ErrorCode);
// Re-throw if it's not a defined exception
if (ex.ErrorCode == WSAETIMEDOUT || ex.ErrorCode == WSAEHOSTUNREACH)
{
// DO nothing......
}
else
{
throw;
}
}
finally
{
socket.Close();
}
Console.ReadLine();
}
|
|
|
|

|
hey
me too got time out exception. But not in the first time. The loop executes once. but it goes for second time it throws an exception. Any solution please!
|
|
|
|

|
I had the same issue, I was working from home at the time but once I was back in the office it worked, it was down to the vpn software blocking the port I needed, so you might want to check that nothing is blocking that port i.e. vpn, fireware etc.
|
|
|
|

|
Hi
I am facing a problem, the code doesn't return anything if the network is disabled, though there are local instances.
|
|
|
|

|
Can you help me to get the list of all the terminals connected into the network..
I want all the hosts connected to the network.
Thank you in advance.
-Preeti
|
|
|
|

|
Very good article.
As I understand, WMI is meant to deliver exactly this kind information.
I was just curious to know if you have experience in using WMI for such purposes, and its pros & cons?
Shrirang
|
|
|
|

|
I'm not an expert on WMI, but as I understand it, you would have to get a list of computers on the network, and then use WMI to ask each indivdually if they had an sql server running.
Truth,
James
|
|
|
|

|
Hi James
Great arcticle.
I have one doubt about fetching the list of running msde instances through c#.
I have 3 instances of MSDE installed on my machine say for example
MACHINE11\DBSTORAGE1
MACHINE11\DBSTORAGE2
MACHINE11\DBSTORAGE3
Now through c# using SMO or SQL DMO when I retreive the list of sql server instances, I get only the default instance. How can I get the list of named instances like above.
Can you pls help me with this.
Rajesh
|
|
|
|

|
The code is great.
The drawback is that it does not discover SQL Servers not having TCP protocol enabled...
Are there any other known methods for finding them? (note that sql service manager sees them)...
|
|
|
|

|
How about to use registry to look up last connected servers in Sql Server Enterprise Manager ?
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib\LastConnect
Left Side of the "||" represents name section
Right Side of the "||" represents data section
There are 4 entries in the registry field ;
NAME || DATA
------ --------
1-(local) || -33423352:lpc:BADOLAPTOP
-----------------------------------------------
2-BADOLAPTOP || -33423352:lpc:BADOLAPTOP - Local MSDE database with machine name(so its servername is default)
-----------------------------------------------
3-MUHASEBE\LOKAL || -150536184:tcp:MUHASEBE,1433 - Remote DB with machine name (MUHASEBE) and "LOKAL" = SERVER NAME
------------------------------------------------
4-BADOLAPTOP\TEKNOIN || -150536184:lpc:BADOLAPTOP\TEKNOIN - Local DB with machine name (BADOLAPTOP) AND Server Name (TEKNOIN)
------------------------------------------------
So , could it take us any easy solution ?
(Frankly , I'm too lazy to implement any solution.If somebody is interested , please let me know.)
Imo , there could be some security issues regarding to read the reg
Bado.
-- modified at 9:16 Wednesday 7th June, 2006
|
|
|
|

|
I didnt want to use SQLDMO and couldnt use .net2.0 SqlDataSourceEnumeratorm so I was using SQLInfoEnumerator. Unfortunately it was unable to detect some specific servers (even if there were only 4 servers totally), so I was thinking about broadcasting udp manually, but too lazy to sniff with Ethereal
Many thanks!!!
Tonos
|
|
|
|

|
I always time out after 3000 ms no mater what i set as timeout. Why??
I have tried this in VS2003 and VS2005..
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100000);
// For .Net v 2.0 it's a bit simpler
//socket.EnableBroadcast = true; // for .Net v2.0
//socket.ReceiveTimeout = 1000000; // for .Net v2.0
|
|
|
|

|
This does excactly the same but using UdpClient. Where I dont get the Timeout excetion. But i sill finds only 71 of the 136 sql servers on the network..
public static ArrayList UdpClient()
{
UdpClient client = new UdpClient();
byte[] msg = new byte[] { 0x02 };
client.MulticastLoopback = true;
client.EnableBroadcast = true;
client.DontFragment = true;
IPEndPoint serverEndpoint = new IPEndPoint(IPAddress.Broadcast,1434);
client.Send(msg, msg.Length, serverEndpoint);
ArrayList lst = new ArrayList();
while(client.Available>0)
{
IPEndPoint from = new IPEndPoint(IPAddress.Any,0);
byte[] revc = client.Receive(ref from);
String data = System.Text.ASCIIEncoding.ASCII.GetString(revc, 3, BitConverter.ToInt16(revc, 1));
lst.Add(data);
}
client.Close();
return lst;
}
|
|
|
|

|
Has anyone considered putting this "scan" for instances on a background thread that could watch for replys for an extended length of time. The timeout could then be set to anyting and the Receive would just be re-called over and over until you purposely tell the thread to stop looking.
As instances are found the thread would update it's list. It could hold a delegate or send events to notify interested code anytime a new instance was found. That way you could keep adding to a listbox/combobox as instances come in, but not stop the user from picking one if it is already found.
Better still kick off the search when the app first comes up, so that most if not all instances have been found before the user ever gets to the point where they need to pick.
This idea is almost a service held internally, but could be implemented as a real, though small, service where your app could use remoting calls to ask it for the list of instances.
I'm a bit busy on another project right now, but when I get back to the one that uses SQLServer lists I think I'll put some more thought into this and actually try something like this idea.
|
|
|
|

|
Hi, first of all thanx for your excellent work.
I've found that the reply parser is not able to detect multiple instances of sql server on the same machine.
I've modified your Seek procedure as follows below so that now is able to detect multiple instances.
Thanx again for your work.
static public SqlServerInfo[] DiscoveryAvailableServers() {
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
// For .Net v 2.0 it's a bit simpler
// socket.EnableBroadcast = true; // for .Net v2.0
// socket.ReceiveTimeout = 3000; // for .Net v2.0
ArrayList servers = new ArrayList();
try {
byte[] msg = new byte[] { 0x02 };
IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 1434);
socket.SendTo(msg, ep);
int cnt = 0;
byte[] bytBuffer = new byte[1024];
do {
cnt = socket.Receive(bytBuffer);
// *** MODIFIED ************************************************
string reply = ASCIIEncoding.ASCII.GetString(bytBuffer, 3, BitConverter.ToInt16(bytBuffer, 1));
int p;
int startIndex = 0;
do {
p = reply.IndexOf(";;", startIndex);
if (p > startIndex) {
servers.Add(new SqlServerInfo(null, reply.Substring(startIndex, p - startIndex)));
startIndex = p + 2;
}
} while (p >= 0);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 300);
} while (cnt != 0);
// ***************************************************
}
catch (SocketException socex) {
const int WSAETIMEDOUT = 10060; // Connection timed out.
const int WSAEHOSTUNREACH = 10065; // No route to host.
// Re-throw if it's not a timeout.
if (socex.ErrorCode == WSAETIMEDOUT || socex.ErrorCode == WSAEHOSTUNREACH) {
// DO nothing......
}
else {
// Console.WriteLine("{0} {1}", socex.ErrorCode, socex.Message);
throw;
}
}
finally {
socket.Close();
}
// Copy from the untyped but expandable ArrayList, to a
// type-safe but fixed array of SqlServerInfos.
SqlServerInfo[] aServers = new SqlServerInfo[servers.Count];
servers.CopyTo(aServers);
return aServers;
}
}
paco
|
|
|
|

|
Hi Paco
I tried implementing your change, but it lists the sql server instance but doesn't list any of the msde instance running on my machine. It gives me this error
Login failed for user ''. The user is not associated with a trusted SQL Server
connection.
I have one doubt about fetching the list of running msde instances through c#.
I have 3 instances of MSDE installed on my machine say for example
MACHINE11\DBSTORAGE1
MACHINE11\DBSTORAGE2
MACHINE11\DBSTORAGE3
Now through c# using SMO or SQL DMO when I retreive the list of sql server instances, I get only the default instance. How can I get the list of named instances like above.
Can you pls help me with this.
Rajesh
Rajesh
|
|
|
|

|
Nothing works in the case if VMWare vitrual network card is enabled. If it is disabled - everything works fine.
Who has the same problem and knows how to solve it?
|
|
|
|

|
How do you enumerate servers that the SQL Browser service is disabled?
When you run osql /L from the command prompt, you retrieve a list of servers that have the SQL Browser service set to enabled and disabled. Anyway to retrieve the complete list of servers (as per osql /L) using C# and without using odbc32.dll.
Mark H
|
|
|
|

|
Hey guys, I run msde2000 on the local lan and i keep getting 3 instances of the same database. what gives?
does MSDE2005 respond the same way?
|
|
|
|

|
is there something similar i coud use to discover oracle servers on the local network?
I'm sure it's a broadcast packet, again, i just don't have money right now to shell for a new computer to turn into an oracle box.
And as far as doing the same thing for MySQL, well, i'm sorry, guys, you can't at least not with the standard version of mysql. hmmmm good idea, an article about a MySQL heartbeat monitor in C# that responds to broadcast packets.
-><-
There is no spoon
|
|
|
|

|
I've been looking for a faster way to get the list of SQL Server for some time now, and I thought this was it. I'd tried to do this before, but didn't have a sniffer to figure it all out.
I implemented portions of your code to just pull out the list of the server names ... I don't need the rest in my app.
Your routines returned 4 at first, but 3 were identical. I discovered the identical ones were because my machine has VMWare Workstation installed so it has virtual networks all multi-homed to my NIC, so it reported my machine 3 times. I added code to weed out duplicates, so it then returned just 2 servers.
One minor complaint is it returns the machine name for the local server instead of "(local)".
The real problem is my current routine returns 4 different machines having servers. I tried changing the timeouts in your code all the way up to 10s, but it never found the others.
So I'm still using my existing calls for now ... which FYI once used SQLDMO, but quite some time ago I "upgraded" them to use ODBC because the ODBC DLLs ship with windows, and SQLDMO isn't always there, not to mention how slow it was.
For your reference the 2 machines not found on my network are both MSDE installations, that I can connect to and use with my app, and my current functions find, though they take a fair bit longer than yours. I'll include my current code below if you'd like to try it out and see if you can "sniff" what more it might be doing to find the opther two machines.
-- code below --
public static string[] MicrosoftSQLServers()
{
// This uses SQLDMO, which is a pig, must be installed
// onto the machine, and has to be called through Interop
// services because it is COM, so is slower yet!
//SQLDMO.Application sqlApp = new SQLDMO.ApplicationClass();
//SQLDMO.NameList sqlSvrs = sqlApp.ListAvailableSQLServers();
//sqlApp = null;
//
//string[] sqlServers = new string[sqlSvrs.Count];
//for( int srvNum=0; srvNum
/// 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
///
/// A valid string to query for
///
private static string[] RetrieveInformation( string InputParam )
{
IntPtr environmentHandle = IntPtr.Zero;
IntPtr connectionHandle = IntPtr.Zero;
StringBuilder inConnection = new StringBuilder( InputParam );
short stringLength= (short)inConnection.Length;
StringBuilder outConnection = new StringBuilder( DEFAULT_RESULT_SIZE );
short stringLength2Ptr= 0;
try
{
if( SQL_SUCCESS == SQLAllocHandle( SQL_HANDLE_ENV, environmentHandle, out
environmentHandle ) )
{
if( SQL_SUCCESS == SQLSetEnvAttr( environmentHandle,
SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0 ) )
{
if( SQL_SUCCESS == SQLAllocHandle( SQL_HANDLE_DBC,
environmentHandle, out connectionHandle ) )
{
if( SQL_NEED_DATA == SQLBrowseConnect(
connectionHandle, inConnection, stringLength, outConnection, DEFAULT_RESULT_SIZE, out stringLength2Ptr ) )
{
if( SQL_NEED_DATA != SQLBrowseConnect(
connectionHandle, inConnection, stringLength, outConnection, DEFAULT_RESULT_SIZE, out stringLength2Ptr ) )
{
return( null );
}
}
}
}
}
}
catch
{
return( null );
}
finally
{
FreeConnection( connectionHandle );
FreeConnection( environmentHandle );
}
if( outConnection.ToString() != "" )
return( ParseSQLOutConnection( outConnection.ToString() ) );
return( null );
}
///
/// Parse an outConnection string returned from SQLBrowseConnect
///
/// string to parse
///
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());
}
private static void FreeConnection(IntPtr handleToFree)
{
if(handleToFree!= IntPtr.Zero)
SQLFreeHandle(SQL_HANDLE_DBC,handleToFree);
}
#endregion
#endregion
|
|
|
|

|
Another interesting tidbit ... my local MSDE installation is on TCP port 1434 instead of the default for SQLServer (TCP port 1433) ... could a differnt port throw off the seek?
|
|
|
|

|
I tested the version of the class which I downloaded in a large corporate network environment. Using the osql /L command I got a list of nearly 100 SQL Servers. Usint this code the most I ever got was 3. The issue seems to be that the Receive() method times out on the 4th server. The question I have is how can I ever get around this failure? We issue a broadcast message presumably to all the SQL Servers on the network, and when the Receive() method times out on one of them, we're hosed? Anyone have another idea?
David Bradford
|
|
|
|

|
It's not clear to me from your reply if is was my code in my note or this project page's code that only returned 3 instances ... I don't have a Receive() method.
As far as other ideas go I have heard, but haven't been able to verify, that each instance of SQL Server will discover the others and that you can theoritically ask any instance that you can get to for a list of all those it knows about. I assume that would be fast, and as good a list as possible assuming the server you ask has been up for some time, which it normally would be in a production environment. Anyone ever see code to do this?
Another method that I used in the past was to ask the local system for the registered SQLServer instances. It only returns a list of instances that have been connected to at some time in the past, but it returns the list nearly instantly. It worked for me for a while because most people repeatedly use the same instances all the time, but eventually I had customers that were using my app that had never used anything to access SQL data before, and so they didn't know what to do to get to it ... ever since I've been implementing active looking for instances. Maybe a combination of these methods would be better yet.
|
|
|
|

|
I have a machine with two SQL Server instances (CORE and CORE\DEV) but the code only discovers one. Or at least it shows only one.
I think the bug may be in the parsing of the info sent by the machine:
ServerName;CORE;InstanceName;MSSQLSERVER;IsClustered;No;Version;
8.00.194;tcp;1433;;ServerName;CORE;InstanceName;DEV;IsClustered;No;Version;
8.00.194;np;\\CORE\pipe\MSSQL$DEV\sql\query;tcp;1533;;
You can see there are two instances here separated by two semicolons.
Thanks
-- modified at 6:05 Friday 2nd December, 2005
|
|
|
|

|
Just out of curiosity, do you get the same server list as from this piece of source (.NET 2.0)?:
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
if (factory.CanCreateDataSourceEnumerator)
{
foreach (DataRow row in factory.CreateDataSourceEnumerator().GetDataSources().Rows)
{
System.Diagnostics.Trace.WriteLine(row["ServerName"] + " " + row["InstanceName"]);
}
}
|
|
|
|

|
No, If you have many Sql servers on the network, like 60+ then this list is the most complete. This are the ways i have tested to recive servers.
1. The code in the article, times out after 3 secs no mater what. Which give you time ro recieve aprox 58 servers. (Yes i have changesd the timeout, but it dont work)
2. The ODBC retive of servers gives me an list, WHITOUT the instance names. and without some servers
3. This 2.0 code gives me the complete list With many of the instance names. Still some instancename is missing. Looks like all servers on the network is recieved here.
So far it liks like the last method is working best. To bad its only on .Net 2.0
|
|
|
|

|
What a fantastic bit of code. I have always hated having to code around SQL-DMO to acheive this and never realised it was so simple.
One suggestion; since we know that we are dealing with SQL Server; how about returning an SqlConnection object from GetConnection(...) instead of an OleDbConnection?
Person martin = new Person();
while (martin.Alive) {
martin.Code();
}
|
|
|
|

|
Because I need to call GetOleDbSchemaTable which is only defined in OleDbConnection.
When I create a .Net v2.0 version of this, I'll use the new GetSchema method, and then I return a SqlConnection (and make the method public)
Truth,
James
|
|
|
|

|
That is a fair point!
Person martin = new Person();
while (martin.Alive) {
martin.Code();
}
|
|
|
|

|
You don't _need_ to call GetOleDbSchema ...
To get the list of databases you can do this:
SqlCommand command = m_Connection.CreateCommand();
command.CommandText = "SELECT name FROM sysdatabases";
SqlDataReader dr = command.ExecuteReader();
ArrayList dbList = new ArrayList();
while( dr.Read() ) dbList.Add( dr.GetString(0) );
command.Dispose();
To get tables, columns, etc. use a query like this:
"SELECT * FROM Information_Schema.Tables WHERE Table_Type = 'BASE TABLE' OR Table_Type = 'VIEW'"
Just research 'Information_Schema' for details on how to use it!
|
|
|
|

|
James,
This looks great. It's interesting to see how this is done from the ground up. Nice job!
I was wondering if you've found this method of SQL Server discovery to provide an added benefit over using the SQLDMO COM object to locate servers on the network.
Thanks.
-Matt
------------------------------------------
The 3 great virtues of a programmer:
Laziness, Impatience, and Hubris.
--Larry Wall
|
|
|
|

|
Basically, just that we don't have to have the COM object around. You either have to cross your fingers and hope it's already installed, or install it yourself, and worry about registration and licensing etc.
Truth,
James
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
An article on locating MS SQL Server instances on the local network, and retrieving information about them.
| Type | Article |
| Licence | CPOL |
| First Posted | 24 Nov 2005 |
| Views | 192,132 |
| Bookmarked | 134 times |
|
|