484 lines
22 KiB
C#
484 lines
22 KiB
C#
#if SQLSERVER
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Data;
|
|
using System.Net;
|
|
using System.ServiceProcess;
|
|
|
|
namespace Sdaleo.Systems.SQLServer
|
|
{
|
|
#region SQLServer General Enums
|
|
|
|
/// <summary>
|
|
/// SQL Server Versions as specified by SQL Server
|
|
/// </summary>
|
|
public enum SQLServerVersion
|
|
{
|
|
SQL_SERVER_2000 = 80,
|
|
SQL_SERVER_2005 = 90,
|
|
SQL_SERVER_2008 = 100,
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// General SQL Server Functions
|
|
/// </summary>
|
|
public class SQLServerGeneral
|
|
{
|
|
#region SQL Version Functions
|
|
|
|
/// <summary>
|
|
/// Retrieves the SQL Server Version Information from the specified SQL Server Instance
|
|
/// (* Prefered Function to use *)
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="version">we pass out the SQL Server Specific Version</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError GetSQLServerVersion(IConnectDb credential, out SQLServerVersion version)
|
|
{
|
|
version = SQLServerVersion.SQL_SERVER_2000; // Default behavior
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
int nVersion = (int)SQLServerVersion.SQL_SERVER_2000;
|
|
DBError dberror = GetSQLServerVersion(credential, out nVersion);
|
|
if (dberror.ErrorOccured)
|
|
return dberror;
|
|
|
|
// SQLServerVersion numbers are multiple of 10's
|
|
nVersion = nVersion * 10;
|
|
try
|
|
{
|
|
version = (SQLServerVersion)Enum.Parse(typeof(SQLServerVersion), nVersion.ToString());
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
dberror = DBError.Create(e.Message);
|
|
}
|
|
return dberror;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the SQL Server Version String Information from the specified SQL Server Instance
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="strVersion">we pass out the SQL Server Specific Version String</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError GetSQLServerVersion(IConnectDb credential, out string strVersion)
|
|
{
|
|
strVersion = string.Empty;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute the Query
|
|
string sql = "EXEC sp_server_info @attribute_id = 2";
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.FillDataTable(sql);
|
|
if (retVal.IsValid)
|
|
{
|
|
strVersion = retVal.GetDataTableRetVal().Rows[0]["attribute_value"].ToString();
|
|
strVersion.Replace("\t", ""); // remove tabs
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the SQL Server Version Integer Information from the specified SQL Server Instance
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="nVersion">we pass out the SQL Server Specific Version Int</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError GetSQLServerVersion(IConnectDb credential, out int nVersion)
|
|
{
|
|
nVersion = 0;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute the Query
|
|
string sql = "SELECT CONVERT(char(20), SERVERPROPERTY('ProductVersion'))";
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.ExecuteScalar(sql);
|
|
if(retVal.IsValid)
|
|
{
|
|
string strVersion = retVal.GetScalarRetVal();
|
|
String[] strVersionSplit = strVersion.Split('.');
|
|
int.TryParse(strVersionSplit[0], out nVersion);
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SQL File N' Disk functions
|
|
|
|
/// <summary>
|
|
/// Retrieves the default path for the SQL Server Instance or for the Database on the SQL Server.
|
|
/// Leave Database blank in the credential to find the default path for the Server.
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="DefaultPath">default path found or "" if not</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerDefaultPath(IConnectDb credential, out string DefaultPath)
|
|
{
|
|
DefaultPath = string.Empty;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Get the Path for the default Path for the Database if Specified
|
|
string sql = String.Empty;
|
|
if (credential.DBMS.IsDatabaseSetAndNonSystem)
|
|
sql = String.Format("SELECT filename FROM [{0}]..sysfiles", credential.DBMS.Database);
|
|
else
|
|
sql = "SELECT filename FROM master..sysfiles where [name]='master'";
|
|
|
|
// Execute the Query
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.ExecuteScalar(sql);
|
|
if ((retVal.IsValid) && !String.IsNullOrEmpty(retVal.GetScalarRetVal()))
|
|
{
|
|
string strResult = retVal.GetScalarRetVal();
|
|
int indx = strResult.LastIndexOf('\\');
|
|
if (indx >= 0)
|
|
strResult = strResult.Remove(indx);
|
|
DefaultPath = strResult;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function retries an array of the Fixed HardDrives/Disks that are available on the Server
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="fixedDisks">an array of all the fixed disk's drive letters (i.e. C), empty list, if error occured</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerFixedDisks(IConnectDb credential, out string[] fixedDisks)
|
|
{
|
|
fixedDisks = null;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute the Query
|
|
string sql = "EXEC master..xp_fixeddrives";
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.FillDataTable(sql);
|
|
List<String> retList = new List<String>();
|
|
if (retVal.IsValid)
|
|
{
|
|
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
|
|
retList.Add(row["drive"].ToString());
|
|
}
|
|
fixedDisks = retList.ToArray();
|
|
return retVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function retries an array of directories for the specified Path on the specified SQL Server
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="Path">a valid path that exists on the server, i.e. C:\Program Files</param>
|
|
/// <param name="Directories">an array of all directories found in the specified path, empty list if no directories found or if error occured</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerGetDirectoriesInPath(IConnectDb credential, string Path, out string[] Directories)
|
|
{
|
|
Directories = null;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute the Query
|
|
string sql = String.Format("EXEC master..xp_dirtree '{0}', 1, 1", Path);
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.FillDataTable(sql);
|
|
List<String> retList = new List<String>();
|
|
if (retVal.IsValid)
|
|
{
|
|
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
|
|
{
|
|
bool bIsDirectory = (row["file"].ToString() == "0");
|
|
if (bIsDirectory)
|
|
retList.Add(row["subdirectory"].ToString());
|
|
}
|
|
}
|
|
Directories = retList.ToArray();
|
|
return retVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Function retries an array of files for the specified Path on the specified SQL Server
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="Path">a valid path that exists on the server, i.e. C:\Program Files</param>
|
|
/// <param name="Files">an array of all files found in the specified path, empty list if no files found or if error occured</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerGetFilesInPath(IConnectDb credential, string Path, out string[] Files)
|
|
{
|
|
Files = null;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute the Query
|
|
string sql = String.Format("EXEC master..xp_dirtree '{0}', 1, 1", Path);
|
|
DB db = DB.Create(credential.DBMS.WithoutDatabase());
|
|
DBRetVal retVal = db.FillDataTable(sql);
|
|
List<String> retList = new List<String>();
|
|
if (retVal.IsValid)
|
|
{
|
|
foreach (DataRow row in retVal.GetDataTableRetVal().Rows)
|
|
{
|
|
bool bIsFile = (row["file"].ToString() == "1");
|
|
if (bIsFile)
|
|
retList.Add(row["subdirectory"].ToString());
|
|
}
|
|
}
|
|
Files = retList.ToArray();
|
|
return retVal;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SQL Connection Checkers
|
|
|
|
/// <summary>
|
|
/// Quick Check function to see if the passed in credential allows us to connect to the server
|
|
/// If Credential contains a Database, then it will verify the Database's Existence
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="nConnectionTimeout">Specify the ConnectionTimout</param>
|
|
/// <param name="CanConnect">Returns true if successfull in connecting to the server</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerCheckConnection(IConnectDb credential, uint nConnectionTimeout, out bool CanConnect)
|
|
{
|
|
// the SQL Server should at least have a master db, so this list should never be empty,
|
|
// if it is, an error must have occured, either with the credential or with the server
|
|
CanConnect = false;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
// Execute Query
|
|
string[] Databases = null;
|
|
DBError dberror = SQLServerDatabase.DatabasesListAll(credential.DBMS.WithoutDatabase().Timeouts.WithConnectionTimeout(nConnectionTimeout), out Databases);
|
|
if (dberror.ErrorOccured || (Databases == null) || (Databases.Length == 0))
|
|
CanConnect = false;
|
|
else
|
|
CanConnect = true;
|
|
|
|
// Check Database Existence, if specified
|
|
if (CanConnect)
|
|
{
|
|
dbError = Validation.IsValidDatabaseName(credential.DBMS.Database);
|
|
if (!dberror.ErrorOccured)
|
|
{
|
|
// Verify that the Database exists
|
|
bool bFound = false;
|
|
foreach (string db in Databases)
|
|
{
|
|
if (db.ToUpper() == credential.DBMS.Database.ToUpper())
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Let the Caller know if they can connect to the Database
|
|
CanConnect = bFound;
|
|
}
|
|
}
|
|
return dberror;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quick Check function to see if the passed in credential allows us to connect to the
|
|
/// server, read some data, as well as check SysAdmin Rights for the passed in Credential
|
|
/// If Credential contains a Database, then it will verify the Database's Existence
|
|
/// </summary>
|
|
/// <param name="credential">SQL Server Credentials</param>
|
|
/// <param name="nConnectionTimeout">Specify the ConnectionTimout</param>
|
|
/// <param name="IsValid">true, if passed in credential connects and is a sysadmin, false otherwise</param>
|
|
/// <returns>DBError Object with ErrorOccured, if error Occured</returns>
|
|
public static DBError SQLServerCheckConnectionNCredential(IConnectDb credential, uint nConnectionTimeout, out bool IsValid)
|
|
{
|
|
IsValid = false;
|
|
DBError dbError = ValidationConsts.IsCredentialValid(credential, DBSystem.SQL_SERVER);
|
|
if (dbError.ErrorOccured)
|
|
return dbError;
|
|
|
|
DBError dberror = SQLServerCheckConnection(credential, nConnectionTimeout, out IsValid);
|
|
if (dberror.ErrorOccured || !IsValid)
|
|
return dberror;
|
|
|
|
// Now also make sure that the credential is a SysAdmin
|
|
dberror = SQLServerSecurity.LoginIsSysAdmin(credential, credential.User, out IsValid);
|
|
return dberror;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SQL Browse
|
|
|
|
/// <summary>
|
|
/// Returns a array of any found valid SQL Server intances * Using the SQLBrowse Functionallity *
|
|
/// If SQLBrowse fails, will look in the Registry
|
|
/// This Function can take a long time, depending on the Network
|
|
/// </summary>
|
|
/// <returns>list of valid SQLServers or null if error occured</returns>
|
|
public static string[] SQLServerNamesAndInstaces()
|
|
{
|
|
// Call the SQL Browse Function
|
|
List<String> validSQLServerInstances = new List<string>();
|
|
string[] SQLServersRaw = SQLInfoEnumerator.EnumerateSQLServers();
|
|
foreach (string SQLServerRaw in SQLServersRaw)
|
|
{
|
|
// Target name is empty - so add any valid instances found
|
|
if (Validation.IsValidServerNameAndInstanceName(SQLServerRaw))
|
|
validSQLServerInstances.Add(SQLServerRaw);
|
|
}
|
|
|
|
// Last thing to try if EnumerateSQLServers() failed is to query the registry
|
|
// for all possible SQL Server Installations there * and return those *
|
|
if (validSQLServerInstances.Count == 0)
|
|
{
|
|
string strInstalledInstances = RegKey.GetKey<string>(HKEYRoot.LocalMachine, "Microsoft\\Microsoft SQL Server", "InstalledInstances", String.Empty);
|
|
if (!String.IsNullOrEmpty(strInstalledInstances))
|
|
{
|
|
string MachineName = Dns.GetHostName();
|
|
// Add any Registry Found Instances
|
|
string[] Instances = strInstalledInstances.Split(' ');
|
|
foreach (string Instance in Instances)
|
|
validSQLServerInstances.Add(MachineName + "\\" + Instance);
|
|
}
|
|
}
|
|
return validSQLServerInstances.ToArray();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SQL Service Functions
|
|
|
|
/// <summary>
|
|
/// Use this to start a SQL Service on the specified Server. You must have Windows admin/SController rights to
|
|
/// that machine in order for this function to work
|
|
/// </summary>
|
|
/// <param name="ServerOrServerNInstance">Name of the SQL Server or SQL ServerNInstance you want to start (required)</param>
|
|
/// <param name="WaitTimeoutInSeconds">Set to Value > 0 to force a wait for the specified amount of seconds(not required)</param>
|
|
/// <returns>true if Service was started or was already running, false if an error occured</returns>
|
|
public static bool SQLServerServiceStart(string ServerOrServerNInstance, int WaitTimeoutInSeconds)
|
|
{
|
|
string Server = string.Empty;
|
|
string Instance = string.Empty;
|
|
if (String.IsNullOrEmpty(ServerOrServerNInstance))
|
|
return false;
|
|
|
|
if (!SQLServerUtilities.SplitServerOrServerNInstance(ServerOrServerNInstance, out Server, out Instance))
|
|
return false;
|
|
|
|
// Construct the proper service name
|
|
string Service = string.Empty;
|
|
if (!String.IsNullOrEmpty(Instance))
|
|
Service = String.Format("MSSQL${0}", Instance);
|
|
else
|
|
Service = "MSSQLSERVER";
|
|
|
|
string MachineName = Dns.GetHostName();
|
|
bool bIsOnThisMachine = (MachineName.ToLower() == Server.ToLower());
|
|
try
|
|
{
|
|
ServiceController service = null;
|
|
if (bIsOnThisMachine)
|
|
service = new ServiceController(Service);
|
|
else
|
|
service = new ServiceController(Service, Server);
|
|
|
|
bool bStartService = (service.Status != ServiceControllerStatus.Running);
|
|
if (bStartService)
|
|
{
|
|
service.Start();
|
|
if (WaitTimeoutInSeconds > 0)
|
|
{
|
|
TimeSpan timeout = TimeSpan.FromSeconds(WaitTimeoutInSeconds);
|
|
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
|
|
return (service.Status == ServiceControllerStatus.Running);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use this to stop a SQL Service on the specified Server. You must have Windows admin/SController rights to
|
|
/// that machine in order for this function to work
|
|
/// </summary>
|
|
/// <param name="ServerOrServerNInstance">Name of the SQL Server or SQL ServerNInstance you want to stop (required)</param>
|
|
/// <param name="WaitTimeoutInSeconds">Set to Value > 0 to force a wait for the specified amount of seconds(not required)</param>
|
|
/// <returns>true if Service was stopped or was already stopped, false if an error occured</returns>
|
|
public static bool SQLServerServiceStop(string ServerOrServerNInstance, int WaitTimeoutInSeconds)
|
|
{
|
|
string Server = string.Empty;
|
|
string Instance = string.Empty;
|
|
if (String.IsNullOrEmpty(ServerOrServerNInstance))
|
|
return false;
|
|
|
|
if (!SQLServerUtilities.SplitServerOrServerNInstance(ServerOrServerNInstance, out Server, out Instance))
|
|
return false;
|
|
|
|
// Construct the proper service name
|
|
string Service = string.Empty;
|
|
if (!String.IsNullOrEmpty(Instance))
|
|
Service = String.Format("MSSQL${0}", Instance);
|
|
else
|
|
Service = "MSSQLSERVER";
|
|
|
|
string MachineName = Dns.GetHostName();
|
|
bool bIsOnThisMachine = (MachineName.ToLower() == Server.ToLower());
|
|
try
|
|
{
|
|
ServiceController service = null;
|
|
if (bIsOnThisMachine)
|
|
service = new ServiceController(Service);
|
|
else
|
|
service = new ServiceController(Service, Server);
|
|
|
|
bool bStopService = (service.Status != ServiceControllerStatus.Stopped);
|
|
if (bStopService)
|
|
{
|
|
service.Stop();
|
|
if (WaitTimeoutInSeconds > 0)
|
|
{
|
|
TimeSpan timeout = TimeSpan.FromSeconds(WaitTimeoutInSeconds);
|
|
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
|
|
return (service.Status == ServiceControllerStatus.Stopped);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception) { /* ignore */ }
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use this to restart a SQL Service on the specified Server. You must have Windows admin/SController rights to
|
|
/// that machine in order for this function to work
|
|
/// </summary>
|
|
/// <param name="ServerOrServerNInstance">Name of the SQL Server or SQL ServerNInstance you want to restart (required)</param>
|
|
/// <param name="WaitTimeoutInSeconds">Set to Value > 0 to force a wait for the specified amount of seconds(not required)</param>
|
|
/// <returns>true if Service was restared successfully, false if an error occured</returns>
|
|
public static bool SQLServerServiceRestart(string ServerOrServerNInstance, int WaitTimeoutInSeconds)
|
|
{
|
|
return SQLServerServiceStop(ServerOrServerNInstance, WaitTimeoutInSeconds) && SQLServerServiceStart(ServerOrServerNInstance, WaitTimeoutInSeconds);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
#endif |