无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 16314|回复: 18
打印 上一主题 下一主题

[分享] 【技术·水】浅谈Windows10的CompactOS特性

  [复制链接]
跳转到指定楼层
1#
发表于 2016-8-17 22:22:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
================================注释开始================================
先开始发到吾爱,没达到预期效果;于是发到我认为最适合发布的地方(无忧)
本贴可以任意转载引用;如果能告知楼主一声最好

感谢不离不弃的包子,zifeityzyicq和ART-Master

本技术贴原名《【水·技术】浅谈Windows 10 Build 9879的磁盘清理的System Compression》
远景地址:http://bbs.pcbeta.com/viewthread-1567726-1-1.html
================================注释结束================================

一:前言

上次,我在远景发布了《【水·技术】浅谈Windows 10 Build 9879的磁盘清理的System Compression》;
虽然文笔稚嫩(可以算黑历史了),但依旧上了远景首页

这个帖子发布了快两年了,这个世界也有了不少变化

Windows10早已从Build 9879进入到了Build 14901;
System Compression也改名为CompactOS;
Windows10下可以使用compact命令行工具;Win7/8/8.1也有Dism++可以帮你;
MSDN也公开了CompactOS的调用方法

在这样的情形下,我打算写个总结帖子

二:CompactOS原理

CompactOS是通过Windows Overlay Filter过滤驱动实现的,该过滤驱动同时也负责WIMBoot的实现

CompactOS在一般人看来如同NTFS压缩和Bitlocker加密一样是透明的
但是CompactOS可以选用压缩率更高的用于压缩WIM文件的算法,你可以使用以下算法

XPRESS4K(WIMBoot压缩算法,CompactOS默认算法;压缩率最低,速度最快)
XPRESS8K
XPRESS16K
LZX(WIM最大压缩;压缩率最高,速度最慢)

于是这也是CompactOS比只使用LZNT压缩算法的NTFS压缩压缩率更高的奥秘所在

三:如何使用CompactOS压缩

第一种途径,你可以通过Windows10开始系统自带的compact命令行工具对文件使用CompactOS压缩

这个用法只适用于Windows 10 Build 10074或更高版本

同时按下键盘上的Win和X键,出现菜单;点击命令提示符(管理员);
接下来弹出用户账户控制对话框,点是就出现了命令提示符窗口。


若安装系统时想对系统文件使用默认CompactOS算法进行全盘压缩,可以执行这样的指令:
DISM /Apply-Image /ImageFile:install.wim /Index:1/ApplyDir:D:\ /compact (D为系统盘符)

如果你要查询你的系统有没有被CompactOS,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:query
如果你的系统被CompactOS的话,会显示以下信息:“系统处于压缩状态。它将保持此状态,除非管理员更改它。”

如果你想要进行OSCompact的话,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:always

如果你要撤销OSCompact,可以在管理员权限的命令提示符下输入以下命令并回车(在线系统适用)
compact /compactos:never

如果你想单独对一个文件进行CompactOS压缩,那怎么办呢?下面举个例子

如果我要对E:\ToolKit\procexp.exe进行lzx算法的Compact压缩,我可以输入以下命令并回车(在线和离线都可以)。
compact /c /exe:lzx E:\ToolKit\procexp.exe

既然介绍了压缩,那么介绍如何解压也是不可少的。
compact /u /exe E:\ToolKit\procexp.exe

如果你的系统不符合要求,或者不习惯命令提示符操作,推荐使用Dism++。使用方法参考Dism++的相关说明,这里不再叙述。

第二种途径,通过API调用对文件进行CompactOS压缩


你可以通过DeviceIoControl传入相应IO控制码实现对文件的CompactOS压缩

SDK要求Windows 10 Build 10240及之后版本;且使用CompactOS前要
#include <winioctl.h>

而且CompactOS压缩对传入和传出的结构有要求
WOF_EXTERNAL_INFO和FILE_PROVIDER_EXTERNAL_INFO_V1这两个结构的内容要放在一个Buffer内传输
且WOF_EXTERNAL_INFO结构的内容要放在FILE_PROVIDER_EXTERNAL_INFO_V1结构内容的前面


为了方便起见,我定义了一个结构
[mw_shl_code=cpp,true]typedef struct _WOF_FILE_EXTERNAL_BACKING_V1
{
        WOF_EXTERNAL_INFO WofInfo;
        FILE_PROVIDER_EXTERNAL_INFO_V1 FileProviderInfo;
} WOF_FILE_EXTERNAL_BACKING_V1, *PWOF_FILE_EXTERNAL_BACKING_V1;[/mw_shl_code]

FSCTL_SET_EXTERNAL_BACKING - 压缩
FSCTL_GET_EXTERNAL_BACKING - 获取压缩信息
FSCTL_DELETE_EXTERNAL_BACKING - 解压缩


PS:CompactOS压缩过的文件,如果以可写方式打开系统会自动解压缩文件(也许微软这么做是为了保证性能)

为了方便起见,我用NativeAPI对CompactOS的调用做了封装

CompactLib.h
  1. // CompactLib By Mouri_Naruto

  2. #pragma once

  3. // Wof压缩算法定义

  4. #define FILE_PROVIDER_COMPRESSION_XPRESS4K   (0x00000000)
  5. #define FILE_PROVIDER_COMPRESSION_LZX        (0x00000001)
  6. #define FILE_PROVIDER_COMPRESSION_XPRESS8K   (0x00000002)
  7. #define FILE_PROVIDER_COMPRESSION_XPRESS16K  (0x00000003)
  8. #define FILE_PROVIDER_COMPRESSION_MAXIMUM    (0x00000004)

  9. /*
  10. 对指定文件执行Wof压缩
  11. */
  12. HRESULT WINAPI WofCompactFile(
  13.         _In_ HANDLE FileHandle,
  14.         _In_ DWORD CompactAlgorithm
  15.         );

  16. /*
  17. 对指定文件执行Wof解压缩
  18. */
  19. HRESULT WINAPI WofUnCompactFile(
  20.         _In_ HANDLE FileHandle
  21.         );

  22. /*
  23. 获取指定文件的Wof压缩算法
  24. (如果文件未压缩或者执行失败返回 -1,否则为Wof压缩算法定义值)
  25. */
  26. DWORD WINAPI WofGetFileCompactAlgorithm(
  27.         _In_ HANDLE FileHandle
  28.         );

  29. /*
  30. 对指定文件执行NTFS压缩
  31. */
  32. HRESULT WINAPI NTFSCompactFile(
  33.         _In_ HANDLE FileHandle
  34.         );

  35. /*
  36. 对指定文件执行NTFS解压缩
  37. */
  38. HRESULT WINAPI NTFSUnCompactFile(
  39.         _In_ HANDLE FileHandle
  40.         );
复制代码


CompactLib.cpp

  1. // CompactLib By Mouri_Naruto

  2. #include <Windows.h>

  3. #include "CompactLib.h"

  4. #ifndef NativeAPI
  5. #define NativeAPI

  6. #pragma comment(lib,"ntdll.lib")

  7. #define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)

  8. typedef struct _IO_STATUS_BLOCK
  9. {
  10.         union
  11.         {
  12.                 NTSTATUS Status;
  13.                 PVOID Pointer;
  14.         };
  15.         ULONG_PTR Information;
  16. } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

  17. typedef VOID(NTAPI *PIO_APC_ROUTINE)(
  18.         _In_ PVOID ApcContext,
  19.         _In_ PIO_STATUS_BLOCK IoStatusBlock,
  20.         _In_ ULONG Reserved
  21.         );

  22. extern "C"
  23. {
  24.         NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(
  25.                 _In_ HANDLE FileHandle,
  26.                 _In_opt_ HANDLE Event,
  27.                 _In_opt_ PIO_APC_ROUTINE ApcRoutine,
  28.                 _In_opt_ PVOID ApcContext,
  29.                 _Out_ PIO_STATUS_BLOCK IoStatusBlock,
  30.                 _In_ ULONG FsControlCode,
  31.                 _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
  32.                 _In_ ULONG InputBufferLength,
  33.                 _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
  34.                 _In_ ULONG OutputBufferLength
  35.                 );

  36.         NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(
  37.                 _In_ NTSTATUS Status
  38.                 );
  39. }
  40. #endif

  41. #include <winioctl.h>

  42. typedef struct _WOF_FILE_EXTERNAL_BACKING_V1
  43. {
  44.         WOF_EXTERNAL_INFO WofInfo;
  45.         FILE_PROVIDER_EXTERNAL_INFO_V1 FileProviderInfo;
  46. } WOF_FILE_EXTERNAL_BACKING_V1, *PWOF_FILE_EXTERNAL_BACKING_V1;

  47. HRESULT WINAPI WofCompactFile(
  48.         _In_ HANDLE FileHandle,
  49.         _In_ DWORD CompactAlgorithm
  50.         )
  51. {
  52.         if (WofGetFileCompactAlgorithm(FileHandle) == CompactAlgorithm)
  53.                 return S_OK;
  54.         
  55.         NTSTATUS status;
  56.         IO_STATUS_BLOCK IoStatus = { 0 };
  57.         WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };

  58.         WofFileInfo.WofInfo.Version = WOF_CURRENT_VERSION;
  59.         WofFileInfo.WofInfo.Provider = WOF_PROVIDER_FILE;
  60.         WofFileInfo.FileProviderInfo.Version = FILE_PROVIDER_CURRENT_VERSION;
  61.         WofFileInfo.FileProviderInfo.Algorithm = CompactAlgorithm;
  62.         WofFileInfo.FileProviderInfo.Flags = 0;

  63.         status = NtFsControlFile(
  64.                 FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_SET_EXTERNAL_BACKING,
  65.                 &WofFileInfo, sizeof(WofFileInfo), NULL, 0);

  66.         return RtlNtStatusToDosError(status);
  67. }

  68. HRESULT WINAPI WofUnCompactFile(
  69.         _In_ HANDLE FileHandle
  70.         )
  71. {
  72.         NTSTATUS status;
  73.         IO_STATUS_BLOCK IoStatus = { 0 };

  74.         status = NtFsControlFile(
  75.                 FileHandle, NULL, NULL, NULL, &IoStatus,
  76.                 FSCTL_DELETE_EXTERNAL_BACKING, NULL, 0, NULL, 0);

  77.         return RtlNtStatusToDosError(status);
  78. }

  79. DWORD WINAPI WofGetFileCompactAlgorithm(
  80.         _In_ HANDLE FileHandle
  81.         )
  82. {
  83.         NTSTATUS status;
  84.         IO_STATUS_BLOCK IoStatus = { 0 };
  85.         WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };

  86.         status = NtFsControlFile(
  87.                 FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_GET_EXTERNAL_BACKING,
  88.                 NULL, 0, &WofFileInfo, sizeof(WofFileInfo));

  89.         return !NT_SUCCESS(status) ? -1 : WofFileInfo.FileProviderInfo.Algorithm;
  90. }

  91. HRESULT WINAPI NTFSCompactFile(
  92.         _In_ HANDLE FileHandle
  93.         )
  94. {
  95.         NTSTATUS status;
  96.         IO_STATUS_BLOCK IoStatus = { 0 };
  97.         USHORT Type = COMPRESSION_FORMAT_DEFAULT;

  98.         status = NtFsControlFile(
  99.                 FileHandle, NULL, NULL, NULL, &IoStatus,
  100.                 FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);

  101.         return RtlNtStatusToDosError(status);
  102. }

  103. HRESULT WINAPI NTFSUnCompactFile(
  104.         _In_ HANDLE FileHandle
  105.         )
  106. {
  107.         NTSTATUS status;
  108.         IO_STATUS_BLOCK IoStatus = { 0 };
  109.         USHORT Type = COMPRESSION_FORMAT_NONE;

  110.         status = NtFsControlFile(
  111.                 FileHandle, NULL, NULL, NULL, &IoStatus,
  112.                 FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);

  113.         return RtlNtStatusToDosError(status);
  114. }
复制代码


四:性能影响和效果

度娘看了看,几乎都表示CompactOS基本上不会影响性能。但CompactOS易产生难整理型文件碎片,在机械硬盘上应注意。

下面附带下个人的体验
由于我使用了LZX算法,于是系统盘比以前腾出了将近一半的空间(原本占用50GB,现在25GB左右)
而且感受不到性能的损失,也许是我的CPU是E3 1230 V2,硬盘是256GB SSD的缘故吧

五:移植CompactOS特性到其他系统

前提条件系统是Windows 7/8/8.1及对应的服务器版本;而且你要使用Windows ADK 10的wofadk.sys

曾经和Dism++作者解决Dism++在Windows Vista下的兼容性问题时
发现Vista下一旦安装了wofadk驱动,bootmgr阶段会报错“启动文件证书无效”

而且你要排除Windows加载wofadk驱动前Windows需要用到的文件

详情可以参考无忧;或者你也可以使用Dism++

附:Windows10 CompactOS排除列表

(IDA打开Windows10的compact.exe命令行工具就可以找到了)
  1. // 文件排除列表
  2. wchar_t *FileExclusionList[] =
  3. {
  4.         L"\\aow.wim",
  5.         L"\\boot\\bcd",
  6.         L"\\boot\\bcd.log",
  7.         L"\\boot\\bootstat.dat",
  8.         L"\\config\\drivers",
  9.         L"\\config\\drivers.log",
  10.         L"\\config\\system",
  11.         L"\\config\\system.log",
  12.         L"\\windows\\bootstat.dat",
  13.         L"\\winload.efi",
  14.         L"\\winload.efi.mui",
  15.         L"\\winload.exe",
  16.         L"\\winload.exe.mui",
  17.         L"\\winresume.efi",
  18.         L"\\winresume.efi.mui",
  19.         L"\\winresume.exe",
  20.         L"\\winresume.exe.mui"
  21. };

  22. // 目录排除列表
  23. wchar_t *DirectoryExclusionList[] =
  24. {
  25.         L"\\Backup\",
  26.         L"\\ManifestCache\",
  27.         L"\\Manifests\"
  28. };
复制代码


感谢阅读,毛利于2016/8/16



评分

参与人数 2无忧币 +2 收起 理由
vrboxing + 1 赞一个!
itoken + 1 很给力!

查看全部评分

2#
发表于 2016-8-17 22:25:13 | 只看该作者
顶顶!d=====( ̄▽ ̄*)b
回复

使用道具 举报

3#
发表于 2016-8-18 01:12:39 来自手机 | 只看该作者
毛利……小五郎………
回复

使用道具 举报

4#
发表于 2016-8-18 01:21:46 来自手机 | 只看该作者
前几天ltsb发布后第一时间在固态硬盘上最大压缩,开启写过滤试了试,有卡顿现象(i5-3317),远没有低端3.0U盘上的嵌入版8.1wimboot流畅(U盘最快写23M),写过滤同样开启,流畅度都可以比肩固态了……

点评

我在U盘上wtg非写过滤也很流畅  详情 回复 发表于 2016-8-18 08:47
回复

使用道具 举报

5#
发表于 2016-8-18 08:47:58 | 只看该作者
nttwqz 发表于 2016-8-18 01:21
前几天ltsb发布后第一时间在固态硬盘上最大压缩,开启写过滤试了试,有卡顿现象(i5-3317),远没有低端3.0 ...

我在U盘上wtg非写过滤也很流畅
回复

使用道具 举报

6#
发表于 2016-8-18 13:49:43 | 只看该作者
学习了,compact很好用,压缩率很高,装完软件,compact一下,感觉很清爽。不过不知道怎么移植到win7系统,让win7也能一个右键菜单就完成compact操作,那样win7+compact可以体积很小很小。
回复

使用道具 举报

7#
发表于 2016-8-18 14:42:51 | 只看该作者
感谢楼主分享!
回复

使用道具 举报

8#
发表于 2016-8-18 15:21:48 | 只看该作者
顶顶毛利的帖子
回复

使用道具 举报

9#
发表于 2016-8-19 08:59:16 | 只看该作者
回来深造了,学习中
回复

使用道具 举报

10#
发表于 2016-8-19 16:34:46 来自手机 | 只看该作者
WIN7-WIMBOOT一直在用
回复

使用道具 举报

11#
发表于 2016-8-19 17:12:09 来自手机 | 只看该作者
虽然看不懂命令行,但支持楼主!我安装系统一般是用工具以compact压缩方式释放映像到硬盘,然后修复引导。这样用compact压缩也安装过win8.1。
回复

使用道具 举报

12#
发表于 2018-2-5 16:36:53 | 只看该作者
谢谢楼主分享!
回复

使用道具 举报

13#
发表于 2018-2-25 00:40:14 | 只看该作者
楼主好厉害!有没有直接排除了系统必须文件后压缩的批处理呢
回复

使用道具 举报

14#
发表于 2018-7-9 10:41:41 | 只看该作者
辛苦普及 学习 不过有压缩就会有系统性能损失  那点损失对于绝大多数人日常使用无感而已  不缺系统分区空间情况下 建议不压缩 否则可以默认4k压缩即可
回复

使用道具 举报

15#
发表于 2018-8-8 07:20:14 | 只看该作者
谢谢分享
回复

使用道具 举报

16#
发表于 2022-3-31 16:05:18 | 只看该作者
d系统的dism能否指定lzx压缩参数呢
回复

使用道具 举报

17#
发表于 2022-6-7 17:32:52 | 只看该作者
要慢慢消化
回复

使用道具 举报

18#
发表于 2025-1-19 23:47:13 | 只看该作者
感谢楼主无私分享
回复

使用道具 举报

19#
发表于 2025-1-27 23:25:46 | 只看该作者
看着不错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-2-20 21:34

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表