正式会员享受无限制浏览网站功能和高速网盘下载,赶快加入本站吧!
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在网上看到许多关于MSDE2000集成到应用程序中一并安装的文章,这些方法无一例外都使用了InstallShield中调用外部命令的方式,其本质就是在安装过程中调用LaunchAppAndWait函数执行MSDE2000的setup.exe程序,这样一来,带来几个问题:
1、无法与应用程序的安装一并卸载;
2、无法实现MSDE2000的最小安装;
3、如果用户中途取消安装,程序不能完全回滚;
4、无法与应用程序安装到同一个目录。
如果使用installshield中的预安装功能,也仅能在MSI工程中使用,同时,也不能灵活地控制安装过程及实现上述功能,为此,我们需要一种方法,用于在安装过程中集成MSDE2000。这是因为许多应用需要SQL Server支持,而MSDE2000确实是一个不错的选择,撇开版权不说,仅全面兼容SQL和支持2G的数据量就足够了,如果能解决安装时的集成问题,就会为极大地方便应用程序的分发。
下面我通过具体实例来介绍这一方法。
目标一:实现不可控的最小安装。
一、数据准备:
1、下载SQL Server 2000 Desktop Engine (MSDE) 组件(SQL2000.MSDE-KB884525-SP4-x86.EXE)
2、双击下载的exe文件,解压缩至C:/SQL2KSP4,在运行中浏览至c:/SQL2KSP4/MSDE,找到setup.exe文件,双击它,不要急着点“确定”,在setup.exe后面空一格,接着输入安装参数:INSTANCENAME="fishout" SECURITYMODE=SQL SAPWD="fishout@TOM.COM" /L*v C:/MSDELog.log,点击确定(其中:INSTANCENAME="实例名",SAPWD="密码",可自行修改,以下均以命名实例“fishout”为例),待其安装完毕后不要启动服务,也不要重启机器,将C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/文件夹下的binn、Data、log三个文件夹保留,其余的删除。
3、准备注册表入口。打开注册表编辑器,导航至:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server,删除多余的子健,使其看上去如图所示:
再在SuperSocketNetLib子键下面的ProtocolList属性中增加两个字符串:tcp/np,右击Microsoft SQL Server,选择导出注册表,文件名任意取,打开并编辑已导出的注册表文件,将安装路径“C:/Program Files/Microsoft SQL Server”替换为“”,使其修改完成的注册表文件如下:
- Windows Registry Editor Version 5.00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server]
- "InstalledInstances"=hex(7):46,00,49,00,53,00,48,00,4f,00,55,00,54,00,00,00,00,/
- 00
- "SsrpActiveServer"=""
- "SqlMdacRegRefCount"=dword:00000001
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT]
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer]
- "AuditLevel"=dword:00000000
- "DefaultLogin"="guest"
- "ListenOn"=hex(7):53,00,53,00,4d,00,53,00,53,00,48,00,37,00,30,00,00,00,53,00,/
- 53,00,4e,00,45,00,54,00,4c,00,49,00,42,00,00,00,00,00
- "LoginMode"=dword:00000000
- "Map_"="//"
- "Map#"="-"
- "Map[ DISCUZ_CODE_173 ]quot;=""
- "SetHostName"=dword:00000000
- "Tapeloadwaittime"=dword:ffffffff
- "uptime_pid"=dword:000000c8
- "uptime_time_utc"=hex:0e,55,77,e8,59,58,ca,01
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer/CurrentVersion]
- "CurrentVersion"="8.00.194"
- "RegisteredOwner"=""
- "SerialNumber"=""
- "CSDVersionNumber"=dword:00000400
- "CSDVersion"="8.00.1100"
- "Language"=dword:00000804
- "checksum"=hex:38,30,32,32,63,31,35,38,61,65,37,64,34,63,64,37,35,30,64,61,30,/
- 33,34,62,36,30,31,34,32,63,62,61,66,37,30,33,30,38,35,35,65,62,64,63,34,34,/
- 36,62,61,37,35,64,61,62,37,30,34,66,37,33,65,35,30,37,64,65,37,34,30,39,31,/
- 32,65,62,39,35,65,62,36,62,63,37,64,64,37,32,66,62,36,65,39,32,63,61,66,63,/
- 33,30,66,62,30,30,35,64,31,37,30,61,65,61,32,34,61,30,30,63,65,33,64,62,66,/
- 62,61,39,64,61,64,65,30,36,36,30,66,31,62,63,63,35,32,37,33,63,32,62,33,30,/
- 36,31,66,66,61,64,65,36,65,32,30,36,38,34,33,64,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer/Parameters]
- "SQLArg0"="-d//MSSQL$FISHOUT//Data//master.mdf"
- "SQLArg1"="-e//MSSQL$FISHOUT//LOG//ERRORLOG"
- "SQLArg2"="-l//MSSQL$FISHOUT//Data//mastlog.ldf"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer/SuperSocketNetLib]
- "ProtocolList"=hex(7):74,00,63,00,70,00,00,00,6e,00,70,00,00,00,00,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer/SuperSocketNetLib/Np]
- "PipeName"="////.//pipe//MSSQL$FISHOUT//sql//query"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/MSSQLServer/SuperSocketNetLib/Tcp]
- "TcpHideFlag"=dword:00000000
- "TcpDynamicPorts"="0"
- "TcpPort"="0"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/FISHOUT/Setup]
- "FeatureName"="SqlRun"
- "FirstStart"=dword:00000000
- "ProductCode"="{E09B48B5-E141-427A-AB0C-D3605127224A}"
- "SQLDataRoot"="//MSSQL$FISHOUT"
- "SQLPath"="//MSSQL$FISHOUT"
- "Edition"="Desktop Engine"
- "PatchLevel"="8.4.2039"
复制代码 二、设计制作安装程序:
1、在installshield中新建一个InstallScript Project工程,命名为MDSE2000,在工程文件夹下新建files文件夹,复制刚才安装目录下MSSQL$FISHOUT文件夹到工程files中,复制C:/WINDOWS/System32/msvcp71.dll及msvcr71.dll文件到files/MSSQL$FISHOUT/Binn中(不要遗忘这个文件),设置Product Properties中TARGETDIR内容为:/Microsoft SQL Server,添加files中MSSQL$FISHOUT文件夹到Application Target Folder中。
2、导入注册表。在Registry注册表入口中右击Destination Computer,单击New Registry Set,重命名为:MDSE2000,右击它,点击:Import REG File...,导入刚才已修改好的注册表设置,在右边勾选与此关联的安装文件组。
3、在安装脚本中点选DefaultFeature,生成Installed事件,代码如下:
- export prototype DefaultFeature_Installed();
- function DefaultFeature_Installed()
- number nvServiceState;
- string szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, szStartServiceArgs;
- BOOL bStartService;
- begin
- // 安装服务
- szServiceName = "MSSQL$FISHOUT";
- szServiceDisplayName = "MSSQL$FISHOUT";
- szServiceDescription = "";
- szServicePathFile = TARGETDIR ^ "mssql$fishout//Binn//sqlservr.exe -sFISHOUT";
- bStartService = TRUE;
- szStartServiceArgs = "";
- if (ServiceGetServiceState (szServiceName, nvServiceState ) >= ISERR_SUCCESS) then
- // 停止并卸载原来的服务
- ServiceStopService ( szServiceName );
- ServiceRemoveService ( szServiceName );
- endif;
- ServiceAddService ( szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, bStartService, szStartServiceArgs );
- end;
复制代码 4、编译生成安装程序,可以看到,生成的安装包仅有12.4兆,比微软原来的安装包要小多了,非常利于网络传输和应用程序的分发,不过,有一个致命的缺点,就是不支持安装路径的更改,这个问题,放在下一节解决。
原创文章,转载请注明出处。
在这一节里,我们解决安装路径的更改问题。大家知道,MSDE2000安装后,数据库路径不能更改,这也是制约许多安装包无法与应用程序一并集成的首要原因,现在我们来解决这一个问题。
主要思路是通过分离msdb和model数据库,然后更改master数据库的系统目录指向,改为相对目录,最后,通过附加msdb及model并重建tempdb数据库来实现。
目标:实现集成包的任意目录安装。
注意:以下操作在前一节基础上继续。
一、准备数据库
1、启动先前安装的MSDE2000服务;
2、使用命令行工具分离并修改系统数据库;
3、将下面SQL脚本内容保存至:C:/Program Files/Microsoft SQL Server/80/Tools/Binn,文件名命名为:detach.sql。
- use master
- [color=#df3434][b][url=http://lib.csdn.net/base/go]Go[/url][/b][/color]
- sp_configure 'allow updates',1
- go
- reconfigure with override
- go
- update sysaltfiles set [filename]='./../data/master.mdf' where [name]='master'
- update sysaltfiles set [filename]='./../data/mastlog.ldf' where [name]='mastlog'
- update sysdatabases set [filename]='./../data/master.mdf' where [name]='master'
- go
- sp_detach_db 'msdb'
- go
- sp_detach_db 'model'
- go
- sp_configure 'allow updates',0
- go
- reconfigure with override
- go
复制代码 4、在运行菜单中输入:cmd /k cd C:/Program Files/Microsoft SQL Server/80/Tools/Binn,单击确定,打开命令窗口,在窗口中输入:sc start mssql$fishout -T3608,启动SQL服务,服务成功启动后再输入:osql -S (local)/fishout -E -i detach.sql,执行相对目录更改及分离操作,操作成功后会出现如下画面:
5、接着继续运行以下命令:net stop mssql$fishout,停止SQL服务,至此,数据文件已准备完成,复制C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/下的所有文件至工程文件夹下files/Data中,确认替换。
二、在安装工程中使用进程方式附加数据库并安装服务
主要设计思路:
当文件复制到目标机器结束后,以单用户、跟踪模式启动服务,以便允许对系统目录进行更新,从而,可以在新的安装目录下附加系统数据库,当以进程方式启动服务成功后,通过调用InstallShield中SQL运行时间库函数,将SQL脚本中的路径替换为实际安装路径并执行附加系统数据库的脚本,成功附加后,中止SQL进程,最后安装并启动服务。
1、建立SQL连接,为安装脚本中使用命令方式执行脚本提供准备。
2、导入数据库附加脚本
将以下脚本内容保存至:工程文件夹下的“Script Files”子文件夹中,文件名为:MSDE2000.sql,右击“NewSQLConnection1”,选择“Insert Script Files...”,浏览至工程文件夹下的“Script Files”子文件夹,将“MSDE2000.sql”脚本导入,在导入后的脚本“Text Replacement”处,单击“Add...”按钮添加一条替换记录,以便实现安装路径的变换,如图:
- if not exists (select name from master.dbo.sysdatabases where name = 'model')
- begin
- exec master..sp_attach_db 'model','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/model.mdf','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/modellog.ldf'
- exec master..sp_attach_db 'msdb','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/msdbdata.mdf','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/msdblog.ldf'
- exec master..sp_resetstatus tempdb
- Alter database tempdb modify file (name = tempdev, filename = 'C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/tempdb.mdf')
- Alter database tempdb modify file (name = templog, filename = 'C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/templog.ldf')
- end
复制代码 3、导入进程中止脚本。
引用前人已写的现成脚本,将以下脚本内容保存至:工程文件夹下的“Script Files”子文件夹中,文件名为:ShutDownRunningApp.rul,单击面板中“InstallScript”,右击“Files”,选择“Insert Script Files...”,浏览至工程文件夹下的“Script Files”子文件夹,将“ShutDownRunningApp.rul”脚本导入,需要使用这个脚本来实现SQL进程的中止。
- //////////////////////////////////////////////////////////////////////////////
- //
- // Description: Windows NT process control functions.
- //
- // The process code is adapted from code posted by William F.
- // Snodgrass to [url]www.installsite.org.[/url] The original code header
- // is appended below. The array code is adapted from code posted
- // by Rajesh Ramachandran to the installshield.is6.installscript
- // newsgroup.
- //
- // Submitted by Richard Iwasa ([email]riwasa@email.com[/email]).
- //
- // Usage example:
- //
- // if ProcessRunning("notepad") then
- // MessageBox("Application is running.", INFORMATION);
- //
- // ProcessEnd("notepad");
- //
- // Delay(2); // Delay to allow process list to refresh
- //
- // if ProcessRunning("notepad") then
- // MessageBox("Application is running.", INFORMATION);
- // else
- // MessageBox("Application is not running.", INFORMATION);
- // endif;
- // else
- // MessageBox("Application is not running.", INFORMATION);
- // endif;
- //
- // Original code header appended below:
- //
- // GetRunningApp();
- // ShutDownApp();
- //
- // These script created functions will look for any running application
- // based on the file name, then display an error message within the Setup.
- // You can optionally halt the install or just continue on.
- //
- // You can use the ShutDownApp() function for shutting down that process
- // or others as well. This is useful for processes that run in the
- // background but have no Windows associated with them. May not work with
- // Services.
- //
- // This script calls functions in PSAPI.DLL that are not supported on
- // Windows 95 or 98.
- //
- // ***Instructions***
- // Place these script peices into the Setup.rul file.
- //
- // Modify the script to include the applications you would like to get or
- // shutdown.
- //
- // Submitted by William F. Snodgrass
- // Contact info: [email]bsnodgrass@geographix.com[/email]
- //
- // Created by Theron Welch, 3/3/99
- // Minor modifications by Stefan Krueger, 11/03/99
- //
- // Copyright (c) 1999-2000 GeoGraphix, Inc.
- //
- //////////////////////////////////////////////////////////////////////////////
-
-
-
- /////////////////////////////////////////////////
- // Function prototypes.
- /////////////////////////////////////////////////
-
- prototype POINTER ArrayToPointer(BYREF VARIANT);
- prototype NUMBER ProcessEnd(STRING);
- prototype BOOL ProcessRunning(STRING);
-
- // Kernel functions.
-
- prototype NUMBER Kernel32.OpenProcess(NUMBER, BOOL, NUMBER);
- prototype NUMBER Kernel32.TerminateProcess(NUMBER, NUMBER);
-
- // Process information functions.
-
- prototype NUMBER PSAPI.EnumProcesses(POINTER, NUMBER, BYREF NUMBER);
- prototype NUMBER PSAPI.EnumProcessModules(NUMBER, BYREF NUMBER, NUMBER,
- BYREF NUMBER);
- prototype NUMBER PSAPI.GetModuleFileNameExA(NUMBER, NUMBER, BYREF STRING,
- NUMBER);
-
-
-
- /////////////////////////////////////////////////
- // Structures.
- /////////////////////////////////////////////////
-
- // Structure to mirror the C/C++ SAFEARRAY data structure.
-
- typedef _SAFEARRAY
- begin
- SHORT cDims;
- SHORT fFeatures;
- LONG cbElements;
- LONG cLocks;
- POINTER pvData;
- // rgsaBound omitted
- end;
-
- // Structure to mirror the C/C++ VARIANT data structure.
-
- typedef _VARIANT
- begin
- SHORT vt;
- SHORT wReserver1;
- SHORT wReserved2;
- SHORT wReserved3;
- NUMBER nData;
- end;
-
-
-
- /////////////////////////////////////////////////
- // Constants.
- /////////////////////////////////////////////////
-
- #define PSAPI_FILE "psapi.dll" // Windows NT process DLL
- #define PROCESSID_LENGTH 4 // 4 bytes (DWORD) for a process ID
-
- // Process information constants.
-
- #define PROCESS_QUERY_INFORMATION 0x400
- #define PROCESS_ALL_ACCESS 0x1f0fff
- #define PROCESS_VM_READ 0x10
-
-
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // Function: ArrayToPointer
- //
- // Description: Converts an InstallShield array into a C array.
- //
- // When an array is created in InstallScript, a VARIANT variable
- // is created which holds an OLEAutomation SAFEARRAY. To pass
- // such an array to a DLL function expecting a C-style array,
- // this function explicitly typecasts the pointer to the array
- // to a _VARIANT pointer so that the _SAFEARRAY pointer can be
- // extracted. The pointer to the actual data is then extracted
- // from the _SAFEARRAY pointer.
- //
- // Parameters: structArray - Array variable.
- //
- // Returns: POINTER - Pointer to array.
- //
- //////////////////////////////////////////////////////////////////////////////
-
- function POINTER ArrayToPointer(structArray)
- _SAFEARRAY POINTER pstructArray; // _SAFEARRAY array pointer
- _VARIANT POINTER pstructVariant; // _VARIANT array pointer
- begin
- // Typecast the pointer to the array to a _VARIANT pointer.
-
- pstructVariant = &structArray;
-
- // Extract the _SAFEARRAY pointer from the _VARIANT.
-
- pstructArray = pstructVariant->nData;
-
- // Return the pointer to the actual data from the _SAFEARRAY.
-
- return pstructArray->pvData;
- end;
-
-
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // Function: _Process_End
- //
- // Description: Terminates running processes for the specified application.
- //
- // Parameters: szAppName - Name of the application to terminate.
- //
- // Returns: >= 0 - Number of processes terminated.
- // -1 - Failure.
- //
- //////////////////////////////////////////////////////////////////////////////
-
- function NUMBER ProcessEnd(szAppName)
- NUMBER nvReturn; // Number of processes terminated
- NUMBER nvProcessIDs(512); // Array of process IDs
- NUMBER nvBytesReturned; // Number of bytes returned in process ID array
- NUMBER nvProcesses; // Number of processes running
- NUMBER nvIndex; // Loop index
- NUMBER nvProcessHandle; // Handle to a process
- NUMBER nvModuleHandle; // Handle to a process module
- NUMBER nvBytesRequired; // Number of bytes required to store values
- POINTER pvProcessIDs; // Pointer to process ID array
- STRING svModuleName; // Module name
- STRING svFileName; // Module filename
- begin
- // The psapi.dll reads the Windows NT performance database. The DLL
- // is part of the Win32 SDK.
-
- if UseDLL(WINSYSDIR ^ PSAPI_FILE) < 0 then
- // Could not load psapi.dll.
-
- MessageBox("错误:不能加载文件---[" + WINSYSDIR ^ PSAPI_FILE +
- "].", SEVERE);
-
- return -1;
- endif;
-
- // Get the PIDs of all currently running processes.
-
- pvProcessIDs = ArrayToPointer(nvProcessIDs);
-
- EnumProcesses(pvProcessIDs, 512, nvBytesReturned);
-
- // Determine the number of process IDs retrieved. Each process ID
- // is PROCESSID_LENGTH bytes.
-
- nvProcesses = nvBytesReturned / PROCESSID_LENGTH;
-
- // Get the executable associated with each process, and check if
- // its filename matches the one passed to the function.
-
- for nvIndex = 1 to nvProcesses
- // Get a handle to the process. The OpenProcess function
- // must have full (all) access to be able to terminate
- // processes.
-
- nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |
- PROCESS_ALL_ACCESS, 0, nvProcessIDs(nvIndex));
-
- if nvProcessHandle != 0 then
- // Get a handle to the first module in the process, which
- // should be the executable.
-
- if EnumProcessModules(nvProcessHandle, nvModuleHandle,
- PROCESSID_LENGTH, nvBytesRequired) != 0 then
- // Get the path of the module.
-
- if GetModuleFileNameExA(nvProcessHandle, nvModuleHandle,
- svModuleName, SizeOf(svModuleName)) != 0 then
- // Extract the filename (without an extension) from
- // the path.
-
- ParsePath(svFileName, svModuleName, FILENAME_ONLY);
-
- if StrCompare(svFileName, szAppName) = 0 then
- // The process module matches the application
- // name passed to the function.
-
- if TerminateProcess(nvProcessHandle, 0) > 0 then
- nvReturn++;
- endif;
- endif;
- endif;
- endif;
- endif;
- endfor;
-
- if UnUseDLL(PSAPI_FILE) < 0 then
- MessageBox("错误:不能卸载文件---[" + WINSYSDIR ^ PSAPI_FILE +
- "].", SEVERE);
-
- return -1;
- endif;
-
- return nvReturn;
- end;
-
-
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // Function: _Process_Running
- //
- // Description: Determines if the specified process is running in memory.
- //
- // Parameters: szAppName - Name of the application to check.
- //
- // Returns: TRUE - The process is running.
- // FALSE - The process is not running.
- //
- //////////////////////////////////////////////////////////////////////////////
-
- function BOOL ProcessRunning(szAppName)
- BOOL bvRunning; // Process is running
- NUMBER nvProcessIDs(512); // Array of process IDs
- NUMBER nvBytesReturned; // Number of bytes returned in process ID array
- NUMBER nvProcesses; // Number of processes running
- NUMBER nvIndex; // Loop index
- NUMBER nvProcessHandle; // Handle to a process
- NUMBER nvModuleHandle; // Handle to a process module
- NUMBER nvBytesRequired; // Number of bytes required to store values
- POINTER pvProcessIDs; // Pointer to process ID array
- STRING svModuleName; // Module name
- STRING svFileName; // Module filename
- begin
- // The psapi.dll reads the Windows NT performance database. The DLL
- // is part of the Win32 SDK.
-
- if UseDLL(WINSYSDIR ^ PSAPI_FILE) < 0 then
- // Could not load psapi.dll.
-
- MessageBox("错误:不能加载文件---[" + WINSYSDIR ^ PSAPI_FILE +
- "].", SEVERE);
-
- return FALSE;
- endif;
-
- // Get the PIDs of all currently running processes.
-
- pvProcessIDs = ArrayToPointer(nvProcessIDs);
-
- EnumProcesses(pvProcessIDs, 512, nvBytesReturned);
-
- // Determine the number of process IDs retrieved. Each process ID
- // is PROCESSID_LENGTH bytes.
-
- nvProcesses = nvBytesReturned / PROCESSID_LENGTH;
-
- // Get the executable associated with each process, and check if
- // its filename matches the one passed to the function.
-
- for nvIndex = 1 to nvProcesses
- // Get a handle to the process.
-
- nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |
- PROCESS_VM_READ, 0, nvProcessIDs(nvIndex));
-
- if nvProcessHandle != 0 then
- // Get a handle to the first module in the process, which
- // should be the executable.
-
- if EnumProcessModules(nvProcessHandle, nvModuleHandle,
- PROCESSID_LENGTH, nvBytesRequired) != 0 then
- // Get the path of the module.
-
- if GetModuleFileNameExA(nvProcessHandle, nvModuleHandle,
- svModuleName, SizeOf(svModuleName)) != 0 then
- // Extract the filename (without an extension) from
- // the path.
-
- ParsePath(svFileName, svModuleName, FILENAME_ONLY);
-
- if StrCompare(svFileName, szAppName) = 0 then
- // The process module matches the application
- // name passed to the function.
-
- bvRunning = TRUE;
-
- goto ProcessRunningEnd;
- endif;
- endif;
- endif;
- endif;
- endfor;
-
- ProcessRunningEnd:
-
- if UnUseDLL(PSAPI_FILE) < 0 then
- MessageBox("错误:不能卸载文件---[" + WINSYSDIR ^ PSAPI_FILE +
- "].", SEVERE);
-
- return FALSE;
- endif;
-
- return bvRunning;
- end;
复制代码 4、完善InstallShield脚本,实现任意目录的MSDE2000安装。
修改“featureevents.rul”中的内容为如下代码:
- #include "ShutDownRunningApp.rul"
- export prototype DefaultFeature_Installed();
- function DefaultFeature_Installed()
- number nvServiceState, nResult;
- string szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, szStartServiceArgs;
- BOOL bStartService;
- LIST listConnections;
- string szMsg, szKey, szConnection, szCmdLine;
- begin
- // 实例名
- szCmdLine = TARGETDIR^"mssql$fishout";
- // 转换为短路经
- LongPathToShortPath(szCmdLine);
- szCmdLine = "/c " + szCmdLine + "//Binn//sqlservr.exe -sFISHOUT -c -f -T3608 -T4022";
- // SQL Server 以单用户模式启动,允许对系统目录进行更新,在新目录附加数据库
- LaunchApplication(WINSYSDIR ^ "cmd.exe", szCmdLine, "", SW_HIDE, LAAW_OPTION_WAIT, LAAW_OPTION_FIXUP_PROGRAM);
- // SQL运行时初始化
- SQLRTInitialize2();
- // 获取连接信息
- listConnections = SQLRTGetConnections();
- ListGetFirstString (listConnections, szConnection);
- // Windows认证方式
- SQLRTPutConnectionAuthentication( szConnection, TRUE );
- // 打开连接
- nResult = SQLRTConnect( szConnection, "(local)//fishout", TRUE, "", "" );
- if( nResult < ISERR_SUCCESS ) then
- // 获取错误信息
- SQLRTGetErrorMessage( szMsg );
- // 显示错误信息
- MessageBox( szMsg, MB_OK );
- else
- // SQL Server登录成功,保存连接信息
- szKey = "";
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_SERVER, szConnection );
- LogWriteCustomString( szKey, "(local)//fishout" );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_USER, szConnection );
- LogWriteCustomString( szKey, "" );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_AUTH, szConnection );
- LogWriteCustomNumber( szKey, SQL_AUTH_WINDOWS );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_DB, szConnection );
- LogWriteCustomString( szKey, "" );
- endif;
- // 执行SQL脚本
- SQLRTComponentInstall("MSDE2000.sql_SQLComponent");
- // 中止SQL Server单用户、跟踪进程
- if ProcessRunning("sqlservr") then
- ProcessEnd("sqlservr");
- endif;
- // 安装SQL Server服务
- szMsg = "正在启动 MSDE2000 SP4服务......";
- SdShowMsg(szMsg, TRUE);
- // 安装服务
- szServiceName = "MSSQL$FISHOUT";
- szServiceDisplayName = "MSSQL$FISHOUT";
- szServiceDescription = "";
- szServicePathFile = TARGETDIR ^ "mssql$fishout//Binn//sqlservr.exe -sFISHOUT";
- bStartService = TRUE;
- szStartServiceArgs = "";
- if (ServiceGetServiceState (szServiceName, nvServiceState ) >= ISERR_SUCCESS) then
- // 停止并卸载原来的服务
- ServiceStopService ( szServiceName );
- ServiceRemoveService ( szServiceName );
- endif;
- ServiceAddService ( szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, bStartService, szStartServiceArgs );
- SdShowMsg(szMsg, FALSE);
- end;
复制代码 回到setup.rul脚本中,将下面相关行注释掉,阻止安装过程中出现SQL登录窗口,以便通过脚本程序控制SQL登录和执行SQL脚本,实现任意目录的安装。
- Dlg_SQLServer:
- //nResult = OnSQLServerInitialize( nResult );
- if( nResult = BACK ) goto Dlg_SdFeatureTree;
复制代码 编译并重建安装工程,至此,可以在任意目录下安装的MSDE2000最小版本(仅数据库核心)成功建立,网上的一些绿色MSDE2000版本只需用于应用程序的测试,与应用程序一起集成分发,客户端的安全性可以得到有效保证(微软原始文件),安装包也显得非常专业,当然,实现安装时实例名及sa密码的更改就更理想了,这个问题留待下一步解决。
在这一节里,我们讨论如何在安装目录的任意指定基础上实现实例名及sa密码的更改,这样,就继承了原有微软80多兆安装包的功能,但是,现有的安装包体积小多了,仅有原来的1/6,当然,这仅是全新安装而言,对于升级安装是不适应的,不过,实际上我们大多数时候都是使用全新安装,何况,MSDE2000还支持多实例安装,所以,这种方法还是非常有实际意义的。
我们先看看默认实例和命名实例在安装上有何区别:
1、安装目录的区别;
默认安装的子目录名称是:C:/Program Files/Microsoft SQL Server/MSSQL/。
命名实例的子目录名称是:C:/Program Files/Microsoft SQL Server/实例名/。
2、注册表中的区别:
默认实例的注册表位置:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer及Microsoft SQL Server子键。
命名实例的注册表位置:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/实例名。
看来默认实例和命名实例在安装上无论是目录名还是注册表都还是有很大区别。
主要设计思路:
首先,安装子目录的区别可以在Components中的Destination统一设定为,通过自定义窗口根据用户选择用脚本进行控制。
然而,注册表的区别就没有可以直接设置的地方了,因为,我们先前采用的是注册表导入的方式并与相关Components进行关联这种方式进行的,如果采用脚本写注册表入口的方式实现,固然可行,可是,这个工作量太大了,有没有更为简便的办法来实现呢?通过查询联机帮助,发现,CreateRegistrySet这个注册表函数就可以实现注册表入口与特定component的关联。
好了,关键问题的解决思路明确了,让我们来具体实现吧!
目标:实现实例名及sa密码的安装时指定。
一、注册表准备
1、如前所述,在运行中浏览至c:/SQL2KSP4/MSDE,让我们以这个命令行安装使用混合模式身份验证的默认实例:setup.exe SECURITYMODE=SQL SAPWD="fishout@TOM.COM" /L*v C:/MSDELog.log,等待安装完毕。
2、打开注册表编辑器,导航至:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer,ProtocolList属性中增加tcp/np键值以加快连接速度,删除多余的子健,将MSSQLServer子键下的内容导出,导航至HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server,同样也删除多余的子健并导出,合并两个注册表文件,编辑修改其中的安装路径,使其如下:
(1)、“默认实例”注册表设置:
- Windows Registry Editor Version 5.00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server]
- "InstalledInstances"=hex(7):4d,00,53,00,53,00,51,00,4c,00,53,00,45,00,52,00,56,/
- 00,45,00,52,00,00,00,00,00
- "SsrpActiveServer"=""
- "SqlMdacRegRefCount"=dword:00000001
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer]
- "AuditLevel"=dword:00000000
- "DefaultLogin"="guest"
- "ListenOn"=hex(7):53,00,53,00,4d,00,53,00,53,00,48,00,37,00,30,00,00,00,53,00,/
- 53,00,4e,00,45,00,54,00,4c,00,49,00,42,00,00,00,00,00
- "LoginMode"=dword:00000000
- "Map_"="//"
- "Map#"="-"
- "Map[ DISCUZ_CODE_180 ]quot;=""
- "SetHostName"=dword:00000000
- "Tapeloadwaittime"=dword:ffffffff
- "uptime_pid"=dword:00000e30
- "uptime_time_utc"=hex:de,57,29,6f,c2,5e,ca,01
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/CurrentVersion]
- "CurrentVersion"="8.00.194"
- "RegisteredOwner"=""
- "SerialNumber"=""
- "CSDVersionNumber"=dword:00000400
- "CSDVersion"="8.00.1100"
- "Language"=dword:00000804
- "checksum"=hex:37,38,32,32,63,31,35,38,61,65,37,64,34,63,64,37,35,30,64,61,30,/
- 33,34,62,37,64,63,33,37,66,33,36,33,62,37,36,35,65,35,39,66,37,31,30,32,36,/
- 62,34,37,64,66,36,33,30,63,37,63,64,62,38,64,65,34,37,65,36,30,62,37,32,36,/
- 39,63,36,34,64,31,65,65,38,33,62,33,62,35,35,31,33,61,36,63,64,61,36,66,63,/
- 66,32,65,64,64,39,31,36,62,63,62,39,36,66,34,63,32,61,36,34,34,63,64,64,35,/
- 35,33,34,31,37,36,31,66,62,30,61,64,61,33,32,64,63,64,32,34,39,64,34,31,31,/
- 31,33,38,63,36,38,61,62,31,64,39,63,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/Parameters]
- "SQLArg0"="-d//Data//master.mdf"
- "SQLArg1"="-e//LOG//ERRORLOG"
- "SQLArg2"="-l//Data//mastlog.ldf"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/SuperSocketNetLib]
- "ProtocolList"=hex(7):74,00,63,00,70,00,00,00,6e,00,70,00,00,00,00,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/SuperSocketNetLib/Np]
- "PipeName"="////.//pipe////sql//query"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/MSSQLServer/SuperSocketNetLib/Tcp]
- "TcpHideFlag"=dword:00000000
- "TcpDynamicPorts"="0"
- "TcpPort"="1433"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MSSQLServer/Setup]
- "FeatureName"="SqlRun"
- "FirstStart"=dword:00000000
- "ProductCode"="{E09B48B5-E141-427A-AB0C-D3605127224A}"
- "SQLDataRoot"=""
- "SQLPath"=""
- "Edition"="Desktop Engine"
复制代码 (2)、“命名实例”注册表设置:
- Windows Registry Editor Version 5.00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server]
- "InstalledInstances"=hex(7):46,00,49,00,53,00,48,00,4f,00,55,00,54,00,00,00,00,/
- 00
- "SsrpActiveServer"=""
- "SqlMdacRegRefCount"=dword:00000001
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server/]
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer]
- "AuditLevel"=dword:00000000
- "DefaultLogin"="guest"
- "ListenOn"=hex(7):53,00,53,00,4d,00,53,00,53,00,48,00,37,00,30,00,00,00,53,00,/
- 53,00,4e,00,45,00,54,00,4c,00,49,00,42,00,00,00,00,00
- "LoginMode"=dword:00000000
- "Map_"="//"
- "Map#"="-"
- "Map[ DISCUZ_CODE_181 ]quot;=""
- "SetHostName"=dword:00000000
- "Tapeloadwaittime"=dword:ffffffff
- "uptime_pid"=dword:00000e10
- "uptime_time_utc"=hex:23,ac,f1,ec,70,5f,ca,01
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer/CurrentVersion]
- "CurrentVersion"="8.00.194"
- "RegisteredOwner"=""
- "SerialNumber"=""
- "CSDVersionNumber"=dword:00000400
- "CSDVersion"="8.00.1100"
- "Language"=dword:00000804
- "checksum"=hex:37,38,32,32,63,31,35,38,61,65,37,64,34,63,64,37,35,30,64,61,30,/
- 33,34,62,36,30,31,34,32,64,30,61,34,32,61,65,31,37,31,34,33,37,32,63,63,37,/
- 65,30,61,64,31,66,30,31,32,32,33,64,31,66,36,66,30,32,65,31,32,37,63,38,35,/
- 38,64,62,39,35,30,34,31,63,32,66,66,38,30,63,38,37,37,66,34,36,66,61,34,34,/
- 36,32,35,33,33,39,61,38,63,34,62,63,38,36,30,65,31,32,37,66,39,64,34,34,32,/
- 37,36,32,37,39,36,66,31,38,33,30,64,32,64,32,32,30,63,62,66,63,61,64,30,34,/
- 32,30,64,35,63,30,30,33,34,33,65,34,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer/Parameters]
- "SQLArg0"="-d//Data//master.mdf"
- "SQLArg1"="-e//LOG//ERRORLOG"
- "SQLArg2"="-l//Data//mastlog.ldf"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer/SuperSocketNetLib]
- "ProtocolList"=hex(7):74,00,63,00,70,00,00,00,6e,00,70,00,00,00,00,00
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer/SuperSocketNetLib/Np]
- "PipeName"="////.//pipe//MSSQL$FISHOUT//sql//query"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//MSSQLServer/SuperSocketNetLib/Tcp]
- "TcpHideFlag"=dword:00000000
- "TcpDynamicPorts"="0"
- "TcpPort"="0"
-
- [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SQL Server//Setup]
- "FeatureName"="SqlRun"
- "FirstStart"=dword:00000000
- "ProductCode"="{E09B48B5-E141-427A-AB0C-D3605127224A}"
- "SQLDataRoot"=""
- "SQLPath"=""
- "Edition"="Desktop Engine"
- "PatchLevel"="8.4.2039"
复制代码 3、在安装工程中,新建注册表入口,重命名为:MDSE2000_Default,右击它,点击:Import REG File...,导入刚才已修改好的“默认实例”注册表设置,再次新建注册表入口,重命名为:MSDE2000_Custom,导入为“命名实例”注册表设置,注意:不要在右边勾选与此关联的安装文件组。
二、实例名的变更
实例名的变更通过两个地方进行设置,一是Components的安装路径仅设置为,通过自定义窗口的脚本根据实例名的选择不同而设置不同的路径,二是注册表设置,根据选择的实例名使用CreateRegistrySet函数关联不同的注册表入口。
三、SA密码的修改方法
在“MSDE2000.sql”脚本内容中增加一行:exec sp_password NULL, '', 'sa',使其看上去如下:
- if not exists (select name from master.dbo.sysdatabases where name = 'model')
- begin
- exec master..sp_attach_db 'model','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/model.mdf','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/modellog.ldf'
- exec master..sp_attach_db 'msdb','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/msdbdata.mdf','C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/msdblog.ldf'
- exec master..sp_resetstatus tempdb
- Alter database tempdb modify file (name = tempdev, filename = 'C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/tempdb.mdf')
- Alter database tempdb modify file (name = templog, filename = 'C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/templog.ldf')
- exec master..sp_password 'fishout@TOM.COM', 'new_password', 'sa'
- use master
- exec sp_configure 'allow updates',1
- reconfigure with override
- update sysdatabases set [filename]='C:/Program Files/Microsoft SQL Server/MSSQL$FISHOUT/Data/master.mdf' where [name]='master'
- exec sp_configure 'allow updates',0
- reconfigure with override
- end
复制代码 四、自定义对话框用户接口的实现
编辑修改原有的SdAskDestPath2对话框,使其如图所示:
将以下自定义对话框脚本另存为:SdAskDestPath2DlgEx.rul,在工程中导入,实现安装路径、实例名和SA密码的设置。
- //////////////////////////////////////////////////////////////////////////////////////////
- //
- // File Name: SdAskDestPath2DlgEx.rul
- //
- // Description: This file contains the InstallShield script for the SdAskDestPath2
- // dialog function.
- //
- /////////////////////////////////////////////////////////////////////////////////////////
-
- #include "Dialogs.h"
- #include "CustomDlg.h"
- #include "Winapi.h"
- #include "ISRTDefs.h"
- #include "Silent.h"
- #include "sdrc.h"
- #include "sdint.h"
- #include "DialogsPriv.h"
- // 对话框ID定义
- #define SD_Radio1 1322
- #define SD_Radio2 1323
- #define SD_Text1 1324
- #define SD_Text2 1325
- #define SD_EditInstanceName 1326
- #define SD_EditSaPassword 1327
- prototype SdAskDestPath2Ex(STRING, STRING, BYREF STRING, BYREF STRING, BYREF STRING);
- function SdAskDestPath2Ex(szTitle, szMsg, svDir, svInstanceName, svSaPassword)
- STRING szDlg, svDirLoc, szTemp;
- INT nId, nTemp, nSdDialog, nStyle;
- HWND hwndDlg;
- BOOL bDone;
- STRING svRadioChoice;
-
- begin
- szDlg = SD_DLG_ASKDESTPATH2;
- nSdDialog = SD_NDLG_ASKDESTPATH2;
- svDirLoc = svDir;
- // 读静默安装参数
- if (MODE=SILENTMODE) then
- SdMakeName( szAppKey, szDlg, szTitle, nSdAskDestPath2 );
- SilentReadData( szAppKey, "Result", DATA_NUMBER, szTemp, nId );
- if ((nId != BACK) && (nId != CANCEL)) then
- SilentReadData( szAppKey, "szDir", DATA_STRING, svDir, nTemp );
- SilentReadData( szAppKey, "szInstanceName", DATA_STRING, svInstanceName, nTemp );
- SilentReadData( szAppKey, "szSaPassword", DATA_STRING, svSaPassword, nTemp );
- endif;
- return nId;
- endif;
- // 确保初始化完成
- if (!bSdInit) then
- SdInit();
- endif;
- if (EzDefineDialog( szDlg, "", "", SD_NDLG_ASKDESTPATH2 ) = DLG_ERR) then
- return -1;
- endif;
- // 循环开始直至用户选择标准按钮
- bDone = FALSE;
- while (!bDone)
- nId = WaitOnDialog( szDlg );
- switch (nId)
- case DLG_INIT:
- hwndDlg = CmdGetHwndDlg( szDlg );
- TextSubGetValue ( "", svRadioChoice, TRUE, TRUE );
- if (svRadioChoice = "") then
- _WinSubEnableControl (hwndDlg, SD_EditInstanceName, 0); // 禁止控件修改
- CtrlSetState(szDlg, SD_Radio1, BUTTON_CHECKED); // 设置初始状态
- else
- CtrlSetState(szDlg, SD_Radio2, BUTTON_CHECKED);
- endif;
- TextSubGetValue ( "", svInstanceName, TRUE, TRUE );
- TextSubGetValue ( "", svSaPassword, TRUE, TRUE );
- if (svSaPassword = "") then
- svSaPassword = "fishout@TOM.COM";
- endif;
- CtrlSetText(szDlg, SD_EditInstanceName, svInstanceName); // 设置初始值
- CtrlSetText(szDlg, SD_EditSaPassword, svSaPassword);
- CtrlSetText( szDlg, 0x80000000 | SD_STA_DESTDIR, svDirLoc );
- if(szMsg != "") then
- SdSetStatic( szDlg, SD_STA_CHANGEDIRMSG, szMsg );
- endif;
- SdGeneralInit( szDlg, hwndDlg, nStyle, szSdProduct );
- SdSetDlgTitle(szDlg, hwndDlg, szTitle);
-
- case SD_Radio1:
- svRadioChoice = "";
- svInstanceName = "";
- svSaPassword = "fishout@TOM.COM";
- CtrlSetText(szDlg, SD_EditInstanceName, svInstanceName);
- CtrlSetText(szDlg, SD_EditSaPassword, svSaPassword);
- _WinSubEnableControl (hwndDlg, SD_EditInstanceName, 0); // 禁止修改
-
- case SD_Radio2:
- svRadioChoice = "CustomInstanceName";
- svInstanceName = "fishout";
- CtrlSetText(szDlg, SD_EditInstanceName, svInstanceName);
- _WinSubEnableControl (hwndDlg, SD_EditInstanceName, 1); // 允许修改
-
- case SD_PBUT_CHANGEDIR:
- SelectDirNoLog( "", "", svDirLoc, TRUE );
- CtrlSetText( szDlg, 0x80000000 | SD_STA_DESTDIR, svDirLoc );
-
- case SD_PBUT_CONTINUE:
- svDir = svDirLoc;
- CtrlGetText(szDlg, SD_EditInstanceName, svInstanceName);
- CtrlGetText(szDlg, SD_EditSaPassword, svSaPassword);
- StrToUpper(svInstanceName, svInstanceName);
- TextSubSetValue ( "", svInstanceName, TRUE );
- TextSubSetValue ( "", svSaPassword, TRUE );
- TextSubSetValue ( "", svRadioChoice, TRUE );
- // 根据实例名的不同,确定不同的安装路径
- if (svRadioChoice = "") then
- svDir = svDir + "//mssql";
- else
- svDir = svDir + "//mssql[ DISCUZ_CODE_183 ]quot; + svInstanceName;
- endif;
- nId = NEXT;
- bDone = TRUE;
-
- case BACK:
- CtrlGetText(szDlg, SD_EditInstanceName, svInstanceName);
- CtrlGetText(szDlg, SD_EditSaPassword, svSaPassword);
- TextSubSetValue ( "", svInstanceName, TRUE );
- TextSubSetValue ( "", svSaPassword, TRUE );
- TextSubSetValue ( "", svRadioChoice, TRUE );
- nId = BACK;
- bDone = TRUE;
-
- case DLG_ERR:
- SdError( -1, "SdAskDestPath2" );
- nId = -1;
- bDone = TRUE;
-
- case DLG_CLOSE:
- SdCloseDlg( hwndDlg, nId, bDone );
-
- default:
- // 检查标准按钮句柄
- if (SdIsStdButton( nId ) && SdDoStdButton( nId )) then
- bDone = TRUE;
- endif;
- endswitch;
- endwhile;
- EndDialog( szDlg );
- ReleaseDialog( szDlg );
- SdUnInit( );
- // 保存静默安装参数
- if (MODE=RECORDMODE) then
- SdMakeName( szAppKey, szDlg, szTitle, nSdAskDestPath2 );
- SilentWriteData( szAppKey, "szDir", DATA_STRING, svDir, 0 );
- SilentWriteData( szAppKey, "szInstanceName", DATA_STRING, svInstanceName, 0 );
- SilentWriteData( szAppKey, "szSaPassword", DATA_STRING, svSaPassword, 0 );
- SilentWriteData( szAppKey, "Result", DATA_NUMBER, "", nId );
- endif;
- return nId;
- end;
复制代码 五、修改脚本文件
1、将Setup.rul中Dlg_SdAskDestPath2标号处的内容修改为以下代码:
- Dlg_SdAskDestPath2:
- if ((nResult = BACK) && (nSetupType != CUSTOM)) goto Dlg_SetupType2;
- szTitle = "";
- szMsg = "";
- // 还原保存的路径,用于自定义对话框
- szDir = szCustomDir;
- if (nSetupType = CUSTOM) then
- //{{IS_SCRIPT_TAG(Dlg_SdAskDestPath2)
- nResult = SdAskDestPath2Ex( szTitle, szMsg, szDir, svInstanceName, svSaPassword );
- //}}IS_SCRIPT_TAG(Dlg_SdAskDestPath2)
- TARGETDIR = szDir;
- else
- TARGETDIR = szDir + "//mssql";
- svInstanceName = "";
- svSaPassword = "fishout@TOM.COM";
- endif;
- if (nResult = BACK) goto Dlg_SetupType2;
复制代码 2、修改“featureevents.rul”中的内容,实现注册表入口关联及SQL脚本的执行,代码如下:
- //---------------------------------------------------------------------------
- // The Installed event is sent after the feature DefaultFeature
- // is installed.
- //---------------------------------------------------------------------------
-
- #include "ShutDownRunningApp.rul"
- export prototype DefaultFeature_Installed();
- function DefaultFeature_Installed()
- number nvServiceState, nResult;
- string szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, szStartServiceArgs;
- BOOL bStartService;
- LIST listConnections;
- string szMsg, szKey, szConnection, szCmdLine, szServer, svInstanceName;
- begin
- szCmdLine = TARGETDIR ^ "Binn//sqlservr.exe";
- // 转换为短路经
- LongPathToShortPath(szCmdLine);
- // 实例名
- TextSubGetValue ( "", svInstanceName, TRUE, TRUE );
- if (svInstanceName = "") then
- szServer = "(local)";
- szServiceName = "MSSQLSERVER";
- szServiceDisplayName = "MSSQLSERVER";
- szServicePathFile = TARGETDIR ^ "Binn//sqlservr.exe -sMSSQLSERVER";
- szCmdLine = "/c " + szCmdLine + " -sMSSQLSERVER -c -f -T3608 -T4022";
- CreateRegistrySet("MSDE2000_Default"); // 写注册表入口
- else
- szServer = "(local)//" + svInstanceName;
- szServiceName = "MSSQL[ DISCUZ_CODE_185 ]quot; + svInstanceName;
- szServiceDisplayName = szServiceName;
- szServicePathFile = TARGETDIR ^ "Binn//sqlservr.exe -s" + svInstanceName;
- szCmdLine = "/c " + szCmdLine + " -s" + svInstanceName + " -c -f -T3608 -T4022";
- CreateRegistrySet("MSDE2000_Custom");
- endif;
- // SQL Server 以单用户模式启动,允许对系统目录进行更新,在新目录附加[color=#df3434][b][url=http://lib.csdn.net/base/mysql]数据库[/url][/b][/color]
- LaunchApplication(WINSYSDIR ^ "cmd.exe", szCmdLine, "", SW_HIDE, LAAW_OPTION_WAIT, LAAW_OPTION_FIXUP_PROGRAM);
- // SQL运行时初始化
- SQLRTInitialize2();
- // 获取连接信息
- listConnections = SQLRTGetConnections();
- ListGetFirstString (listConnections, szConnection);
- // Windows认证方式
- SQLRTPutConnectionAuthentication( szConnection, TRUE );
- // 打开连接
- nResult = SQLRTConnect( szConnection, szServer, TRUE, "", "" );
- if( nResult < ISERR_SUCCESS ) then
- // 获取错误信息
- SQLRTGetErrorMessage( szMsg );
- // 显示错误信息
- MessageBox( szMsg, MB_OK );
- else
- // SQL Server登录成功,保存连接信息
- szKey = "";
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_SERVER, szConnection );
- LogWriteCustomString( szKey, szServer );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_USER, szConnection );
- LogWriteCustomString( szKey, "" );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_AUTH, szConnection );
- LogWriteCustomNumber( szKey, SQL_AUTH_WINDOWS );
- Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_DB, szConnection );
- LogWriteCustomString( szKey, "" );
- endif;
- // 执行SQL脚本
- SQLRTComponentInstall("MSDE2000.sql_SQLComponent");
- // 中止SQL Server单用户、跟踪进程
- if ProcessRunning("sqlservr") then
- ProcessEnd("sqlservr");
- endif;
- // 安装SQL Server服务
- szMsg = "正在启动 MSDE2000 SP4服务......";
- SdShowMsg(szMsg, TRUE);
- // 安装服务
- szServiceDescription = "";
- bStartService = TRUE;
- szStartServiceArgs = "";
- if (ServiceGetServiceState (szServiceName, nvServiceState ) >= ISERR_SUCCESS) then
- // 停止并卸载原来的服务
- ServiceStopService ( szServiceName );
- ServiceRemoveService ( szServiceName );
- endif;
- ServiceAddService ( szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, bStartService, szStartServiceArgs );
- SdShowMsg(szMsg, FALSE);
- end;
复制代码 好了!一个相对比较完美的MSDE2000最小版本就实现了,这下可以将其集成在自己的应用程序中,以下问题全部解决:
1、无法与应用程序的安装一并卸载;
2、无法实现MSDE2000的最小安装;
3、如果用户中途取消安装,程序不能完全回滚;
4、无法与应用程序安装到同一个目录。
|