#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 /// /// SQL Server Versions as specified by SQL Server /// public enum SQLServerVersion { SQL_SERVER_2000 = 80, SQL_SERVER_2005 = 90, SQL_SERVER_2008 = 100, } #endregion /// /// General SQL Server Functions /// public class SQLServerGeneral { #region SQL Version Functions /// /// Retrieves the SQL Server Version Information from the specified SQL Server Instance /// (* Prefered Function to use *) /// /// SQL Server Credentials /// we pass out the SQL Server Specific Version /// DBError Object with ErrorOccured, if error Occured 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; } /// /// Retrieves the SQL Server Version String Information from the specified SQL Server Instance /// /// SQL Server Credentials /// we pass out the SQL Server Specific Version String /// DBError Object with ErrorOccured, if error Occured 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; } /// /// Retrieves the SQL Server Version Integer Information from the specified SQL Server Instance /// /// SQL Server Credentials /// we pass out the SQL Server Specific Version Int /// DBError Object with ErrorOccured, if error Occured 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 /// /// 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. /// /// SQL Server Credentials /// default path found or "" if not /// DBError Object with ErrorOccured, if error Occured 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; } /// /// Function retries an array of the Fixed HardDrives/Disks that are available on the Server /// /// SQL Server Credentials /// an array of all the fixed disk's drive letters (i.e. C), empty list, if error occured /// DBError Object with ErrorOccured, if error Occured 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 retList = new List(); if (retVal.IsValid) { foreach (DataRow row in retVal.GetDataTableRetVal().Rows) retList.Add(row["drive"].ToString()); } fixedDisks = retList.ToArray(); return retVal; } /// /// Function retries an array of directories for the specified Path on the specified SQL Server /// /// SQL Server Credentials /// a valid path that exists on the server, i.e. C:\Program Files /// an array of all directories found in the specified path, empty list if no directories found or if error occured /// DBError Object with ErrorOccured, if error Occured 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 retList = new List(); 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; } /// /// Function retries an array of files for the specified Path on the specified SQL Server /// /// SQL Server Credentials /// a valid path that exists on the server, i.e. C:\Program Files /// an array of all files found in the specified path, empty list if no files found or if error occured /// DBError Object with ErrorOccured, if error Occured 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 retList = new List(); 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 /// /// 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 /// /// SQL Server Credentials /// Specify the ConnectionTimout /// Returns true if successfull in connecting to the server /// DBError Object with ErrorOccured, if error Occured 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; } /// /// 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 /// /// SQL Server Credentials /// Specify the ConnectionTimout /// true, if passed in credential connects and is a sysadmin, false otherwise /// DBError Object with ErrorOccured, if error Occured 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 /// /// 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 /// /// list of valid SQLServers or null if error occured public static string[] SQLServerNamesAndInstaces() { // Call the SQL Browse Function List validSQLServerInstances = new List(); 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(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 /// /// 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 /// /// Name of the SQL Server or SQL ServerNInstance you want to start (required) /// Set to Value > 0 to force a wait for the specified amount of seconds(not required) /// true if Service was started or was already running, false if an error occured 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; } /// /// 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 /// /// Name of the SQL Server or SQL ServerNInstance you want to stop (required) /// Set to Value > 0 to force a wait for the specified amount of seconds(not required) /// true if Service was stopped or was already stopped, false if an error occured 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; } /// /// 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 /// /// Name of the SQL Server or SQL ServerNInstance you want to restart (required) /// Set to Value > 0 to force a wait for the specified amount of seconds(not required) /// true if Service was restared successfully, false if an error occured public static bool SQLServerServiceRestart(string ServerOrServerNInstance, int WaitTimeoutInSeconds) { return SQLServerServiceStop(ServerOrServerNInstance, WaitTimeoutInSeconds) && SQLServerServiceStart(ServerOrServerNInstance, WaitTimeoutInSeconds); } #endregion } } #endif