unit DataBaseOptionsComp;
interface
uses //使用到的包
SysUtils, Classes,DB,ADODB,Variants,ComObj,winsvc,Registry,Windows,Messages,Dialogs,IniOptionsComp;
//const //---常量定義
type
TDataBaseOptions = class(TComponent) //---定義組件,繼承於TComponen
private
//------------------- 屬性定義 ---------------------//
FADOConnection : TADOConnection ; //-- 操作的ADO對象
FIniOptions : TIniOptions ;
public
constructor Create(AOwner: TComponent); override; //-- 重寫create 方法,對屬性進行初始化
destructor Destroy; override; //-- 重寫Destroy 方法,釋放資源
//------------------- 功能方法定義-----------------------//
procedure SetADOConnection(const ADOConn:TADOConnection);
procedure SetIniOptions(const IniOps: TIniOptions);
Function ConnADO2DBServer:Boolean;
Function ConnADO2DataBase:Boolean;overload;
Function ConnADO2DataBase(DBName:string):Boolean;overload;
function ClearADOConn:Boolean;
Function GetLANSQLServerList:TStrings;
Function GetSqlServerStatus:Integer;
Function IsExistsMSSQL: Boolean;
Function StartMSSQL:Boolean;
function StopMSSQL:Boolean;
function GetDataBaseNameList:TStrings;
function AttachDataBase(DBName,DataBaseFilePath,LogFilePath:String):Boolean;
function DetachDataBase(DBName:string):Boolean;
function IsExistsDataBase(DBName:string):Boolean;
function IsExistsProcedure(DBName,procName:string):Boolean;
function DeleteProcedure(DBName,procName:string):Boolean;
function CreateSpKillProcOnMaster:Boolean;
function GetDBConnCount(DBName:string):Integer;
function DelDBConnCount(DBName:string):Boolean;
function BackUpDataBase(DBName,BackUpFilePath:String):boolean;
function RestoreDataBase(DBName,restoreFilePath:String):Boolean;
published
{ Published declarations }
//--- 對屬性值進行讀取和保存操作,如 Get和Set
property ADOConnection: TADOConnection read FADOConnection write SetADOConnection;
property IniOptions: TIniOptions read FIniOptions write SetIniOptions;
end;
procedure Register;
implementation
{ Property Access }
//-------------------- 對屬性值的存取方法 --------------------//
procedure TDataBaseOptions.SetADOConnection(const ADOConn:TADOConnection);
begin
FADOConnection := ADOConn;
//ShowMessage('setADOConection');
end;
procedure TDataBaseOptions.SetIniOptions(const IniOps: TIniOptions);
begin
FIniOptions := IniOps;
//ShowMessage('SetIniOptions');
if FIniOptions.AutoLogon then
begin
ConnADO2DataBase;
end;
end;
//------------------------------------------------------------//
constructor TDataBaseOptions.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
FADOConnection := TADOConnection.create(nil); //-- 初始化一個ADO對象
FIniOptions := TIniOptions.Create(nil);
ShowMessage('111create');
end;
destructor TDataBaseOptions.Destroy;
begin
ClearADOConn;
FADOConnection.Free;
FIniOptions.Free;
inherited Destroy;
end;
procedure Register;
begin
RegisterComponents('ADO', [TDataBaseOptions]);
end;
Function TDataBaseOptions.IsExistsMSSQL: Boolean;
//-------------------------------------------------------//
//------ IsExistsMSSQL 函數說明 ------//
//------ 函數作用:檢測是否安裝SQL Server ------//
//------ 返回值:true:已安裝 ; false :未安裝 ------//
//-------------------------------------------------------//
var
TmpReg: Tregistry;
begin
TmpReg := Tregistry.Create;
try
try
TmpReg.RootKey := HKEY_LOCAL_MACHINE;
if not TmpReg.OpenKey('Software\Microsoft\MSSQLServer\Setup', False) then
abort;
Result := (TmpReg.ReadString('SQLPath') <> '');
TmpReg.CloseKey;
except
Result := False;
end;
finally
TmpReg.Free;
end;
end;
{TODO:檢測SQLService服務的狀態。}
Function TDataBaseOptions.GetSqlServerStatus:Integer;
//-------------------------------------------------------//
//------ GetSqlServerStatus 函數說明 ------//
//------ 函數作用:檢測當前SQL Server服務器狀態 ------//
//------ 返回值: 0:服務器已關閉 ------//
//------ 1:服務器正在運行 2:服務器已暫停 ------//
//------ 3:服務器正在啓動(關閉-->啓動) ------//
//------ 4:服務器正在關閉.(啓動-->關閉) ------//
//------ 5:服務器正在繼續 (暫停-->啓動) ------//
//------ 6:服務器正在暫停 (啓動-->暫停) ------//
//-------------------------------------------------------//
var
ServiceStatus:Integer;
SrvHandle: SC_HANDLE; //這些都在winsvc單元中定義的
Service_Status: _SERVICE_STATUS; //在winsvc單元中有定義
SrvStatus: Integer;
begin
ServiceStatus := -1 ;
//取sql server的狀態,如果sql server正在運行則返回true ,否則返回 false
SrvHandle := OpenSCManager('', SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);
SrvHandle := OpenService(SrvHandle, PChar('MSSQLServer'), SERVICE_QUERY_STATUS or SERVICE_START);
if QueryServiceStatus(SrvHandle,Service_Status) then
begin
//判斷Sql Server服務的狀態
SrvStatus := Service_Status.dwCurrentState;
case SrvStatus of
SERVICE_STOPPED: ServiceStatus := 0; //服務器已關閉
SERVICE_RUNNING: ServiceStatus := 1; //服務器正在運行
SERVICE_PAUSED: ServiceStatus := 2; // 服務器已暫停
SERVICE_START_PENDING: ServiceStatus := 3; //服務器正在啓動(關閉-->啓動)
SERVICE_STOP_PENDING: ServiceStatus := 4; //服務器正在關閉.(啓動-->關閉)
SERVICE_CONTINUE_PENDING: ServiceStatus := 5; //服務器正在繼續 (暫停-->啓動)
SERVICE_PAUSE_PENDING: ServiceStatus := 6; //服務器正在暫停 (啓動-->暫停)
end;
end ;
result := ServiceStatus ;
end;
function TDataBaseOptions.StartMSSQL:Boolean;
//-------------------------------------------------------//
//------ StartMSSQL 函數說明 ------//
//------ 函數作用:啓動 SQL Server 服務器 ------//
//------ 返回值:true:啓動成功 ;false :啓動失敗 ------//
//-------------------------------------------------------//
const
MSSQL_98StartCommand = 'scm -action 1 -pwd "%s "';
MSSQL_NTStartCommand = 'net start mssqlserver';
var
cmdCom:string;
Pass:string;
begin
Pass := '';
if not ((Win32MajorVersion >= 4) and (Win32Platform = VER_PLATFORM_WIN32_NT)) then
cmdCom := Format(MSSQL_98StartCommand,[Pass])
else
cmdCom := MSSQL_NTStartCommand;
try
WinExec(PChar(cmdCom),SW_HIDE);
Result := True;
except
Result := False;
end;
end;
function TDataBaseOptions.StopMSSQL:Boolean;
//-------------------------------------------------------//
//------ StopMSSQL 函數說明 ------//
//------ 函數作用:關閉 SQL Server 服務器 ------//
//------ 返回值:true:關閉成功 ;false :關閉失敗 ------//
//------ 如果當前服務器未啓動,返回true ------//
//-------------------------------------------------------//
const
MSSQL_98StopCommand = 'scm -action 6';
MSSQL_NTStopCommand = 'net stop mssqlserver';
begin
try
if not ((Win32MajorVersion >= 4) and (Win32Platform = VER_PLATFORM_WIN32_NT)) then
WinExec(MSSQL_98StopCommand,SW_HIDE)
else
WinExec(MSSQL_NTStopCommand,SW_HIDE);
Result := True;
except
Result := False;
end;
end;
Function TDataBaseOptions.ConnADO2DBServer:Boolean;
//-------------------------------------------------------//
//------ ConnADO2DBServer 函數說明 ------//
//------ 函數作用:連接 SQL Server 服務器 ------//
//------ 返回值:true:連接成功 ;false :連接失敗 ------//
//------ 如果當前服務器未啓動,返回false ------//
//-------------------------------------------------------//
begin
if GetSqlServerStatus=1 then
begin
with FADOConnection do
begin
Connected:=false;
ShowMessage('22');
if (FIniOptions.AuthenticateBySQLServer) then
ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,FIniOptions.ServerName])
else
ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Data Source=%s',[FIniOptions.ServerName]);
try
Connected:=true;
result := True;
except
ConnectionString := '';
Connected:=false;
result := false;
end;
end;
end
else
Result := false;
end;
Function TDataBaseOptions.ConnADO2DataBase:Boolean;
//-------------------------------------------------------//
//------ ConnADO2DataBase 函數說明 ------//
//------ 函數作用:連接SQL Server服務器上的數據庫 ------//
//------ 根據屬性FDataBaseName的值去連接 ------//
//------ 返回值:true:連接成功 ;false :連接失敗 ------//
//------ 如果當前服務器未啓動,返回false ------//
//-------------------------------------------------------//
begin
if GetSqlServerStatus=1 then
begin
if ConnADO2DBServer then
begin
with FADOConnection do
begin
Connected:=false;
if( FIniOptions.AuthenticateBySQLServer )then
ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Initial Catalog=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,FIniOptions.DataBaseName,FIniOptions.ServerName])
else
ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=%s;Data Source=%s',[FIniOptions.DataBaseName,FIniOptions.ServerName]);
try
Connected:=true;
result := True;
except
ConnectionString := '';
Connected:=false;
result := false;
end;
end;
end
else Result := False;
end
else Result := false;
end;
Function TDataBaseOptions.ConnADO2DataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------ ConnADO2DataBase 函數說明 ------//
//------ 函數作用:連接SQL Server服務器上的數據庫 ------//
//------ 根據傳入的參數:DBName 去連接 ------//
//------ 返回值:true:連接成功 ;false :連接失敗 ------//
//------ 如果當前服務器未啓動,返回false ------//
//-------------------------------------------------------//
begin
if GetSqlServerStatus=1 then
begin
if ConnADO2DBServer then
begin
with FADOConnection do
begin
Connected:=false;
if(FIniOptions.AuthenticateBySQLServer)then
ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Initial Catalog=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,DBName,FIniOptions.ServerName])
else
ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=%s;Data Source=%s',[DBName,FIniOptions.ServerName]);
try
Connected:=true;
result := True;
except
ConnectionString := '';
Connected:=false;
result := false;
end;
end;
end
else Result := False;
end
else Result := false;
end;
function TDataBaseOptions.ClearADOConn:Boolean;
//-------------------------------------------------------//
//------ ClearADOConn 函數說明 ------//
//------ 函數作用:斷開並清除FADOConnection的連接 ------//
//------ 返回值:true:清除成功 ;false :清除失敗 ------//
//------ 如果當前ADO正處於連接狀態,則先關閉 ------//
//-------------------------------------------------------//
begin
with FADOConnection do
begin
if connected then
begin
try
connected := False;
ConnectionString := '';
result := true;
except
result := False;
end;
end
else
begin
ConnectionString := '';
result := True;
end;
end;
end;
Function TDataBaseOptions.GetLANSQLServerList:TStrings;
//-------------------------------------------------------//
//------ GetLANSQLServerList 函數說明 ------//
//------ 函數作用:獲取局域網SQL Server服務器列表 ------//
//------ 返回值:SQL Server服務器名稱列表 ------//
//------ (有時無法獲取本機的服務器名稱) ------//
//-------------------------------------------------------//
var
SQLServerObject,ServerList:Variant;
i,nServers:integer;
SQLServersName:TStrings;
begin
SQLServersName := tstringlist.Create;
try
SQLServerObject := CreateOleObject('SQLDMO.Application');
ServerList := SQLServerObject.ListAvailableSQLServers;
nServers:=ServerList.Count;
for i := 1 to nservers do
begin
SQLServersName.Add(ServerList.Item(i));
end;
finally
SQLServerObject:=Unassigned;
serverList:=Unassigned;
end;
Result := SQLServersName;
end;
function TDataBaseOptions.GetDataBaseNameList:TStrings;
//-------------------------------------------------------//
//------ GetDataBaseNameList 函數說明 ------//
//------ 函數作用:獲取服務器上的數據庫列表 ------//
//------ 返回值:數據庫名稱列表 ------//
//------ 先連接服務器,再獲取數據庫列表 ------//
//-------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
DataBaseNameList:TStrings;
begin
DataBaseNameList := TStringlist.Create;
if ConnADO2DBServer then
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
with adoQ_temp do
begin
Close;
SQL.Clear;
SQL.Add(' select name from master..sysdatabases');
try
Open;
while not Eof do
begin
DataBaseNameList.Add(Fields[0].AsString);
Next;
end;
finally
free;
result := DataBaseNameList;
end;
end;
end
else Result := DataBaseNameList;
end;
function TDataBaseOptions.AttachDataBase(DBName,DataBaseFilePath,LogFilePath:String):Boolean;
//-------------------------------------------------------//
//------ AttachDataBase 函數說明 ------//
//------ 函數作用:附加指定路徑,指定名稱的數據庫 ------//
//------ 返回值:是否附加成功 ------//
//------ 先連接服務器,再附加數據庫 ------//
//-------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
SQL.Add(format('EXEC sp_attach_db ''%s'' , ''%s'' , ''%s''',[DBName,DataBaseFilePath,LogFilePath]));
try
execsql;
result := true;
except
result := false;
end;
Free;
end;
end
else result := False;
end;
function TDataBaseOptions.DetachDataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------ DetachDataBase 函數說明 ------//
//------ 函數作用:分離指定名稱的數據庫 ------//
//------ 返回值:是否分離成功 ------//
//------ 先連接服務器,然後清楚數據庫存在的 ------//
//------ 連接,再附加數據庫 ------//
//-------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
if DelDBConnCount(DBName) then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
SQL.Add(format('exec sp_detach_db ''%s''',[DBName]));
try
execsql;
result := true;
except
result := false;
end;
Free;
end;
end
else result := False;
end
else result := False;
end;
function TDataBaseOptions.IsExistsDataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------ IsExistsDataBase 函數說明 ------//
//------ 函數作用:判斷指定名稱的數據庫是否存在 ------//
//------ 返回值:存在爲true,不存在爲false ------//
//------ 先連接服務器,再判斷數據庫是否存在 ------//
//-------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add('use master;');
sql.add(format('select count(name) as DB_Count from sysdatabases where name=''%s''',[DBName]));
try
open;
if (FieldByName('DB_Count').Value) then
result := True
else
result := False;
except
result := false;
end;
Free;
end;
end
else result := False;
end;
function TDataBaseOptions.IsExistsProcedure(DBName,procName:string):Boolean;
//---------------------------------------------------------------------//
//------ IsExistsProcedure 函數說明 ------//
//------ 函數作用:判斷指定數據庫上是否存在指定的存儲過程 ------//
//------ 返回值:存在爲true,不存在爲false ------//
//------ 先連接服務器,再判斷存儲過程是否存在 ------//
//---------------------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add(format('use %s;',[DBName]));
sql.add('select * from sysobjects');
sql.add(format(' where id = object_id(N''[%s]'') ',[procName]));
sql.add('and OBJECTPROPERTY(id, N''IsProcedure'') = 1 ');
try
open;
if not EOF then
result := True
else
result := False;
except
result := false;
end;
Free;
end;
end
else result := False;
end;
function TDataBaseOptions.DeleteProcedure(DBName,procName:string):Boolean;
//---------------------------------------------------------------------//
//------ DeleteProcedure 函數說明 ------//
//------ 函數作用:刪除指定數據庫上指定的存儲過程 ------//
//------ 返回值:刪除成功爲true,不成功爲false ------//
//------ 先連接服務器,再判斷存儲過程是否存在,存在再刪除 ------//
//---------------------------------------------------------------------//
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
if IsExistsProcedure(DBName,procName) then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add(format('use %s;',[DBName]));
sql.add(format('drop procedure %s',[procName]));
try
execsql;
result := true;
except
result := false;
end;
Free;
end;
end
else result := false;
end
else result := False;
end;
function TDataBaseOptions.CreateSpKillProcOnMaster:Boolean;
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add('use master;');
try
ExecSQL;
except
result := false;
end;
SQL.Clear;
sql.add('create procedure sp_kill_processes(@dbname varchar(100))');
sql.add('as begin ');
sql.add(' declare @pro_kill nvarchar(255) ');
sql.add(' declare tasklist_cursor cursor for select ''kill '' + ');
sql.add(' convert(varchar(5),spid) + '' -- '' + p.loginame ');
sql.add(' from sysprocesses p,sysdatabases d ');
sql.add(' where p.dbid = d.dbid and d.name = @dbname ');
sql.add(' open tasklist_cursor ');
sql.add(' fetch next from tasklist_cursor into @pro_kill ');
sql.add(' while(@@fetch_status = 0) ');
sql.add(' begin ');
sql.add(' exec(@pro_kill) ');
sql.add(' if(@@error <> 0) return 0 ');
sql.add(' fetch next from tasklist_cursor into @pro_kill ');
sql.add(' end ');
sql.add(' close tasklist_cursor ');
sql.add(' deallocate tasklist_cursor ');
sql.add(' return 1 ');
sql.add('end ');
try
execsql;
result := true;
except
result := false;
end;
free;
end;
end
else result := False;
end;
function TDataBaseOptions.GetDBConnCount(DBName:string):Integer;
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add('use master;');
sql.Add('select count(*) as connCount');
sql.Add('from [master].[dbo].[sysprocesses]');
sql.Add('where dbid in ( select dbid from [master].[dbo].[sysdatabases]');
sql.Add(format('where name=''%s'')',[DBName]));
try
open;
result := FieldByName('connCount').Value ;
except
result := -1;
end;
Free;
end;
end
else result := -1;
end;
function TDataBaseOptions.DelDBConnCount(DBName:string):Boolean;
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
if not IsExistsProcedure('master','sp_kill_processes') then
begin
if not CreateSpKillProcOnMaster then
result := False;
end;
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.add('use master;');
sql.Add(format('exec [master].[dbo].[sp_kill_processes] %s',[DBName]));
try
execsql;
result := True ;
except
result := False;
end;
Free;
end;
end
else result := False;
end;
function TDataBaseOptions.BackUpDataBase(DBName,backUpFilePath:String):Boolean;
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if ConnADO2DBServer then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
sql.Add(format('backup database %s to disk=''%s''',[DBName,backUpFilePath]));
try
execsql;
result := True ;
except
result := False;
end;
Free;
end;
end
else result := False;
end;
function TDataBaseOptions.RestoreDataBase(DBName,restoreFilePath:String):Boolean;
var
adoQ_temp:TADOQuery ;
begin
adoQ_temp:= TADOQuery.Create(nil);
adoQ_temp.Connection := FADOConnection ;
if DelDBConnCount(DBName) then
begin
with adoQ_temp do
begin
Close;
SQL.Clear;
SQL.ADD('use master;');
SQL.ADD(format('restore database %s from disk=''%s''',[DBName,restoreFilePath]));
try
execsql;
result := True ;
except
result := False;
end;
Free;
end;
end
else result := false;
end;
end.