zoukankan      html  css  js  c++  java
  • 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?

    1. use master   
    2. go   
    3. sp_configure 'allow updates',1   
    4. go   
    5. reconfigure with override
    6. go   
    7. update sysaltfiles set [filename]='.\..\data\master.mdf' where [name]='master'
    8. update sysaltfiles set [filename]='.\..\data\mastlog.ldf' where [name]='mastlog'
    9. update sysdatabases set [filename]='.\..\data\master.mdf' where [name]='master'
    10. go   
    11. sp_detach_db 'msdb'
    12. go   
    13. sp_detach_db 'model'
    14. go   
    15. sp_configure 'allow updates',0   
    16. go   
    17. reconfigure with override
    18. go 

    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?

    1. if not exists (select name from master.dbo.sysdatabases where name = 'model')   
    2. begin   
    3.     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'
    4.     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'
    5.     exec master..sp_resetstatus tempdb   
    6.     Alter database tempdb modify file (name = tempdev, filename = 'C:\Program Files\Microsoft SQL Server\MSSQL$FISHOUT\Data\tempdb.mdf')   
    7.     Alter database tempdb modify file (name = templog, filename = 'C:\Program Files\Microsoft SQL Server\MSSQL$FISHOUT\Data\templog.ldf')   
    8. end 

    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?

    1. //////////////////////////////////////////////////////////////////////////////
    2. //
    3. // Description: Windows NT process control functions.
    4. //
    5. //              The process code is adapted from code posted by William F.
    6. //              Snodgrass to www.installsite.org. The original code header
    7. //              is appended below. The array code is adapted from code posted
    8. //              by Rajesh Ramachandran to the installshield.is6.installscript
    9. //              newsgroup.
    10. // 
    11. // Submitted by Richard Iwasa (riwasa@email.com).
    12. //
    13. // Usage example:
    14. //
    15. // if ProcessRunning("notepad") then
    16. //      MessageBox("Application is running.", INFORMATION);
    17. //
    18. //      ProcessEnd("notepad");
    19. //        
    20. //      Delay(2);  // Delay to allow process list to refresh
    21. //        
    22. //      if ProcessRunning("notepad") then
    23. //          MessageBox("Application is running.", INFORMATION);
    24. //      else
    25. //          MessageBox("Application is not running.", INFORMATION);
    26. //      endif;
    27. //  else
    28. //      MessageBox("Application is not running.", INFORMATION);
    29. //  endif;
    30. //
    31. // Original code header appended below:
    32. //
    33. // GetRunningApp();
    34. // ShutDownApp();
    35. // 
    36. // These script created functions will look for any running application
    37. // based on the file name, then display an error message within the Setup.
    38. // You can optionally halt the install or just continue on.
    39. // 
    40. // You can use the ShutDownApp() function for shutting down that process
    41. // or others as well. This is useful for processes that run in the 
    42. // background but have no Windows associated with them. May not work with
    43. // Services.
    44. // 
    45. // This script calls functions in PSAPI.DLL that are not supported on 
    46. // Windows 95 or 98.
    47. // 
    48. // ***Instructions***
    49. // Place these script peices into the Setup.rul file.
    50. // 
    51. // Modify the script to include the applications you would like to get or
    52. // shutdown.
    53. // 
    54. // Submitted by William F. Snodgrass
    55. // Contact info: bsnodgrass@geographix.com
    56. // 
    57. // Created by Theron Welch, 3/3/99
    58. // Minor modifications by Stefan Krueger, 11/03/99
    59. // 
    60. // Copyright (c) 1999-2000 GeoGraphix, Inc. 
    61. //
    62. //////////////////////////////////////////////////////////////////////////////
    63. /////////////////////////////////////////////////
    64. // Function prototypes.
    65. /////////////////////////////////////////////////
    66. prototype POINTER ArrayToPointer(BYREF VARIANT);   
    67. prototype NUMBER  ProcessEnd(STRING);   
    68. prototype BOOL    ProcessRunning(STRING);   
    69. // Kernel functions.
    70. prototype NUMBER Kernel32.OpenProcess(NUMBER, BOOL, NUMBER);   
    71. prototype NUMBER Kernel32.TerminateProcess(NUMBER, NUMBER);   
    72. // Process information functions.
    73. prototype NUMBER PSAPI.EnumProcesses(POINTER, NUMBER, BYREF NUMBER);   
    74. prototype NUMBER PSAPI.EnumProcessModules(NUMBER, BYREF NUMBER, NUMBER,   
    75.         BYREF NUMBER);   
    76. prototype NUMBER PSAPI.GetModuleFileNameExA(NUMBER, NUMBER, BYREF STRING,   
    77.         NUMBER);   
    78. /////////////////////////////////////////////////
    79. // Structures.
    80. /////////////////////////////////////////////////
    81. // Structure to mirror the C/C++ SAFEARRAY data structure.
    82. typedef _SAFEARRAY   
    83. begin   
    84.     SHORT   cDims;   
    85.     SHORT   fFeatures;   
    86.     LONG    cbElements;   
    87.     LONG    cLocks;   
    88.     POINTER pvData;   
    89. // rgsaBound omitted
    90. end;   
    91. // Structure to mirror the C/C++ VARIANT data structure.
    92. typedef _VARIANT   
    93. begin   
    94.     SHORT  vt;   
    95.     SHORT  wReserver1;   
    96.     SHORT  wReserved2;   
    97.     SHORT  wReserved3;   
    98.     NUMBER nData;   
    99. end;   
    100. /////////////////////////////////////////////////
    101. // Constants.
    102. /////////////////////////////////////////////////
    103. #define PSAPI_FILE        "psapi.dll"  // Windows NT process DLL
    104. #define PROCESSID_LENGTH  4            // 4 bytes (DWORD) for a process ID
    105. // Process information constants.
    106. #define PROCESS_QUERY_INFORMATION  0x400
    107. #define PROCESS_ALL_ACCESS         0x1f0fff
    108. #define PROCESS_VM_READ            0x10
    109. //////////////////////////////////////////////////////////////////////////////
    110. //
    111. // Function:    ArrayToPointer
    112. //
    113. // Description: Converts an InstallShield array into a C array.
    114. //
    115. //              When an array is created in InstallScript, a VARIANT variable
    116. //              is created which holds an OLEAutomation SAFEARRAY. To pass
    117. //              such an array to a DLL function expecting a C-style array,
    118. //              this function explicitly typecasts the pointer to the array
    119. //              to a _VARIANT pointer so that the _SAFEARRAY pointer can be
    120. //              extracted. The pointer to the actual data is then extracted
    121. //              from the _SAFEARRAY pointer.
    122. //
    123. // Parameters:  structArray - Array variable.
    124. //
    125. // Returns:     POINTER - Pointer to array.
    126. //
    127. //////////////////////////////////////////////////////////////////////////////
    128. function POINTER ArrayToPointer(structArray)   
    129.     _SAFEARRAY POINTER pstructArray;    // _SAFEARRAY array pointer
    130.     _VARIANT   POINTER pstructVariant;  // _VARIANT array pointer
    131. begin   
    132. // Typecast the pointer to the array to a _VARIANT pointer.
    133.     pstructVariant = &structArray;   
    134. // Extract the _SAFEARRAY pointer from the _VARIANT.
    135.     pstructArray = pstructVariant->nData;   
    136. // Return the pointer to the actual data from the _SAFEARRAY.
    137. return pstructArray->pvData;   
    138. end;   
    139. //////////////////////////////////////////////////////////////////////////////
    140. //
    141. // Function:    _Process_End
    142. //
    143. // Description: Terminates running processes for the specified application.
    144. //
    145. // Parameters:  szAppName - Name of the application to terminate.
    146. //
    147. // Returns:     >= 0 - Number of processes terminated.
    148. //                -1 - Failure.
    149. //
    150. //////////////////////////////////////////////////////////////////////////////
    151. function NUMBER ProcessEnd(szAppName)   
    152.     NUMBER  nvReturn;           // Number of processes terminated
    153.     NUMBER  nvProcessIDs(512);  // Array of process IDs
    154.     NUMBER  nvBytesReturned;    // Number of bytes returned in process ID array
    155.     NUMBER  nvProcesses;        // Number of processes running
    156.     NUMBER  nvIndex;            // Loop index
    157.     NUMBER  nvProcessHandle;    // Handle to a process
    158.     NUMBER  nvModuleHandle;     // Handle to a process module
    159.     NUMBER  nvBytesRequired;    // Number of bytes required to store values
    160.     POINTER pvProcessIDs;       // Pointer to process ID array
    161.     STRING  svModuleName;       // Module name
    162.     STRING  svFileName;         // Module filename 
    163. begin   
    164. // The psapi.dll reads the Windows NT performance database. The DLL
    165. // is part of the Win32 SDK.
    166. if UseDLL(WINSYSDIR ^ PSAPI_FILE) < 0 then   
    167. // Could not load psapi.dll.
    168.         MessageBox("错误:不能加载文件---[" + WINSYSDIR ^ PSAPI_FILE +   
    169. "].", SEVERE);   
    170. return -1;   
    171.     endif;   
    172. // Get the PIDs of all currently running processes.
    173.     pvProcessIDs = ArrayToPointer(nvProcessIDs);   
    174.     EnumProcesses(pvProcessIDs, 512, nvBytesReturned);   
    175. // Determine the number of process IDs retrieved. Each process ID
    176. // is PROCESSID_LENGTH bytes.
    177.     nvProcesses = nvBytesReturned / PROCESSID_LENGTH;   
    178. // Get the executable associated with each process, and check if
    179. // its filename matches the one passed to the function.
    180. for nvIndex = 1 to nvProcesses   
    181. // Get a handle to the process. The OpenProcess function
    182. // must have full (all) access to be able to terminate
    183. // processes.
    184.         nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |   
    185.                 PROCESS_ALL_ACCESS, 0, nvProcessIDs(nvIndex));   
    186. if nvProcessHandle != 0 then   
    187. // Get a handle to the first module in the process, which
    188. // should be the executable.
    189. if EnumProcessModules(nvProcessHandle, nvModuleHandle,         
    190.                     PROCESSID_LENGTH, nvBytesRequired) != 0 then   
    191. // Get the path of the module.
    192. if GetModuleFileNameExA(nvProcessHandle, nvModuleHandle,   
    193.                         svModuleName, SizeOf(svModuleName)) != 0 then   
    194. // Extract the filename (without an extension) from
    195. // the path.
    196.                     ParsePath(svFileName, svModuleName, FILENAME_ONLY);   
    197. if StrCompare(svFileName, szAppName) = 0 then   
    198. // The process module matches the application 
    199. // name passed to the function.
    200. if TerminateProcess(nvProcessHandle, 0) > 0 then   
    201.                             nvReturn++;   
    202.                         endif;   
    203.                     endif;   
    204.                 endif;   
    205.             endif;   
    206.         endif;   
    207.     endfor;   
    208. if UnUseDLL(PSAPI_FILE) < 0 then   
    209.         MessageBox("错误:不能卸载文件---[" + WINSYSDIR ^ PSAPI_FILE +   
    210. "].", SEVERE);   
    211. return -1;   
    212.     endif;   
    213. return nvReturn;   
    214. end;   
    215. //////////////////////////////////////////////////////////////////////////////
    216. //
    217. // Function:    _Process_Running
    218. //
    219. // Description: Determines if the specified process is running in memory.
    220. //
    221. // Parameters:  szAppName - Name of the application to check.
    222. //
    223. // Returns:     TRUE  - The process is running.
    224. //              FALSE - The process is not running.
    225. //
    226. //////////////////////////////////////////////////////////////////////////////
    227. function BOOL ProcessRunning(szAppName)   
    228.     BOOL    bvRunning;          // Process is running
    229.     NUMBER  nvProcessIDs(512);  // Array of process IDs
    230.     NUMBER  nvBytesReturned;    // Number of bytes returned in process ID array
    231.     NUMBER  nvProcesses;        // Number of processes running
    232.     NUMBER  nvIndex;            // Loop index
    233.     NUMBER  nvProcessHandle;    // Handle to a process
    234.     NUMBER  nvModuleHandle;     // Handle to a process module
    235.     NUMBER  nvBytesRequired;    // Number of bytes required to store values
    236.     POINTER pvProcessIDs;       // Pointer to process ID array
    237.     STRING  svModuleName;       // Module name
    238.     STRING  svFileName;         // Module filename 
    239. begin   
    240. // The psapi.dll reads the Windows NT performance database. The DLL
    241. // is part of the Win32 SDK.
    242. if UseDLL(WINSYSDIR ^ PSAPI_FILE) < 0 then   
    243. // Could not load psapi.dll.
    244.         MessageBox("错误:不能加载文件---[" + WINSYSDIR ^ PSAPI_FILE +   
    245. "].", SEVERE);   
    246. return FALSE;   
    247.     endif;   
    248. // Get the PIDs of all currently running processes.
    249.     pvProcessIDs = ArrayToPointer(nvProcessIDs);   
    250.     EnumProcesses(pvProcessIDs, 512, nvBytesReturned);   
    251. // Determine the number of process IDs retrieved. Each process ID
    252. // is PROCESSID_LENGTH bytes.
    253.     nvProcesses = nvBytesReturned / PROCESSID_LENGTH;   
    254. // Get the executable associated with each process, and check if
    255. // its filename matches the one passed to the function.
    256. for nvIndex = 1 to nvProcesses   
    257. // Get a handle to the process.
    258.         nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |   
    259.                 PROCESS_VM_READ, 0, nvProcessIDs(nvIndex));   
    260. if nvProcessHandle != 0 then   
    261. // Get a handle to the first module in the process, which
    262. // should be the executable.
    263. if EnumProcessModules(nvProcessHandle, nvModuleHandle,         
    264.                     PROCESSID_LENGTH, nvBytesRequired) != 0 then   
    265. // Get the path of the module.
    266. if GetModuleFileNameExA(nvProcessHandle, nvModuleHandle,   
    267.                         svModuleName, SizeOf(svModuleName)) != 0 then   
    268. // Extract the filename (without an extension) from
    269. // the path.
    270.                     ParsePath(svFileName, svModuleName, FILENAME_ONLY);   
    271. if StrCompare(svFileName, szAppName) = 0 then   
    272. // The process module matches the application 
    273. // name passed to the function.
    274.                         bvRunning = TRUE;   
    275. goto ProcessRunningEnd;   
    276.                     endif;   
    277.                 endif;   
    278.             endif;   
    279.         endif;   
    280.     endfor;   
    281.     ProcessRunningEnd:   
    282. if UnUseDLL(PSAPI_FILE) < 0 then   
    283.         MessageBox("错误:不能卸载文件---[" + WINSYSDIR ^ PSAPI_FILE +   
    284. "].", SEVERE);   
    285. return FALSE;   
    286.     endif;   
    287. return bvRunning;   
    288. end; 

    ////////////////////////////////////////////////////////////////////////////// // // 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?

    1. #include "ShutDownRunningApp.rul"
    2. export prototype DefaultFeature_Installed();   
    3. function DefaultFeature_Installed()   
    4.     number nvServiceState, nResult;   
    5. string szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, szStartServiceArgs;   
    6.     BOOL bStartService;   
    7.     LIST listConnections;   
    8. string szMsg, szKey, szConnection, szCmdLine;   
    9. begin   
    10. // 实例名
    11.     szCmdLine = TARGETDIR^"mssql$fishout";   
    12. // 转换为短路经
    13.     LongPathToShortPath(szCmdLine);   
    14.     szCmdLine = "/c  " + szCmdLine + "\\Binn\\sqlservr.exe -sFISHOUT -c -f -T3608 -T4022";   
    15. // SQL Server 以单用户模式启动,允许对系统目录进行更新,在新目录附加数据库
    16.     LaunchApplication(WINSYSDIR ^ "cmd.exe", szCmdLine, "", SW_HIDE, LAAW_OPTION_WAIT, LAAW_OPTION_FIXUP_PROGRAM);   
    17. // SQL运行时初始化
    18.     SQLRTInitialize2();   
    19. // 获取连接信息
    20.     listConnections = SQLRTGetConnections();   
    21.     ListGetFirstString (listConnections, szConnection);   
    22. // Windows认证方式
    23.     SQLRTPutConnectionAuthentication( szConnection, TRUE );   
    24. // 打开连接
    25.     nResult = SQLRTConnect( szConnection, "(local)\\fishout", TRUE, "", "" );   
    26. if( nResult < ISERR_SUCCESS ) then   
    27. // 获取错误信息
    28.         SQLRTGetErrorMessage( szMsg );   
    29. // 显示错误信息
    30.         MessageBox( szMsg, MB_OK );   
    31. else
    32. // SQL Server登录成功,保存连接信息
    33.         szKey = "";   
    34.         Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_SERVER, szConnection );   
    35.         LogWriteCustomString( szKey, "(local)\\fishout" );   
    36.         Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_USER, szConnection );   
    37.         LogWriteCustomString( szKey, "" );   
    38.         Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_AUTH, szConnection );   
    39.         LogWriteCustomNumber( szKey, SQL_AUTH_WINDOWS );   
    40.         Sprintf( szKey, SQL_FORMATSTRING_CONNECTION_DB, szConnection );   
    41.         LogWriteCustomString( szKey, "" );   
    42.     endif;   
    43. // 执行SQL脚本
    44.     SQLRTComponentInstall("MSDE2000.sql_SQLComponent");   
    45. // 中止SQL Server单用户、跟踪进程
    46. if ProcessRunning("sqlservr") then   
    47.         ProcessEnd("sqlservr");   
    48.     endif;   
    49. // 安装SQL Server服务
    50.     szMsg = "正在启动 MSDE2000 SP4服务......";   
    51.     SdShowMsg(szMsg, TRUE);   
    52. // 安装服务
    53.     szServiceName = "MSSQL$FISHOUT";   
    54.     szServiceDisplayName = "MSSQL$FISHOUT";   
    55.     szServiceDescription = "";   
    56.     szServicePathFile = TARGETDIR ^ "mssql$fishout\\Binn\\sqlservr.exe -sFISHOUT";   
    57.     bStartService = TRUE;   
    58.     szStartServiceArgs = "";   
    59. if (ServiceGetServiceState (szServiceName, nvServiceState ) >= ISERR_SUCCESS) then   
    60. // 停止并卸载原来的服务
    61.         ServiceStopService ( szServiceName );   
    62.         ServiceRemoveService ( szServiceName );   
    63.     endif;   
    64.     ServiceAddService ( szServiceName, szServiceDisplayName, szServiceDescription, szServicePathFile, bStartService, szStartServiceArgs );   
    65.     SdShowMsg(szMsg, FALSE);   
    66. end; 

    #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?

    1. Dlg_SQLServer:   
    2. //nResult = OnSQLServerInitialize( nResult );
    3. if( nResult = BACK ) goto Dlg_SdFeatureTree; 

    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

  • 相关阅读:
    java基础--字符转换Unicode
    java基础---集合框架
    洛谷 P2049 魔术棋子(vector)
    洛谷 P3133 [USACO16JAN]Radio Contact G
    洛谷 P2679 子串
    洛谷 P2549 计算器写作文
    洛谷 P2758 编辑距离
    洛谷 P1481 魔族密码
    洛谷 P1754 球迷购票问题
    洛谷 P2782 友好城市
  • 原文地址:https://www.cnblogs.com/Cindy_weiwei/p/1601762.html
Copyright © 2011-2022 走看看