|
================================注释开始================================
先开始发到吾爱,没达到预期效果;于是发到我认为最适合发布的地方(无忧)
本贴可以任意转载引用;如果能告知楼主一声最好
感谢不离不弃的包子,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
- // CompactLib By Mouri_Naruto
- #pragma once
- // Wof压缩算法定义
- #define FILE_PROVIDER_COMPRESSION_XPRESS4K (0x00000000)
- #define FILE_PROVIDER_COMPRESSION_LZX (0x00000001)
- #define FILE_PROVIDER_COMPRESSION_XPRESS8K (0x00000002)
- #define FILE_PROVIDER_COMPRESSION_XPRESS16K (0x00000003)
- #define FILE_PROVIDER_COMPRESSION_MAXIMUM (0x00000004)
- /*
- 对指定文件执行Wof压缩
- */
- HRESULT WINAPI WofCompactFile(
- _In_ HANDLE FileHandle,
- _In_ DWORD CompactAlgorithm
- );
- /*
- 对指定文件执行Wof解压缩
- */
- HRESULT WINAPI WofUnCompactFile(
- _In_ HANDLE FileHandle
- );
- /*
- 获取指定文件的Wof压缩算法
- (如果文件未压缩或者执行失败返回 -1,否则为Wof压缩算法定义值)
- */
- DWORD WINAPI WofGetFileCompactAlgorithm(
- _In_ HANDLE FileHandle
- );
- /*
- 对指定文件执行NTFS压缩
- */
- HRESULT WINAPI NTFSCompactFile(
- _In_ HANDLE FileHandle
- );
- /*
- 对指定文件执行NTFS解压缩
- */
- HRESULT WINAPI NTFSUnCompactFile(
- _In_ HANDLE FileHandle
- );
复制代码
CompactLib.cpp
- // CompactLib By Mouri_Naruto
- #include <Windows.h>
- #include "CompactLib.h"
- #ifndef NativeAPI
- #define NativeAPI
- #pragma comment(lib,"ntdll.lib")
- #define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)
- typedef struct _IO_STATUS_BLOCK
- {
- union
- {
- NTSTATUS Status;
- PVOID Pointer;
- };
- ULONG_PTR Information;
- } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
- typedef VOID(NTAPI *PIO_APC_ROUTINE)(
- _In_ PVOID ApcContext,
- _In_ PIO_STATUS_BLOCK IoStatusBlock,
- _In_ ULONG Reserved
- );
- extern "C"
- {
- NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(
- _In_ HANDLE FileHandle,
- _In_opt_ HANDLE Event,
- _In_opt_ PIO_APC_ROUTINE ApcRoutine,
- _In_opt_ PVOID ApcContext,
- _Out_ PIO_STATUS_BLOCK IoStatusBlock,
- _In_ ULONG FsControlCode,
- _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
- _In_ ULONG InputBufferLength,
- _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
- _In_ ULONG OutputBufferLength
- );
- NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(
- _In_ NTSTATUS Status
- );
- }
- #endif
- #include <winioctl.h>
- 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;
- HRESULT WINAPI WofCompactFile(
- _In_ HANDLE FileHandle,
- _In_ DWORD CompactAlgorithm
- )
- {
- if (WofGetFileCompactAlgorithm(FileHandle) == CompactAlgorithm)
- return S_OK;
-
- NTSTATUS status;
- IO_STATUS_BLOCK IoStatus = { 0 };
- WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };
- WofFileInfo.WofInfo.Version = WOF_CURRENT_VERSION;
- WofFileInfo.WofInfo.Provider = WOF_PROVIDER_FILE;
- WofFileInfo.FileProviderInfo.Version = FILE_PROVIDER_CURRENT_VERSION;
- WofFileInfo.FileProviderInfo.Algorithm = CompactAlgorithm;
- WofFileInfo.FileProviderInfo.Flags = 0;
- status = NtFsControlFile(
- FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_SET_EXTERNAL_BACKING,
- &WofFileInfo, sizeof(WofFileInfo), NULL, 0);
- return RtlNtStatusToDosError(status);
- }
- HRESULT WINAPI WofUnCompactFile(
- _In_ HANDLE FileHandle
- )
- {
- NTSTATUS status;
- IO_STATUS_BLOCK IoStatus = { 0 };
- status = NtFsControlFile(
- FileHandle, NULL, NULL, NULL, &IoStatus,
- FSCTL_DELETE_EXTERNAL_BACKING, NULL, 0, NULL, 0);
- return RtlNtStatusToDosError(status);
- }
- DWORD WINAPI WofGetFileCompactAlgorithm(
- _In_ HANDLE FileHandle
- )
- {
- NTSTATUS status;
- IO_STATUS_BLOCK IoStatus = { 0 };
- WOF_FILE_EXTERNAL_BACKING_V1 WofFileInfo = { 0 };
- status = NtFsControlFile(
- FileHandle, NULL, NULL, NULL, &IoStatus, FSCTL_GET_EXTERNAL_BACKING,
- NULL, 0, &WofFileInfo, sizeof(WofFileInfo));
- return !NT_SUCCESS(status) ? -1 : WofFileInfo.FileProviderInfo.Algorithm;
- }
- HRESULT WINAPI NTFSCompactFile(
- _In_ HANDLE FileHandle
- )
- {
- NTSTATUS status;
- IO_STATUS_BLOCK IoStatus = { 0 };
- USHORT Type = COMPRESSION_FORMAT_DEFAULT;
- status = NtFsControlFile(
- FileHandle, NULL, NULL, NULL, &IoStatus,
- FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);
- return RtlNtStatusToDosError(status);
- }
- HRESULT WINAPI NTFSUnCompactFile(
- _In_ HANDLE FileHandle
- )
- {
- NTSTATUS status;
- IO_STATUS_BLOCK IoStatus = { 0 };
- USHORT Type = COMPRESSION_FORMAT_NONE;
- status = NtFsControlFile(
- FileHandle, NULL, NULL, NULL, &IoStatus,
- FSCTL_SET_COMPRESSION, &Type, sizeof(Type), NULL, 0);
- return RtlNtStatusToDosError(status);
- }
复制代码
四:性能影响和效果
度娘看了看,几乎都表示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命令行工具就可以找到了)
- // 文件排除列表
- wchar_t *FileExclusionList[] =
- {
- L"\\aow.wim",
- L"\\boot\\bcd",
- L"\\boot\\bcd.log",
- L"\\boot\\bootstat.dat",
- L"\\config\\drivers",
- L"\\config\\drivers.log",
- L"\\config\\system",
- L"\\config\\system.log",
- L"\\windows\\bootstat.dat",
- L"\\winload.efi",
- L"\\winload.efi.mui",
- L"\\winload.exe",
- L"\\winload.exe.mui",
- L"\\winresume.efi",
- L"\\winresume.efi.mui",
- L"\\winresume.exe",
- L"\\winresume.exe.mui"
- };
- // 目录排除列表
- wchar_t *DirectoryExclusionList[] =
- {
- L"\\Backup\",
- L"\\ManifestCache\",
- L"\\Manifests\"
- };
复制代码
感谢阅读,毛利于2016/8/16
|
评分
-
查看全部评分
|