标签:des style blog http 使用 os io 文件
原文:InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布原帖地址:http://blog.csdn.net/fishout/archive/2009/10/28/4739269.aspx
在这一节里,我们解决安装路径的更改问题。大家知道,MSDE2000安装后,数据库路径不能更改,这也是制约许多安装包无法与应用程序一并集成的首要原因,现在我们来解决这一个问题。
主要思路是通过分离msdb和model数据库,然后更改master数据库的系统目录指向,改为相对目录,最后,通过附加msdb及model并重建tempdb数据库来实现。
目标:实现集成包的任意目录安装。
注意:以下操作在前一节基础上继续。
一、准备数据库
1、启动先前安装的MSDE2000服务;
2、使用命令行工具分离并修改系统数据库;
3、将下面SQL脚本内容保存至:C:\Program Files\Microsoft SQL Server\80\Tools\Binn,文件名命名为:detach.sql。
view plaincopy to clipboardprint?
use master go 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...”按钮添加一条替换记录,以便实现安装路径的变换,如图:
view plaincopy to clipboardprint?
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进程的中止。
view plaincopy to clipboardprint?
////////////////////////////////////////////////////////////////////////////// // // Description: Windows NT process control functions. // // The process code is adapted from code posted by William F. // Snodgrass to www.installsite.org. 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 (riwasa@email.com). // // 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: bsnodgrass@geographix.com // // 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”中的内容为如下代码:
view plaincopy to clipboardprint?
#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脚本,实现任意目录的安装。
view plaincopy to clipboardprint?
Dlg_SQLServer: //nResult = OnSQLServerInitialize( nResult ); if( nResult = BACK ) goto Dlg_SdFeatureTree;
编译并重建安装工程,至此,可以在任意目录下安装的MSDE2000最小版本(仅数据库核心)成功建立,网上的一些绿色MSDE2000版本只需用于应用程序的测试,与应用程序一起集成分发,客户端的安全性可以得到有效保证(微软原始文件),安装包也显得非常专业,当然,实现安装时实例名及sa密码的更改就更理想了,这个问题留待下一步解决。
参考文档:
http://support.microsoft.com/kb/224071
http://support.microsoft.com/kb/288809/zh-cn
InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布,布布扣,bubuko.com
InstallShield集成安装MSDE2000最小版本(二) fishout特许授权发布
标签:des style blog http 使用 os io 文件
原文地址:http://www.cnblogs.com/lonelyxmas/p/3922657.html