创建再分发安装
1. | 调用再分发程序包之前,请首先让您的安装例程安装您的应用程序文件,并进行所需的设置。 |
2. | 安装 。您可以使用 /Q:A 标志执行安静的无人参与安装,并在应用程序(例如: /Q:A )安装期间不显示再分发安装的用户界面。然后您的例程必须检测结束时是否需要重新启动重新启动。 |
命令行参数
将 作为应用程序的一部分进行安装时,管理员或开发人员可以通过使用下列命令,来控制安装 UI 显示和重新启动重新启动行为:
/Q:A
此命令指定无人参与安装,并且不出现任何 UI 或警告。
注 下一节中的代码示例说明了如何在程序包运行结束之后确定成功还是失败,以及是否需要重新启动。
检测 的安装状态
下面的代码可用于 Windows Media Format SDK runtime 再分发或 Windows Media Player 再分发程序包。
安装状态将作为 HRESULT 存储在下列位置:
HKCU, Software\Microsoft\MediaPlayer\Setup, REG_SZ, value InstallResult
HRESULT 值可用于确定安装是否成功以及是否需要重新启动。
下面的 C++ 示例代码可包含在一个调用安装应用程序中。此代码会根据组件再分发程序包中 Windows Media 安装写入的 HRESULT 值,将 fSuccess 和 fRebootNeeded 变量设置为合适的 true 或 false。
1#include <windows.h>
2#include <stdio.h>
3
4// If NS_S_REBOOT_REQUIRED is undefined, use 0xD2AF9.
5#ifndef NS_S_REBOOT_REQUIRED
6#define NS_S_REBOOT_REQUIRED 0xd2af9
7#endif
8
9int main( void )
10{
11 HKEY hKey = NULL;
12 BOOL fSuccess = FALSE;
13 BOOL fRebootNeeded = FALSE;
14
15if( ERROR_SUCCESS == RegOpenKeyExA(
2#include <stdio.h>
3
4// If NS_S_REBOOT_REQUIRED is undefined, use 0xD2AF9.
5#ifndef NS_S_REBOOT_REQUIRED
6#define NS_S_REBOOT_REQUIRED 0xd2af9
7#endif
8
9int main( void )
10{
11 HKEY hKey = NULL;
12 BOOL fSuccess = FALSE;
13 BOOL fRebootNeeded = FALSE;
14
15if( ERROR_SUCCESS == RegOpenKeyExA(
16 HKEY_CURRENT_USER,
17 "Software\\Microsoft\\MediaPlayer\\Setup",
18 0, KEY_QUERY_VALUE, &hKey ))
19 {
20 char szResult[64];
21 DWORD dwResult = sizeof( szResult );
22
23if( ERROR_SUCCESS == RegQueryValueExA(
24 hKey, "InstallResult", NULL, NULL,
25 (LPBYTE)szResult, &dwResult ) )
26 {
27 sscanf( szResult, "%x", &dwResult );
28 fSuccess = SUCCEEDED( dwResult );
29 fRebootNeeded = ( NS_S_REBOOT_REQUIRED == dwResult );
30 }
17 "Software\\Microsoft\\MediaPlayer\\Setup",
18 0, KEY_QUERY_VALUE, &hKey ))
19 {
20 char szResult[64];
21 DWORD dwResult = sizeof( szResult );
22
23if( ERROR_SUCCESS == RegQueryValueExA(
24 hKey, "InstallResult", NULL, NULL,
25 (LPBYTE)szResult, &dwResult ) )
26 {
27 sscanf( szResult, "%x", &dwResult );
28 fSuccess = SUCCEEDED( dwResult );
29 fRebootNeeded = ( NS_S_REBOOT_REQUIRED == dwResult );
30 }
31
32 RegCloseKey( hKey );
33 }
34
35 if( fSuccess )
36 {
37 printf( "Setup Succeeded" );
38 if( fRebootNeeded )
39 printf( "A restart IS required\n" );
40 else
41 printf( "A restart IS NOT required\n" );
42 }
43 else
44 {
45 printf( "Setup Failed" );
32 RegCloseKey( hKey );
33 }
34
35 if( fSuccess )
36 {
37 printf( "Setup Succeeded" );
38 if( fRebootNeeded )
39 printf( "A restart IS required\n" );
40 else
41 printf( "A restart IS NOT required\n" );
42 }
43 else
44 {
45 printf( "Setup Failed" );
46 if( fRebootNeeded )
47 printf( "A restart IS required\n" );
48 else
49 printf( "A restart IS NOT required\n" );
50 }
51
52 return 0;
53}
54
47 printf( "A restart IS required\n" );
48 else
49 printf( "A restart IS NOT required\n" );
50 }
51
52 return 0;
53}
54
如果要将再分发程序包包括在您的应用程序中,则当您在安装例程中调用该再分发程序包时,可以使用 /Q:A 标志。这样会抑制用户界面 (UI) 的显示。因为 程序包的设计意图就是为了用于软件再分发,所以该程序包会抑制自动重新启动,不会通过用户界面返回或通知用户重新启动情况。请确保使用返回注册表的信息来 执行下列操作:
• | 确定在运行 之后计算机是否需要重新启动。 |
• | 处理需要重新启动的情况,以及需要重新启动时与最终用户的通信。 |
下面的示例代码可在您的安装例程中用来以安静模式运行再分发程序包,并在计算机必须重新启动时通知您的安装例程。
1/**////////////////////////////////////////////////////////////////////////
2//
3// MUST ADD:
4//
5// You must add "shlwapi.lib" to your project settings (link)
6//
7/**////////////////////////////////////////////////////////////////////////
8
9#include <windows.h>
10#include <shlwapi.h>
11#include <TCHAR.H>
12#include <iostream>
13using std::cout;
14using std::endl;
15
2//
3// MUST ADD:
4//
5// You must add "shlwapi.lib" to your project settings (link)
6//
7/**////////////////////////////////////////////////////////////////////////
8
9#include <windows.h>
10#include <shlwapi.h>
11#include <TCHAR.H>
12#include <iostream>
13using std::cout;
14using std::endl;
15
16#define MAX_TIMEOUT_MS 30 * 60 * 1000
17#define TIME_INCREMENT 250
18
19// Prototypes
20BOOL GoInstallWMRedist( BOOL );
21BOOL SystemNeedsReboot( void );
22
23void main( void )
24{
25 GoInstallWMRedist( TRUE );
26
27 cout << "Setup is complete";
28
29 if( SystemNeedsReboot() )
30 {
17#define TIME_INCREMENT 250
18
19// Prototypes
20BOOL GoInstallWMRedist( BOOL );
21BOOL SystemNeedsReboot( void );
22
23void main( void )
24{
25 GoInstallWMRedist( TRUE );
26
27 cout << "Setup is complete";
28
29 if( SystemNeedsReboot() )
30 {
31 // Write some code here to ensure that your application will
32 // restart the computer, and delay dll registrations and so on
33 // until after the restart, where possible. For example,
34 // set a global flag for use by the application.
35 cout << "A restart IS required" << endl;
36 }
37 else
38 cout << "A restart IS NOT required" << endl;
39
40}
41
42/**////////////////////////////////////////////////////////////////////////
43//
44// Usage:
45//
32 // restart the computer, and delay dll registrations and so on
33 // until after the restart, where possible. For example,
34 // set a global flag for use by the application.
35 cout << "A restart IS required" << endl;
36 }
37 else
38 cout << "A restart IS NOT required" << endl;
39
40}
41
42/**////////////////////////////////////////////////////////////////////////
43//
44// Usage:
45//
46// Takes one parameter (BOOL)
47//
48// If you want to wait for completion, pass TRUE,
49// else pass FALSE.
50//
51/**////////////////////////////////////////////////////////////////////////
52BOOL GoInstallWMRedist( BOOL fWaitForCompletion )
53/**////////////////////////////////////////////////////////////////////////
54{
55 STARTUPINFO StartUpInfo;
56 PROCESS_INFORMATION ProcessInfo;
57
58 StartUpInfo.cb = sizeof( StartUpInfo );
59 StartUpInfo.lpReserved = NULL;
60 StartUpInfo.dwFlags = 0;
47//
48// If you want to wait for completion, pass TRUE,
49// else pass FALSE.
50//
51/**////////////////////////////////////////////////////////////////////////
52BOOL GoInstallWMRedist( BOOL fWaitForCompletion )
53/**////////////////////////////////////////////////////////////////////////
54{
55 STARTUPINFO StartUpInfo;
56 PROCESS_INFORMATION ProcessInfo;
57
58 StartUpInfo.cb = sizeof( StartUpInfo );
59 StartUpInfo.lpReserved = NULL;
60 StartUpInfo.dwFlags = 0;
61 StartUpInfo.cbReserved2 = 0;
62 StartUpInfo.lpReserved2 = NULL;
63 StartUpInfo.lpDesktop = NULL;
64 StartUpInfo.lpTitle = NULL;
65 StartUpInfo.dwX = 0;
66 StartUpInfo.dwY = 0;
67 StartUpInfo.dwXSize = 0;
68 StartUpInfo.dwYSize = 0;
69 StartUpInfo.dwXCountChars = 0;
70 StartUpInfo.dwYCountChars = 0;
71 StartUpInfo.dwFillAttribute = 0;
72 StartUpInfo.dwFlags = 0;
73 StartUpInfo.wShowWindow = 0;
74 StartUpInfo.hStdInput = NULL;
75 StartUpInfo.hStdOutput = NULL;
62 StartUpInfo.lpReserved2 = NULL;
63 StartUpInfo.lpDesktop = NULL;
64 StartUpInfo.lpTitle = NULL;
65 StartUpInfo.dwX = 0;
66 StartUpInfo.dwY = 0;
67 StartUpInfo.dwXSize = 0;
68 StartUpInfo.dwYSize = 0;
69 StartUpInfo.dwXCountChars = 0;
70 StartUpInfo.dwYCountChars = 0;
71 StartUpInfo.dwFillAttribute = 0;
72 StartUpInfo.dwFlags = 0;
73 StartUpInfo.wShowWindow = 0;
74 StartUpInfo.hStdInput = NULL;
75 StartUpInfo.hStdOutput = NULL;
76 StartUpInfo.hStdError = NULL;
77
78 // Run the installer with the Quiet for All and Reboot:Never
79 // flags. The installation should be silent, and the setup routine
80 // will be notified whether the computer must be restarted.
81
82 if( !CreateProcess( _T("c:\\temp\\"),
83 _T("c:\\temp\\ /Q:A"), NULL, NULL, FALSE,
84 0, NULL, NULL, &StartUpInfo, &ProcessInfo ) )
85 {
86 DWORD myError = GetLastError();
87 return( FALSE );
88 }
89
90 CloseHandle( ProcessInfo.hThread );
77
78 // Run the installer with the Quiet for All and Reboot:Never
79 // flags. The installation should be silent, and the setup routine
80 // will be notified whether the computer must be restarted.
81
82 if( !CreateProcess( _T("c:\\temp\\"),
83 _T("c:\\temp\\ /Q:A"), NULL, NULL, FALSE,
84 0, NULL, NULL, &StartUpInfo, &ProcessInfo ) )
85 {
86 DWORD myError = GetLastError();
87 return( FALSE );
88 }
89
90 CloseHandle( ProcessInfo.hThread );
91
92 if( fWaitForCompletion )
93 {
94 DWORD dwTimePassed = 0;
95 while( TRUE )
96 {
97 if( WAIT_TIMEOUT != WaitForMultipleObjects(
98 1, &ProcessInfo.hProcess, FALSE, TIME_INCREMENT ) )
99 break;
100
101 if( dwTimePassed > MAX_TIMEOUT_MS )
102 {
103 TerminateProcess( ProcessInfo.hProcess, E_FAIL );
104 break;
105 }
92 if( fWaitForCompletion )
93 {
94 DWORD dwTimePassed = 0;
95 while( TRUE )
96 {
97 if( WAIT_TIMEOUT != WaitForMultipleObjects(
98 1, &ProcessInfo.hProcess, FALSE, TIME_INCREMENT ) )
99 break;
100
101 if( dwTimePassed > MAX_TIMEOUT_MS )
102 {
103 TerminateProcess( ProcessInfo.hProcess, E_FAIL );
104 break;
105 }
106 dwTimePassed += TIME_INCREMENT;
107 }
108 }
109 CloseHandle( ProcessInfo.hProcess);
110
111 return( TRUE );
112}
113
114/**////////////////////////////////////////////////////////////////////////
115//
116// Used to determine whether the system should be restarted
117//
118/**////////////////////////////////////////////////////////////////////////
119BOOL SystemNeedsReboot( void )
120/**////////////////////////////////////////////////////////////////////////
107 }
108 }
109 CloseHandle( ProcessInfo.hProcess);
110
111 return( TRUE );
112}
113
114/**////////////////////////////////////////////////////////////////////////
115//
116// Used to determine whether the system should be restarted
117//
118/**////////////////////////////////////////////////////////////////////////
119BOOL SystemNeedsReboot( void )
120/**////////////////////////////////////////////////////////////////////////
121{
122 BOOL fNeedExists = FALSE;
123 OSVERSIONINFO osvi;
124
125 osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
126 GetVersionEx( &osvi );
127
128 if( VER_PLATFORM_WIN32_NT != osvi.dwPlatformId )
129 {
130 TCHAR szIniPath[MAX_PATH];
131
132 GetWindowsDirectory(szIniPath,
133 sizeof(szIniPath)/sizeof(TCHAR));
134 PathAddBackslash( szIniPath );
135 _tcscat( szIniPath, _T("wininit.ini") );
122 BOOL fNeedExists = FALSE;
123 OSVERSIONINFO osvi;
124
125 osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
126 GetVersionEx( &osvi );
127
128 if( VER_PLATFORM_WIN32_NT != osvi.dwPlatformId )
129 {
130 TCHAR szIniPath[MAX_PATH];
131
132 GetWindowsDirectory(szIniPath,
133 sizeof(szIniPath)/sizeof(TCHAR));
134 PathAddBackslash( szIniPath );
135 _tcscat( szIniPath, _T("wininit.ini") );
136
137 if( 0xFFFFFFFF != GetFileAttributes( szIniPath ) )
138 {
139 HFILE hFile;
140
141 if( (hFile =
142 _lopen(szIniPath,OF_READ|OF_SHARE_DENY_NONE))!=
143 HFILE_ERROR )
144 {
145 fNeedExists = ( 0 != _llseek(hFile, 0L, FILE_END) );
146 _lclose(hFile);
147 }
148 }
149 }
150sdk else
137 if( 0xFFFFFFFF != GetFileAttributes( szIniPath ) )
138 {
139 HFILE hFile;
140
141 if( (hFile =
142 _lopen(szIniPath,OF_READ|OF_SHARE_DENY_NONE))!=
143 HFILE_ERROR )
144 {
145 fNeedExists = ( 0 != _llseek(hFile, 0L, FILE_END) );
146 _lclose(hFile);
147 }
148 }
149 }
150sdk else
151 {
152 HKEY hKey = NULL;
153
154 if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
155 _T("System\\CurrentControlSet\\Control\\Session Manager"),
156 0, KEY_READ, &hKey ) )
157 {
158 if( ERROR_SUCCESS == RegQueryValueEx( hKey,
159 _T("PendingFileRenameOperations"),
160 NULL, NULL, NULL, NULL))
161 {
162 fNeedExists = TRUE;
163 }
164
165 RegCloseKey( hKey );
152 HKEY hKey = NULL;
153
154 if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
155 _T("System\\CurrentControlSet\\Control\\Session Manager"),
156 0, KEY_READ, &hKey ) )
157 {
158 if( ERROR_SUCCESS == RegQueryValueEx( hKey,
159 _T("PendingFileRenameOperations"),
160 NULL, NULL, NULL, NULL))
161 {
162 fNeedExists = TRUE;
163 }
164
165 RegCloseKey( hKey );
166 }
167 }
168
169 return( fNeedExists );
170}
167 }
168
169 return( fNeedExists );
170}
再分发 Windows Media Encoder 9 Series 软件
当 您分发基于 Windows Media Encoder SDK 的应用程序时,必须通过在安装中再分发 Windows Media Encoder,或者要求您的用户自行安装 Windows Media Encoder,将 Windows Media Encoder 软件也包括在内。
如果您要再分发 Windows Media Encoder,则必须在安装中包括并运行 安装文件。Microsoft 网站的下载中心中提供有此文件。如果您希望最终用户自行安装 Windows Media Encoder,则可以引导这些用户访问此网站。
默认情况下,Windows Media Encoder 安装在 C:\Program Files\Windows Media Components\Encoder 目录中。
命令行参数
下面几项内容显示了 常用的命令行参数。
对于不带 UI 的无人参与安装:
/Q:A
对于带有进度条的无人参与安装:
/Q
检测 Windows Media Encoder 9 Series
您可以通过搜索注册表的方式,确定所安装的 Windows Media Encoder 的版本:
HKLM, Software\Microsoft\Windows Media\Encoder, "Version"
在该编码器项下面,如果设置了 Version 字符串值,则可以放心地使用该字符串值作为所安装的 Windows Media Encoder 的版本。
您可以使用下列注册表项来确定 Windows Media Encoder 安装目录的位置:
HKLM, Software\Microsoft\Windows Media\Encoder, "InstallDir"
再分发 Windows Media Player 9 Series 软件
在应用程序中检测 Windows Media Player
您可以通过搜索注册表的方式,确定所安装的 Windows Media Player 的版本。
HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components
对于 Windows Media Player 6.4,请查看该项:
"{22d6f312-b0f6-11d0-94ab-0080c74c7e95}"
对于 Windows Media Player 7、Windows Media Player for Windows® XP 或 Windows Media Player 9 Series,请查看该项:
"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"
在上述任一项下面,如果 IsInstalledDWORD 值设置为 0x1,则可以放心地使用“Version”字符串值作为所安装的 Windows Media Player 的版本。
和 命令行参数
下面是几个常用的命令行参数。
对于不带 UI、不需要重新启动或没有重新启动提示的无人参与安装:
/q:A /c:" /Q:A /R:N /P:#e"
这是一个标准的命令行,通常应该用于执行无人参与安装。
防止媒体库移植:
/q:A /R:N /c:" /NoMigrate /P:#e"
对安装程序包进行缓存,用于以后的 Windows 升级移植:
/q:A /R:N /c:" /P:#e"
/P:#e 指定,在 Windows Media Player 安装过程中应该对 Windows Media Player 安装程序包进行缓存。在处理操作系统将来升级的所有命令行中,通常应该使用此参数。不应在命令行中包括 /P:#e 的唯一一种情况为,您知道目标系统永远不会升级为更高版本的操作系统。例如,如果您正在 Windows 2000 上安装 Windows Media Player 9 Series,并且该计算机在将来的某一天可能会升级为 Windows XP,则必须在命令行中使用 /P:#e。如果不使用此参数,则在 Windows XP 安装之后,Windows Media Player 9 Series 文件会被 Windows Media Player for Windows XP 的文件所覆盖。
对于安静模式:
/Q
此参数用于不带 UI 的无人参与安装。
取消重新启动提示:
/R:N
此参数表示永远不需要重新启动,也不出现提示。如果您忽略此命令,则无论是否已经安装该软件,播放器都会在安装结束时提示用户重新启动计算机。
创建嵌套的系统还原点:
/NestedRestore
如果您的应用程序创建的系统还原点会将 Windows Media Player 还原点嵌套在应用程序还原点中,请使用此参数。
不允许创建系统还原点
/DisallowSystemRestore
此标志会禁止系统还原点的创建。大多数情况下,对于一般的软件再分发方案都不应该使用此标志。只有当您可以代表最终用户作出明确选择, 不支持 Windows Media Player 9 Series 文件回滚到该播放器的更早版本时,才应该使用此标志。此标志只应在公司部署或者原始设备制造商 (OEM) 安装方案中使用。
注意
• | 命令行参数区分大小写。 |
• | 取消重新启动提示时,必须检查 InstallResult 注册表项,并处理调用安装应用程序中的重新启动通知。 |
• | Windows Media Player 9 Series 还会安装 Windows Media Format runtime,因此无需将 Media Player 9 Series 分发程序包和 Windows Media Format Runtime 分发程序包同时包括在一个软件再分发程序包中。例如,如果您在安装中包括了 或 ,则无需包括 。 |
检测 和 的安装状态
下面的代码可用于 Windows Media Player 再分发程序包。
安装状态作为 HRESULT 存储在下列位置:
HKCU, Software\Microsoft\MediaPlayer\Setup, REG_SZ, value InstallResult
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论