为WindowsXPEmbedded创建自定义组件

转自:http://www.chinaitpower.com/A/2004-06-11/83197.html   

luckyhm 推荐
jiazhengod 20071015

简介

  有多种为 Microsoft Windows XP Embedded 创建自定义组件的方法。例如,可以将导入设备驱动程序 .inf 文件直接导入到 Component Designer 工具中(与 Microsoft Windows NT Embedded 4.0 相比,这是一项巨大的进步)。可以通过导入 Devices.pmq(Target Analyzer Probe (TAP) 或 Target Analyzer (TA) 的输出)来创建组件 — 到目前为止一切顺利 — 但是如何创建能够描述自定义应用程序的组件呢?
  
  出于本文的目的,我决定构建一 种安全设备,它使用 TimerShot Windows XP PowerToy — 一种非常酷的应用程序,可以从连接的映像设备捕获映像,并且将该映像存储到预设的位置 — 我的本地硬盘上,或者网络共享上(在本文末尾可以找到指向 Windows XP PowerToy 的链接)。可以将 TimerShot 配置为每数秒钟或每数分钟抓取一个映像;所有这些都在应用程序内部配置,并且存储在 Windows XP 注册表中。我还将包含另一个名为“PhotoDisplay”的应用程序,它是我专门为本文编写的。PhotoDisplay 可用来查看已存储的 JPEG 文件。
  
  遗憾的是,没有任何工具可以自动完成为应用程序生成 Windows XP Embedded 组件的过程 — 需要进行一些侦探工作。因此,我将摆脱猎鹿人,叫上我的朋友华生医生(这里是双关语),并且开始工作。
  
   安装选项
  在构建 Windows XP Embedded 设备时,可以使用多种用于添加第三方应用程序/技术的选项。这些选项主要取决于设备的硬件配置以及用于制造发行设备的方法。
  
   在构建从 R/W 媒体(通常是硬盘)中启动并且包含 CD-ROM/DVD-ROM 驱动器、显示器、键盘和鼠标的设备时,将具有最大的灵活性。在该配置中,可以直接在 Embedded Target 上运行第三方安装程序,这将直接在目标设备上复制和配置应用程序。如果要构建一次性的设备,或者如果要在 Windows XP Embedded 上测试应用程序以确保所有必需的操作系统组件都存在(将在下面讨论),则该选项很有用。
  
  另一个选项是生成 Windows XP Embedded 映像(通常是生成到 /Windows Embedded Images 文件夹中),再将必需的应用程序/资源手动添加到生成文件夹中。然后,可以将 Windows XP Embedded 操作系统映像(以及应用程序/资源)复制到可启动的媒体,并且随后可以对应用程序进行测试。这仅适用于不要求注册 COM 对象或安装基础操作系统服务的简单应用程序。
  
  最好的方法是创建一个满足以下条件的组件:可以在 Target Designer 内部使用该组件,并且可以像任何其他 Windows XP Embedded 组件一样选择该组件。如果您已经在多用户情况中安装了 Windows XP Embedded 工具,则这是一种理想的选项。但是,这需要完成一些工作。让我们分析一下如何安装应用程序,以及通常修改操作系统的哪些部分。
  
  安 装程序的形式和大小各不相同,既可以是简单的 xcopy、IExpress,也可以是要求用户提供注册信息并且可能发行多张 CD/DVD 的 GUI 安装程序。安装程序可能安装数据库引擎或操作系统服务、设备驱动程序或支持 DLL,并且可能对操作系统注册表或 INI 文件进行更改 — 在某些情况下,所安装的文件可能被安装到 PC 上的多个文件夹中:用于存放核心应用程序的 Program Files,用于存放设备驱动程序的“/Windows/System32”,或者其他取决于安装程序的文件夹。要确定应该在您的 Windows XP Embedded 组件中包含哪些内容,乍看起来似乎并不是一件普通的工作。令人欣慰的是,有一些工具和技术可以为您提供协助。
  
  下一部分将对在确定要在 Windows XP Embedded 组件中包含哪些文件/注册表设置和操作系统组件时需要的工具进行高级概述。
  
   侦探工具包
  本部分概述了在生成自定义 Windows XP Embedded 组件时需要的工具。
  
  在生成和测试组件时,需要两组工具。其中一些工具将运行在开发 PC 上,而其他工具将包含在目标设备上以调试应用程序或组件。让我们将这些工具划分为上述两个类别,然后考察一下每种工具的使用方法。
  
   在开发 PC 上使用的工具
   虽然无法更改应用程序的安装程序的行为,但是可以监控操作系统以判断安装应用程序后产生了哪些更改。可以使用许多工具来协助完成这一过程。因为某些安装 程序在安装过程中 要求重新启动,所以理想情况下应该使用能够在重新启动以后监控 PC 的文件系统和注册表中的更改的工具。诸如 Inctrl5 (ZDNet)、SysDiff (Microsoft) 之类的应用程序在安装应用程序之前 获取文件系统和注册表的快照,然后在安装之后 获取文件系统和注册表的快照,并且提供有关二者之间差异的报告 — 这可以协助确定应该在组件中包含哪些文件。请注意,在安装应用程序时已经在运行的应用程序和服务也可能对文件系统和注册表进行更改。
  
  下面是已在我的开发 PC 上使用的工具列表,从而确定应该在我的自定义组件中包含哪些文件/注册表项 — 我将通过本文稍后介绍的过程中的各个步骤来解释每种工具的用法。
  
  • InCtrl5 — 用于获取文件系统和注册表的快照,并且提供差异列表 (ZDNet)
  
  • Dumpbin — 用于确定应用程序/DLL 使用了哪些 DLL (Microsoft Visual Studio .NET)
  
  • Depends — 也可以用于确定应用程序使用了哪些 DLL(以及 API)
  
  • RegMon — 动态监控对注册表所做的更改 (NT System Internals)
  
  • FileMon — 动态监控文件系统 (NT System Internals)
  
  • Windows XP Embedded 开发工具 — Target Analyzer Probe、Component Designer、Component Database Manager、Target Designer
  
   在目标设备上使用的工具
   使用上述工具来确定需要哪些文件和注册表项只是难题的一部分。在已经生成 Windows XP Embedded 映像之后,应用程序还将需要接受测试以确保它能够按预期工作 — 应用程序有可能动态加载 DLL 或者创建 COM 对象的实例,但无法使用 Dumpbin 或 Depends 捕获这些信息。因此,在目标设备上需要一些调试工具。下面是已在我的目标设备上使用的工具列表(在部署最终的操作系统映像之前,应该删除这些工具)。
  
  • RegMon — 动态监控对注册表所做的更改 (NT System Internals)
  
  • FileMon — 动态监控文件系统 (NT System Internals)
  
  在下一部分中,我将演练这些工具的用法。
  
   综述
  过程概述
  
   首先,让我们扼要重述安全设备并列出可用的组件。我们的计划是基于 Windows XP Embedded 生成安全设备。在该例中,我将使用 Toshiba Tecra 9000 膝上型电脑作为我的开发 PC,使用 Logitech USB Camera 和 Windows XP Embedded TimerShot PowerToy(有关该组件的下载位置,请参见本文末尾的链接)作为我的目标设备,并且使用前面提到的侦探工具包。
  
   Toshiba 膝上型电脑具有两个硬盘分区。主分区包含 Windows XP Professional 以及我的所有开发工具(Windows XP Embedded、Visual Studio .NET 等等),并且被格式化为 NTFS。我还具有一个大小为 700MB 的辅助分区(大小大概与光盘相等),并且被格式化为 FAT32。我已经修改了我的 BOOT.INI(它驻留在可启动驱动器的根目录中,以便为 Windows XP Embedded 添加辅助启动选项 — 注意,Boot.ini 被配置为具有 System 和 Hidden 属性) — Boot.ini 如下所示:
  
  [boot loader]
  timeout=30
  default=multi(0)disk(0)rdisk(0)partition(1)/WINDOWS
  [operating systems]
  multi(0)disk(0)rdisk(0)partition(1)/WINDOWS="Microsoft Windows XP
   Professional" /fastdetect
  multi(0)disk(0)rdisk(0)partition(2)/WINDOWS="Microsoft Windows XP
   Embedded" /fastdetect
  
   在启动时,我得到了两个选项:启动到 Windows XP Professional(在我的主分区上),或者启动到我的 Windows XP Embedded 映像(在我的辅助分区上)。在 30 秒钟的超时以后,默认选项是启动到 Windows XP Professional。
  
  步骤 1 — 从安装程序中捕获信息
   创建自定义组件的第一步是确定应用程序所需的文件和注册表设置。安装程序和侦探工具应该在 Windows XP Professional 上运行。可以针对完全配置的操作系统映像来运行和测试应用程序 — 本文稍后将针对 Windows XP Embedded 测试应用程序。
  
   Windows XP PowerToys Web 站点列出了一些 PowerToy;单击相应的链接以下载某个 PowerToy 时,将提示您选择 Open、Save、Cancel 或 More Info。单击“Save”可将 TimershotPowertoySetup.exe 程序保存到硬盘上。注意,选择“Open”时将下载并安装 PowerToy。此时,不需要捕获安装过程中的信息。
  
  还将需要文件系统和注册表快照工具。出于本文的目的,我已经选择使用 ZDNet 提供的 Inctrl5,尽管还可以使用许多类似的工具。
  
  以下为 Inctrl5 的外观:安装程序的位置被插入(在我的示例中为 c:/stuff/XP-PowerToys/TimershotPowertoySetup.exe),报告输出位置被更改为指向我的安装文件夹,然后我单击 GO!。
  
 

  
图" 1.

  InCtrl5 捕获我的开发 PC 的注册表和文件系统的快照,然后启动 PowerToy 安装程序。安装过程完成后,将获取第二个快照,并且生成一个报告。
  
   经过编译的报告将列出对文件系统、注册表、INI 文件和文本文件(autoexec.nt 和 config.nt)所做的全部 更改 — 对于安装 PowerToy 的情况,该报告包含在安装 PowerToy 时正在运行的其他应用程序对文件系统和注册表所做的更改。该报告还包含用于卸载 PowerToy 的注册表项和文件。因为我要构建嵌入式设备并且不希望用户删除该应用程序,所以我可以忽略卸载信息。
  
  让我们查看一下由于安装 PowerToy 而对我的系统造成的一些更改。
  
  注册表
  
  添加了 17 个注册表项,包括:
  
  HKEY_CLASSES_ROOT/Installer/Products/CCBB347A83433BB43879C6D9A91C526A
  
  这显然将由 PowerToy 的卸载程序使用,并且可以忽略。还添加了一些附加的子项;同样,它们可以忽略。
  
  向注册表中添加了 138 个值,包括:
  
  HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Explorer RecentDocs/.bmp
  
  在安装 PowerToy 的过程中,我正在撰写和保存本文,所以一些注册表值是由于我继续工作而被更改的。
  
  HKEY_CLASSES_ROOT/Installer/Products/CCBB347A83433BB43879C6D9A91C526A
  
  一些由卸载过程使用的值已经被添加到注册表中 — 这些值可以忽略,因为我不希望用户删除该应用程序。
  
  奇怪的是,没有列出任何 TimerShot 注册表项。因此,可以假设 TimerShot PowerToy 在运行时检查是否存在可选的注册表项,如果不存在这样的注册表设置,则使用默认选项。
  
  文件
  
   现在讨论文件。以下是在 TimerShot PowerToy 安装过程中更改的文件的清单(摘自 Inctrl5 报告)— 您可以看到大多数文件都被安装/卸载过程使用。有趣的行是 timershot.exe;它已被安装到 /Windows/System32 文件夹中。
  
  c:/Documents and Settings/All Users/Start Menu/Programs/Powertoys for
   Windows XP/Timershot.lnk
  Date: 4/29/2002 4:53 AM
  Size: 1,641 bytes
  c:/WINDOWS/Downloaded Installations/Timershot Powertoy for Windows XP.msi
  Date: 4/29/2002 4:53 AM
  Size: 411,684 bytes
  c:/WINDOWS/Installer/2a1e66.msi
  Date: 4/29/2002 4:53 AM
  Size: 349,696 bytes
  c:/WINDOWS/Installer/{A743BBCC-3438-4BB3-8397-
   6C9D9AC125A6}/ARPPRODUCTICON.exe
  Date: 4/29/2002 4:53 AM
  Size: 22,486 bytes
  c:/WINDOWS/Installer/{A743BBCC-3438-4BB3-8397-6C9D9AC125A6}/Readme_1.htm
  Date: 4/29/2002 4:53 AM
  Size: 318 bytes
  c:/WINDOWS/Installer/{A743BBCC-3438-4BB3-8397-
   6C9D9AC125A6}/Timershot_1.exe
  Date: 4/29/2002 4:53 AM
  Size: 22,486 bytes
  c:/WINDOWS/system32/timershot.exe
  Date: 3/19/2002 5:30 PM
  Size: 192,000 bytes
  d:/System Volume Information/_restore{1FE94AF8-3502-4A8F-8658-
   25737CDB40DE}/RP46/change.log.1
  Date: 4/29/2002 4:53 AM
  Size: 496 bytes
  d:/System Volume Information/_restore{1FE94AF8-3502-4A8F-8658-
   25737CDB40DE}/RP46/RestorePointSize
  Date: 4/29/2002 4:53 AM
  Size: 8 bytes
  
  注 此时,我拥有了应用程序的文件清单。这当然可能包括一些可执行文件和 DLL。
  
  步骤 2 — 注册表设置
   许多可由用户配置的选项,包括拍照的计时器时间间隔、输出文件的位置以及输出映像的大小。此刻我所不了解的是选项在注册表中的位置(我假设应用程序将其 配置信息存储在注册表中,应用程序可以使用 WritePrivateProfileString 同样容易地将配置信息存储在 INI 文件中)。
  
  以下为 TimerShot 应用程序具有的外观,包括一些可由用户配置的选项(注意,我已经截去了一些选项,以便减小文档中位图的大小)。
  
 

  
图" 2.

   我可以猜测 TimerShot PowerToy 所使用的注册表项的名称 — 可能是 TimerShot 或 PowerToy,并且我可以使用 RegEdit 搜索注册表项。但是,一些注册表项可能在注册表内部发生更改,包括一些与 Logitech Camera 相关联的注册表项。因此,此时我具有一些选项:
  
  1.我可以运行快照软件,安装并运行 TimerShot PowerToy,对 PowerToy 选项进行更改,然后让我的快照软件列出差异。
  
  2.我还可以对注册表进行更改,并且在运行时监控更改。这正是可以使用 SysInternals RegMon 实用工具的时机。RegMon 截获对注册表的读写请求,并且在其报告窗口中列出这些请求。
  
   我可以通过运行 RegMon 实用工具来确定程序在运行时所使用的注册表项,接着运行应用程序 TimerShot;然后,我对应用程序的选项进行更改,并且使用 RegMon 来监控已经更改的注册表项。以下为正在运行的 RegMon。我已经将 TimerShot 计时器时间间隔从 10 分钟(默认值)更改为 5 秒钟。请注意,下列注册表项已经更改。
  
  HKEY_CURRENT_USER/Software/Microsoft/Powertoys for XP/TimerShot
  
 

  
图" 3.

  注 此时,我拥有了应用程序所需的文件清单和注册表项。
  
  步骤 3 — 应用程序依赖项
   应用程序二进制文件 (EXE/DLL) 以及用于该应用程序的注册表项的名称和位置现在已经知道了。此时不知道的是该应用程序所使用的核心操作系统文件。这时使用 dumpbin(Visual Studio .NET 附带的命令行工具)或 Depends(Web 可下载工具 — 有关详细信息,请参见本文末尾的链接)将会很方便。
  
  下面,您可以看到实际运行的 depends.exe。在应用程序的左上窗格中,您可以清楚地看到必需的 DLL 的列表。该列表包括 KERNEL32.DLL、GDI32.DLL、USER32.DLL(到目前为止还没有令人感到惊讶)、MSVCRT.DLL 和 SHLWAPI.DLL — 它具有一些依赖项,包括 OLE32.DLL、APPHELP.DLL、MLANG.DLL。
  
 

  
图" 4.

  注 此时,我拥有了应用程序所需的文件清单和注册表项。
  
  步骤 3 — 应用程序依赖项
   应用程序二进制文件 (EXE/DLL) 以及用于该应用程序的注册表项的名称和位置现在已经知道了。此时不知道的是该应用程序所使用的核心操作系统文件。这时使用 dumpbin(Visual Studio .NET 附带的命令行工具)或 Depends(Web 可下载工具 — 有关详细信息,请参见本文末尾的链接)将会很方便。
  
  下面,您可以看到实际运行的 depends.exe。在应用程序的左上窗格中,您可以清楚地看到必需的 DLL 的列表。该列表包括 KERNEL32.DLL、GDI32.DLL、USER32.DLL(到目前为止还没有令人感到惊讶)、MSVCRT.DLL 和 SHLWAPI.DLL — 它具有一些依赖项,包括 OLE32.DLL、APPHELP.DLL、MLANG.DLL。
  
 

  
图" 5.

  注 此时,我拥有了文件、注册表项和必需的 DLL 的列表 — 下一步是生成该组件。
  
  步骤 4 — 生成该组件
   生成该组件与生成任何其他组件没有什么不同。我拥有必需文件的列表,我知道需要添加哪些注册表项,并且我具有组件依赖项(基于 dumpbin/depends 输出的依赖文件列表)。有关组件设计和开发的详细信息,请参阅 Windows XP Embedded 联机文档或 MSDN 联机文档。
  
  对于自定义组件,有一些需要考虑的问题。例如,可能有一些 COM 对象或 Microsoft ActiveX 控件需要首先注册,然后才能供核心应用程序使用。(您可以使用 Dumpbin/EXPORTS 命令来分析 DLL 的导出,以确定相应的组件是否为 COM/ActiveX 组件。如果公开了函数 DllRegisterServer、DllUnRegisterServer 和 DllCanUnloadNow,则应该是 COM 对象或 ActiveX 控件。)First Boot Agent (FBA) 可用于注册 COM 对象。这是通过组件资源启用的。请观察下面的 Component Designer 屏幕快照,您可以看到许多可以启用的自定义资源,包括 FBA COM/DLL Registration、快捷方式的创建等等。Windows XP Embedded 文档提供了有关如何使用 FBA 命令的概述 — 请在《系统设计指南》中查找 Windows XP Embedded 主题 — 附录信息 — 自定义资源。
  
 

  
图" 6.

   您可能正在纳闷 First Boot Agent 完成哪些工作。在创建了 Windows XP Embedded 映像并将其部署到设备上之后,设备第一次打开就可建立首次启动。此时,First Boot Agent (FBA) 可以执行下列系统配置任务:
  
  • 无法使用 Target Designer 脱机执行的任务,例如使用“即插即用”进行的设备检测和配置
  
  • 在运行时执行更为切实可行的任务,如注册组件对象模型 (COM) 服务器
  
  步骤 5 — 生成 Windows XP Embedded 操作系统映像
   生成 Windows XP Embedded 映像非常简单。我已经完成了基于 Target Analyzer Probe (TAP) 的输出创建组件的过程,包括 Logitech Camera 的驱动程序。但是,我需要向项目中添加一个小型的组件列表。这些组件包括:
  
  • Tecra9000 — 包括 Logitech WebCam(从 TAP 的输出创建的组件)
  
  • TimerShot(刚刚在 Component Designer 中创建的组件)
  
  • 设计模板之一(我选择了 Information Appliance)。
  
  • FAT 组件,位于 Software | System | Storage and File Systems | Infrastructure | File Systems 下。
  
  • FAT Format 组件,位于 Software | System | Storage and File Systems | Applications 下。
  
  • Explorer Shell 组件,位于 Software | System | User Interface | Shells 下。
  
  • 您必须包括一个 OS Loader。选择 Windows NT Loader 组件,位于 Software | System | System Services | Base 下。
  
  • English Language 组件,位于 Software | System | International | Infrastructure | English Language Support 下。
  
   • 我还添加了 Windows Image Acquisition User Interface 组件,它位于 Software | System | Printing & Imaging | Applications 下。我希望使用 Control Panel Scanners & Cameras 小程序(它是通过 Windows Image Acquisition User Interface 组件启用的)在 Windows XP Embedded 映像上充分测试 Logitech Camera。添加该组件可以提供测试照相机的能力,而无须运行 TimerShot 应用程序;一旦我知道照相机可以正常工作,我就可以继续前进以运行应用程序。如果需要,可以测试照相机,然后可以删除该控制面板小程序,并且可以重新生成 操作系统映像。
  
  • 我还需要对项目工作区内部的 User Interface Core | Settings 进行更改,以启用 Start 菜单上的控制面板。
  
 

  
图" 7.

  注 此时,我可以生成操作系统映像(有关配置和生成 Windows XP Embedded 操作系统映像的详细信息,请参阅 Target Designer 联机帮助)。
  
   在 Windows XP Embedded 内测试应用程序
  需要对应用程序进行测试,以确保所有组件都能按预期正常工作。应该在 Windows XP Embedded 映像中包含一些工具,以便为部署自定义应用程序的测试/调试阶段提供帮助。
  
  TimerShot 应用程序在 Windows XP Embedded 上运行非常良好。下面是它在运行时具有的外观:
  
 

  
图" 8.

   测试应用程序的第一步是简单地在 Windows XP Embedded 上运行应用程序,并查看哪些组件能够正常工作(更为重要的是,哪些组件不能正常工作)。如果所有组件都能正常工作,则测试完成。然而,事实很可能是缺少一 个或多个必需的资源。这些资源可能是尚未注册的 COM 对象、规则 DLL、辅助应用程序 (EXE) 和资源文件(数据文件、位图、.wav 文件等等),或缺少的注册表项。如何确定缺少哪些资源呢?此时可以使用 SysInternals 工具 FileMon 和 Regmon。您在这时有多个选项;可以为 Target Designer 创建一个工具箱组件,并在其中包括 RegMon 和 FileMon 应用程序(首选),也可以生成您的 o/s 映像(通常生成到 /Windows Embedded Images 文件夹中)并且将 FileMon/Regmon 文件放入您的生成文件夹中。然后,当您将 Windows XP Embedded 操作系统映像复制到可启动的媒体并且启动 o/s 时,就可以使用这些应用程序。
  
  因为我在生成 TimerShot 组件前配置了 TimerShot 应用程序的选项,所以您已经了解了如何使用 RegMon 来跟踪对注册表所做的更改。我可以在 Windows XP Embedded 设备上使用 RegMon 来跟踪对注册表进行的读/写操作,这有助于确定要运行该应用程序需要哪些附加的注册表项。例如,您可以在目标设备上启动 RegMon,然后启动 TimerShot 应用程序,并且查看在启动时从注册表中读取的项。对于任何不存在于设备注册表中的项,RegMon 都将报告 NOTFOUND。
  
   FileMon 工具可用来跟踪缺少的文件和 DLL — 我已经向我的 Windows XP Embedded 设备中添加了两个应用程序:TimerShot(它可以从 Logitech Camera 中捕获 JPEG 图像)和“PhotoDisplay”;我还添加了一个 MFC 应用程序,它是用 Visual Studio .NET 编写的,并且具有用于在应用程序工作区中显示 JPEG 文件的外部支持 DLL。当我运行 PhotoDisplay 应用程序时,我收到了以下含义隐晦的消息:
  
 

  
图" 9.

   我知道因为缺少某个必需的 DLL,应用程序将无法正常工作。我无法确定缺少哪个 DLL,但是我可以运行 Depends 或 Dumpbin 来列出静态链接的 DLL(以及所有似乎包含在我的 Windows XP Embedded 映像中的组件)。我不知道正在动态加载哪些 DLL(或 COM 对象),但是我可以使用 RegMon 来跟踪正在由 PhotoDisplay 应用程序加载的文件。下面是正在我的 Windows XP Embedded 目标设备上运行的 FileMon 的快照。注意,我已经突出强调了那个显示有试图加载 DispImage.DLL 的 PhotoDisplay 应用程序的部分。该 DLL 没有包括在 Windows XP Embedded 映像中,因此无法被应用程序加载。要修复该应用程序,我只需要将 DispImage.DLL 文件添加到 Windows XP Embedded 映像中(通过更新我的 PhotoDisplay 组件)。
  

  
图" 10.

  注 此时,我已经为 TimerShot 应用程序创建了一个组件,包括在 Windows XP Embedded 设备上运行 TimerShot 应用程序所需的所有文件和注册表项。
  
   小结
   要为应用程序生成 Windows XP Embedded 组件,需要完成一些工作并使用一些工具。在本文中,我重点介绍了为 Windows XP Professional PowerToy TimerShot 生成组件所需的一般性步骤;用于生成该组件的原理和工具与用于为较大的应用程序生成组件的原理和工具完全相同。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值