WinPE:创建应用

原始设备制造商 (OEM) 已获 Windows PE (WinPE) 授权,可使用它创建自定义部署和恢复实用工具。 本主题将指导 OEM 开发在 Windows PE 中运行的部署和恢复应用。

注意 Windows PE 并不是一个常规用途的操作系统。 除部署和恢复外,它不能用于其他任何目的。 不应将其用作瘦客户端或嵌入式操作系统。

可扩展性

大多数 Windows PE 应用是固定功能的 shell 应用,它们提供自己的 GUI。 Windows 安装程序应用和 Windows 恢复环境 (Windows RE) 是其中的两个示例。

  • 如果可以接受显示命令提示符,则修改 Startnet.cmd - 这是自动启动应用的最便捷方式。 请参阅 WinPE:装载和自定义

  • 若要让应用绕过命令行并在 GUI 中启动,请使用 Winpeshl.exe、Wpeinit.exe、wpeutil.exe 和 wpeutil.dll。

Winpeshl.exe、Wpeinit.exe、wpeutil.exe 和 wpeutil.dll

默认情况下,Winpeshl.exe 是 Windows PE 启动时运行的第一个进程。 这是由以下 REG_SZ 类型的注册表值指定的。

HKEY_LOCAL_MACHINE
   System
      Setup
         CmdLine

Winpeshl.exe 搜索名为 Winpeshl.ini 的文件。 如果该文件不存在,Winpeshl.exe 会启动一个执行 Startnet.cmd 脚本的 Cmd.exe 进程。 如果 Winpeshl.ini 存在并且包含要启动的应用,则会执行这些应用而不是 Cmd.exe。

Wpeinit.exe 安装即插即用 (PnP) 设备,启动网络堆栈,并在 Windows PE 启动时处理 Unattend.xml 设置。 有关详细信息,请参阅 Wpeinit 和 Startnet.cmd:使用 WinPE 启动脚本

通过允许在 Windows PE 启动时运行 Wpeinit.exe 或通过运行 Wpeutil 命令行选项命令,可以随时启动网络。

自定义 shell 应用可以使用 LoadLibraryGetProcAddress 函数直接调用 Wpeutil.dll。

Wpeutil.dll 导出的每个函数都具有与 WinMain Function 相同的函数签名,如以下代码示例所示。

int InitializeNetworkingW(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);

以下代码示例演示如何初始化网络。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
typedef int (*WpeutilFunction)( 
HINSTANCE hInst, 
HINSTANCE hPrev, 
LPTSTR lpszCmdLine, 
int nCmdShow 
);
int __cdecl _tmain( int argc, TCHAR *argv[] )
{
    
HMODULE         hWpeutil          = NULL;
    
WpeutilFunction InitializeNetwork = NULL;
    
int             result            = 0;
    
TCHAR           szCmdLine[]       = _T("");
    
hWpeutil = LoadLibrary( _T("wpeutil") );
    
if( NULL == hWpeutil )
    
{
        _tprintf( _T("Unable to load wpeutil.dll \ n") );
        
return GetLastError();
}
    
InitializeNetwork = (WpeutilFunction)GetProcAddress( 
hWpeutil, 
"InitializeNetworkW" 
);
    
if( NULL == InitializeNetwork )
    
{
        
FreeLibrary( hWpeutil );
        
return GetLastError();
    
}
    
result = InitializeNetwork( NULL, NULL, szCmdLine, SW_SHOW );
    
if( ERROR_SUCCESS == result )
    
{
        _tprintf( _T("Network initialized. \ n") );
    
}
  
else
    
{
        _tprintf( _T("Initialize failed: 0x%08x"), result );
    
}
    
FreeLibrary( hWpeutil );

return result;}

有关 Wpeutil.dll 导出的完整列表,请参阅 Wpeutil 命令行选项

Visual Studio 项目设置

某些基本的 Visual Studio 项目设置可能与 Visual Studio 项目向导创建的默认设置不同。 请确保设置项目的生成设置,以生成与 Windows PE 兼容的应用和 DLL,如下所示:

  1. 必须通过不使用 MFC 或 ATL 的本机 C 或 C++ 代码开发 Windows PE 应用。 因此,如果使用 Visual Studio 项目向导,请选择 Win32 项目并确保未选中 MFC 和 ATL。

  2. 将项目选项设置为链接到静态 C/C++ 运行时库,而不是 .dll 版本的 Msvcrt.dll。

  3. 打开项目属性并将“配置属性”\“C/C++ 运行时库”设置为“多线程”或“多线程调试”,而不是设置某个 .dll 版本。 如果不执行此步骤,应用可能无法在 Windows PE 上运行。

  4. 如果计划在 64 位版本的 Windows PE 上托管应用,请将项目生成选项设置为使用 Visual Studio 中的 x64 编译器编译所有二进制文件。

  5. 如果计划在 32 位版本的 Windows PE 上托管应用,请将项目选项设置为使用 x86 编译器进行编译。

  6. 确保项目未设置 /clr: 编译器选项。 此选项生成托管 C++ 代码,该代码不会在 Windows PE 上运行。

警告 应用可以使用你编写或从第三方获得许可的自定义 .dll 文件。 将这些 .dll 文件添加到适用于 Windows PE 的应用。 但是,不要使用 Msvcrt.dll,也不要包含不属于 Windows PE 的其他 Windows .dll 文件。

API 兼容性参考

Windows PE 是一个轻量级的启动操作系统,它基于 Windows 操作系统的组件子集。 它旨在托管部署和恢复应用。 因此,它包含许多 Windows 二进制文件,托管对这些类别的应用最重要的 API 时需要这些二进制文件。 由于大小和其他设计限制,Windows PE 并未包含所有 Windows 二进制文件,因此并非所有 Windows API 都存在或可用。

Windows PE 中支持的 API

Windows PE 支持以下 API:

  1. Windows API 集 (Mincore.lib)

  2. 部署映像维护和管理 (DISM) API (Dismapi.lib)

  3. Windows 映像 API (Wimgapi.lib)

如果某个 API 的行为与其在完整 Windows 操作系统上的行为相同,并且在适用于 Windows 操作系统的 Windows SDK 中有所记载,那么除非另有说明,否则将其视为受支持并可供应用使用。 由于 Windows PE 基于 Windows 中的组件,因此它包含在适用于 Windows 操作系统的 Windows SDK 中发布的 Windows API 的重要子集。 这些受支持的 API 的参数、调用约定和行为将与完整 Windows 操作系统上的相同或几乎相同,除非它们受到独特 Windows PE 环境的影响。 仅使用这些 API 的应用应该可以在完整的 Windows 操作系统和 Windows PE 之间移植。

在某些情况下,一部分可能的参数值将在 Windows PE 上可用。 这可能是由于运行时环境特有的条件造成的,例如在只读介质上运行、无法访问持久状态或其他设计限制。 在这种情况下,该 API 可能不受支持,但如果没有其他替代方案,仍然可以使用它完成特定任务。

通常,如果某个 API 在 Windows PE 上不能正常工作或根本不工作,则表示不支持且不得使用该 API,即使它驻留在 Windows PE 包含的二进制文件中也是如此。 该 API 可能会失败,是因为 Windows PE 是 Windows 操作系统的子集,或者是因为 Windows PE 特有的运行时设计考虑。 此类故障在 Windows PE 中不被视为 bug。

由于 Windows PE 不包含许多 Windows 组件,因此许多 API 不可用。 它们可能完全丢失,因为它们所在的 Windows 二进制文件不存在。 或者,它们可能只是部分存在,因为尽管它们所在的 Windows 二进制文件存在,但它们所依赖的一个或多个二进制文件却不存在。 此外,Windows PE 中的某些 API 无法正常工作,并且其行为与在 Windows 中不同。 这些 API 不受支持且不得使用,因为未定义它们在 Windows PE 上的行为。

有时,可能没有合适的 API 来完成特定任务。 为了找到替代解决方案,你需要使用不同的应用逻辑、不同的算法设计或重新定义基础问题。

适用于 Windows 10 的 WinPE

WinPE:调试应用