你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / 数据库开发
3.5 SQL Server 数据库应用程序的无值守部署
 

一、引言

软件部署是一个获得应用程序并将它安装到另一台机器上的过程,一般通过安装程序完成。一个项目完成之后,在软件交互发布前,安装程序的制作是一个必要的过程。由于Microsoft SQL Server 2000的低成本、可管理性和易维护性,现在很多数据库应用程序都是基于SQL Server 2000数据库平台运行的,但对于最终用户而言,部署SQL Server 2000数据库环境却是一件很复杂的事情,因此设计人员在安装打包时,应充分考虑不同用户使用相同的SQL Server 2000安装配置等情况,减少软件发布成本,实现软件部署的“傻瓜化”。

二、设计

在默认情况下,当使用SQL Server 2000的安装程序屏幕进行值守安装时,所指定的所有选项都被记录进安装程序初始化文件(setup.iss)中,该文件存放在系统根目录(%windir%)下,用于为以后提供安装设置。而通过调用程序执行该文件,即可实现SQL Server 2000的无值守安装,整个安装过程基本不需要用户的干预,在 MicrosoftSQL Server™ 2000 安装光盘中提供了示例的批处理文件(如Sqlins.bat)和安装程序初始化文件(如Sqlins.iss)。在安装完毕数据库后,就可通过SQL Serverosql.exe 实用工具执行Transact-SQL 语句、系统存储过程和脚本文件实现数据库实例的初始化。以下是具体的实施步骤:

1步:通过注册表判断SQL Server是否已经安装,如果已经安装,则启动服务器(第4步)。

2步:通过调用批处理文件等方式执行SQL Server的安装命令:setupsql.exe -s -m -SMS -f1 " setup.iss"

3步:建一个循环,通过进程来判断安装程序的结束,一旦结束则启动服务器(第4步)。

4步:通过进程或服务判断SQL Server服务是否已经启动,如果已经启动则配置数据库(第5步),否则调用sqlservr.exe程序或Windows服务启动服务。

5步:通过批处理文件等方式调用SQL Serverosql.exe命令执行外部SQL脚本文件(该文件通过调用“CREATE DATABASECREATE DEVICERESTORE DATABASE”等Transact-SQL语句和“sp_dropdevicesp_addumpdevicesp_attach_db”等系统存储过程,实现数据库初始数据文件与日志文件的导入),将初始的数据库附加到服务器上。

6步:建一个循环,通过进程来判断配置程序的结束,一旦结束则启动服务器,安装应用程序。

三、编码

设计人员需要把执行SQL Server安装命令的批处理文件setup.bat、经过值守安装后并记录在系统根目录(%windir%)的安装程序初始化文件setup.iss、数据库初始化文件MyInstance.mdf(假设数据库实例名为MyInstance)、应用系统安装文件Setup.exe一起发布至Microsoft SQL Server 2000安装根目录下。

其中setup.bat文件的内容为:

@echo on

start /wait x86\setup\setupsql.exe -s -m -SMS -f1 "setup.iss"

@echo off

1.功能实现的核心代码

//-从注册表中检索是否安装 Microsoft SQL Server 2000 数据库-///

procedure TForm1.FormCreate(Sender: TObject);

var

  Registry: TRegistry;

begin

  Registry := TRegistry.Create;

  Registry.RootKey := HKEY_LOCAL_MACHINE;

  if Registry.OpenKey('\SOFTWARE\Microsoft\MSSQLServer\Setup', False) then

    //-从注册表中检索是否安装 MyInstance 数据库实例-

if not FileExists(Registry.ReadString('SQLDataRoot') + '\Data\MyInstance_Data.mdf') then

      BitBtn2Click(nil);

  else//没有安装 Microsoft SQL Server 2000 数据库

    BitBtn1Click(nil);

  Registry.Free;

end;

///-安装 SQL Server 2000数据库-///

procedure TForm1.BitBtn1Click(Sender: TObject);

var

  sBatFileName: string;

  iWinExecAndWait32: Integer;

begin

  if Application.MessageBox('确认执行"安装 SQL Server 2000数据库"吗?', '提示', MB_YESNO + MB_ICONINFORMATION) = IDNO then

    Exit;

  //-生成调用osql.exe命令的批处理文件setup.bat'并等待其执行完毕-

  sBatFileName := ExtractFileDir(ParamStr(0)) + '\setup.bat';

  iWinExecAndWait32 := WinExecAndWait32(sBatFileName, SW_HIDE);

  if iWinExecAndWait32 = 0 then

  begin

    //-启动MSSQLSERVER服务并等待-

    RunService('MSSQLSERVER');

    Sleep(6000);

    Application.MessageBox('"安装 SQL Server 2000数据库"执行完毕!', '提示', MB_OK + MB_ICONINFORMATION);

    ///-配置 SQL Server 2000数据库-   

    BitBtn2Click(nil);

  end;

end;

///-配置 SQL Server 2000数据库-///

procedure TForm1.BitBtn2Click(Sender: TObject);

var

  Registry: TRegistry;

  sCrlf, sMdfFileName, sSQL, sDataInstallLocation: string;

  slSQL, slBAT: TStringList;

  iWinExecAndWait32: Integer;

begin

  if QueryServiceState('MSSQLSERVER') = 0 then

  begin

    if Application.MessageBox('确认执行"配置 SQL Server 2000数据库"吗?', '提示', MB_YESNO + MB_ICONINFORMATION) = IDNO then

      Exit;

    //-启动MSSQLSERVER服务并等待-

    if QueryServiceState('MSSQLSERVER') = 0 then

    begin

      RunService('MSSQLSERVER');

      Sleep(5000);

    end;

    ///-配置MyInstance数据库-///

    sCrlf := Chr(13) + Chr(10);

    sMdfFileName := ExtractFilePath(ParamStr(0)) + '\MyInstance.mdf';

    Registry := TRegistry.Create;

    Registry.RootKey := HKEY_LOCAL_MACHINE;

    Registry.OpenKey('\SOFTWARE\Microsoft\MSSQLServer\Setup', False);

    sDataInstallLocation := Registry.ReadString('SQLDataRoot') + '\Data\MyInstance_Data.mdf';

    Registry.Free;

    //-生成SQL文件,并保存临时文件-

    sSQL := 'USE master' + sCrlf +

           'if not exists (select * from sysdatabases where name=''MyInstance'')' + sCrlf +

           'CREATE DATABASE MyInstance' + sCrlf +

           'if exists (select * from sysdevices where name=''MyInstance'')' + sCrlf +

           'EXEC sp_dropdevice ''MyInstance''' + sCrlf +

           'EXEC sp_addumpdevice ''disk'', ''MyInstance'', ''' + sDataInstallLocation + '''' + sCrlf +

           'RESTORE DATABASE MyInstance' + sCrlf +

           'FROM DISK=''' + sMdfFileName + '''' + sCrlf +

           'WITH REPLACE';

    slSQL := TStringList.Create;

    slSQL.Add(sSQL);

    slSQL.SaveToFile('c:\temp1.sql');

    slSQL.Clear;

    //-生成并执行调用osql.exe命令的批处理文件-

    slBAT:= TStringList.Create;

    slBAT.Add('@echo off');

    slBAT.Add('osql.exe -E -S -i "c:\temp1.sql"' + ' -o "c:\result1.txt"');

    slBAT.Add('exit');

    slBAT.SaveToFile('c:\temp1.bat');

    slBAT.Clear;

    iWinExecAndWait32 := WinExecAndWait32('c:\temp1.bat', SW_HIDE);

    if iWinExecAndWait32 = 0 then

    begin

      Application.MessageBox('"配置 SQL Server 2000数据库"执行完毕!', '提示', MB_OK + MB_ICONINFORMATION);

      ///-安装 xxxxxxxxxx信息管理系统-

      BitBtn3Click(nil);

    end;

  end;

end;

///-安装 xxxxxxxxxx信息管理系统-///

procedure TForm1.BitBtn3Click(Sender: TObject);

var

  sExeFileName: string;

  iWinExecAndWait32: Integer;

begin

  if Application.MessageBox('确认执行"安装 xxxxxxxxxx信息管理系统"吗?', '提示', MB_YESNO + MB_ICONINFORMATION) = IDNO then

    Exit;

  //-执行系统安装程序-

  sExeFileName := ExtractFilePath(ParamStr(0)) + '\Setup.exe';

  iWinExecAndWait32 := WinExecAndWait32(sExeFileName, SW_SHOW);

  if iWinExecAndWait32 = 0 then

  begin

    Application.MessageBox('"安装 xxxxxxxxxx信息管理系统"执行完毕!', '提示', MB_OK + MB_ICONINFORMATION);

  end;

end;

2.调用的几个关键函数和过程的核心代码

///-执行一个外部程序并等待其执行结束-///

function WinExecAndWait32(FileName: string; Visibility: Integer): Cardinal;

var

  zAppName: array[0..512] of char;

  zCurDir: array[0..255] of char;

  WorkDir: string;

  StartupInfo: TStartupInfo;

  ProcessInfo: TProcessInformation;

  Msg: TagMsg;

  ExitCode: cardinal;

begin

  StrPCopy(zAppName, FileName);

  GetDir(0, WorkDir);

  StrPCopy(zCurDir, WorkDir);

  FillChar(StartupInfo, Sizeof(StartupInfo), #0);

  StartupInfo.cb := Sizeof(StartupInfo);

  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;

  StartupInfo.wShowWindow := Visibility;

  if CreateProcess(nil, zAppName, nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then

  begin

    repeat

      while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do

      begin

        if (Msg.message = WM_QUIT) then

          Result := Msg.wParam;

        TranslateMessage(msg);

        Dispatchmessage(msg);

        Sleep(100);

      end;

      GetExitCodeProcess(ProcessInfo.hProcess, ExitCode);

    until (ExitCode <> STILL_ACTIVE);

    CloseHandle(ProcessInfo.hThread);

    CloseHandle(ProcessInfo.hProcess);

    Result := 0;

  end

  else

    Result := GetLastError;

end;

///-查询某一Windows服务-///

function QueryServiceState(ServiceName: String): Cardinal;

var

 svcmgr, svc: Integer;

 temp: _SERVICE_STATUS;

begin

  svcmgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);

  if svcmgr = 0 then

  begin

    Result := 0;

    Exit;

  end;

  svc := OpenService(svcmgr, PChar(ServiceName), SERVICE_ALL_ACCESS); 

  if svc = 0 then

  begin

    CloseServiceHandle(svcmgr);

    Result := 0;

    Exit;

  end;

  QueryServiceStatus(svc, temp);

  if temp.dwCurrentState = SERVICE_STOPPED then

    Result := 1

  else

    Result := 0;

  CloseServiceHandle(svcmgr);

  CloseServiceHandle(svc);

  if (Result <> 1) and (Result <> 0) then

    Result := 1;

end;

///-启动某一Windows服务-///

Procedure RunService(ServiceName: String);

var

 svcmgr, svc: Integer;

 temp: _SERVICE_STATUS;

 s: Pchar;

begin

  svcmgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);

  if svcmgr = 0 then

    Exit;

  svc := OpenService(svcmgr, PChar(ServiceName), SERVICE_ALL_ACCESS);

  if svc = 0 then

  begin

    CloseServiceHandle(svcmgr);

    Exit;

  end;

  QueryServiceStatus(svc, temp);

  if temp.dwCurrentState = SERVICE_STOPPED then

    StartService(svc, 0, s);

  CloseServiceHandle(svcmgr);

  CloseServiceHandle(svc);

end;

四、结语

本文介绍了使用Delphi实现一个完整的Microsoft SQL Server 2000数据库应用程序的部署过程,包括数据库全部自动安装运行,基本不需要用户的干预。以上所有程序在Delphi7.0SQL Server 2000环境下调试通过。

 

 

 

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089