.NET导出Excel的四种方法及评测

news/2023/12/1 10:26:28

前言

导出Excel是.NET的常见需求,开源社区、市场上,都提供了不少各式各样的Excel操作相关包。本文,我将使用NPOI、EPPlus、OpenXML、Aspose.Cells四个市面上常见的库,各完成一个导出Excel示例。然后对其代码风格和性能做一个横向比较。最后我将说出我自己的感想。

文中所有的示例代码可以在这里下载:https://github.com/sdcb/blog-data/tree/master/2019/20190824-dotnet-excel-compare

NPOI

NPOI源自于Java的Apache POI(https://poi.apache.org/),目前最新版本是2.4.1。NPOI是开源项目,作者是华人(https://github.com/tonyqus/),项目地址是:https://github.com/tonyqus/npoi。

几年前大家导出Excel都使用COM,但COM不方便,这个组件的推出无疑弥补了.NET在Excel方面组件的空白,大家都说比COM好用。

NPOI还加入了.NET Core Community组织,项目地址是:https://github.com/dotnetcore/NPOI。

EPPlus

EPPlus是另一个开源的Excel操作库,目前最新版本是4.5.3.2。Github地址是:https://github.com/JanKallman/EPPlus。

EPPlus仅依赖基础类库BCL,完全没有第三方包依赖,也是.NET原生库。

EPPlus只支持导出Office 2007之后的格式,也就是xlsx。这已经是存在12年的格式了,但如果有客户想要导出xls,EPPlus将不支持。

OpenXML

OpenXML的NuGet包全称是DocumentFormat.OpenXml:是微软推出的较为低层的Excel操作库,最新稳定版本是2.9.1。OpenXML也是开源项目,地址是:https://github.com/OfficeDev/Open-XML-SDK。

从该项目的名字可以看出,OpenXML比较涉及底层,因此很容易令人浮想联翩,感觉它的性能、速度很可能是最快的,但真的如此吗?

Aspose.Cells

这是Aspose Pty Ltd公司推出的Excel操作库。它是众多Aspose File Format API产品其中之一。目前最新版本是19.8.0(基于年/月)。Aspose提供了应有尽有的文件格式支持,除了.NET外,Aspose还提供了C++和Java的包。

据我所知Aspose的客户支持服务也不错,客户提出的问题经常可以在下一次发布时解决。

Aspose.Cells是不开源,付费的库,但提供无限期的试用,据[官方网站](https://docs.aspose.com/display/cellsnet/Licensing#Licensing-EvaluationVersionLimitations)显示,试用版将

  • 限制打开文件数量100个

  • 限制使用Aspose.Cells.GridWeb功能

  • 生成的Excel将添加如下水印:640?wx_fmt=png

但经过我的试用,无论是并行还是串行,都没找到限制打开文件数量100个的限制。因此,“试用版”对我们的物理限制,就只有这个水印了(当然加了这个水印,客户肯定也不会有好表情?)。

Excel-COM

COM是随着Excel安装而自带的库,Excel的包名叫Microsoft.Office.Interop.Excel。本文不会深入解析,具体可以看[这篇文档](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interop/how-to-access-office-onterop-objects)。

我想要多说两句的是,COM的old-fashion(过时)不是没有原因的,据我所知COM有以下缺点:

  • 调用时会启动一个进程外的excel.exe,可能因为它为是专门为Office设计的(不是为.NET集成设计的)

  • 要求目标环境安装相关软件,没安装将无法运行

  • 显然也没办法跨平台

  • 使用了大量动态/多参数接口,对开发不是很友好

  • 不像托管内存,COM对资源释放也有要求,具体参见[这篇文章](https://www.breezetree.com/blog/common-mistakes-programming-excel-with-c-sharp)

横向比较


NPOI
EPPlus
OpenXML
Aspose
包依赖
有1个

封装程度正常
正常
低层
正常
支持格式
完善
仅xlsx
仅xlsx
完善
开源协议
Apache-2.0
LGPLMIT
不开源‍
收费类型
免费
免费
免费
收费

评测说明

版本与数据

所有代码的版本号基于上文中提到的最新稳定版本:


最新稳定版本号
NPOI
2.4.1
EPPlus
4.5.3.2
OpenXML2.9.1
Aspose.Cells
19.8.0

数据全部基于我上篇文章使用的6万条/10列的数据,总共数据量19,166 KB。所有数据可以从这里下载:https://github.com/sdcb/blog-data/tree/master/2019/20190821-generate-lorem-data

环境

项目
CPUE3-1230 v3 @ 3.30GHz
内存
24GB DDR3-1600 MHz (8GBx3) 
 操作系统Windows 10 1903 64位
电源选项已设置为“高性能”‍
软件
LINQPad 6.0.18
运行时环境
.NET Core 3.0-preview8-28405-07

注意,LINQPad设置了optimize+,代码都是优化后执行的;代码都指定了Util.NewProcess = true;,确保每次运行都会在新进程中运行,不会互相影响。

我的性能测试函数介绍

IEnumerable<object> Measure(Action action, int times = 5)	
{	return Enumerable.Range(1, times).Select(i =>	{	var sw = Stopwatch.StartNew();	long memory1 = GC.GetTotalMemory(true);	long allocate1 = GC.GetTotalAllocatedBytes(true);	{	action();	}	long allocate2 = GC.GetTotalAllocatedBytes(true);	long memory2 = GC.GetTotalMemory(true);	sw.Stop();	return new	{	次数 = i, 	分配内存 = (allocate2 - allocate1).ToString("N0"),	内存提高 = (memory2 - memory1).ToString("N0"), 	耗时 = sw.ElapsedMilliseconds,	};	});	
}

除了时间,内存占用实际也是非常非常重要、但容易被人忽略的性能指标。大家都以为“内存不值钱”,但——

  • 一旦访问量大,内存就会瞬间上涨,导致频繁GC,导致性能下降;

  • 内存高也会导致服务器分页,这时性能就会急剧下降;

  • 吞吐量下降会导致队列排满,此时服务器就会报503等错误,客户就发现服务器“宕机了”。

(提示:除非你的客户真的愿意多花钱再升级一下服务器,否则不要提“内存不值钱”。)

在我的性能测试函数中,使用了如下两个函数来测试内存占用:

  • GC.GetTotalAllocatedBytes(true) 获取分配内存大小

  • GC.GetTotalMemory(true) 获取占用内存大小

占用内存可能会比分配内存小,因为存在垃圾回收(GC),但GC会影响性能。

通过调用Measure函数,可以测得传入的action的耗时和内存占用。默认会调用5次,可以从5次测试结果中取出能反映性能的值。

测试基准

string Export<T>(List<T> data, string path)	
{	PropertyInfo[] props = typeof(User).GetProperties();	string noCache = null;	for (var i = 0; i < props.Length; ++i)	{	noCache = props[i].Name;	}	for (var i = 0; i < data.Count; ++i)	{	for (var j = 0; j < props.Length; ++j)	{	noCache = props[j].GetValue(data[i]).ToString();	}	}	return noCache;	
}

注意:

  • 我有意使用了反射,这符合我们导出Excel代码简单、易学、好用、好扩展的愿意;

  • 我有意使用了泛型T,而不是实际类型,这也让这些代码容易扩展;

  • 里面的noCache用来规避编译器优化删除代码的行为

测试结果:

次数
分配内存
内存提高
耗时
1
9,863,5208,712
156
29,852,5920
138
39,852,5920147
4
9,873,0969,240
136
59,853,936776
133

可见,基于反射操作6万/10列数据,每次需要分配约9MB内存,但这些内存都会被快速GC,最终内存提高较少。这些使用反射的代码运行耗时在130ms-150ms左右。

各个库的使用和性能表现

NPOI

void Export<T>(List<T> data, string path)	
{	IWorkbook workbook = new XSSFWorkbook();	ISheet sheet = workbook.CreateSheet("Sheet1");	var headRow = sheet.CreateRow(0);	PropertyInfo[] props = typeof(User).GetProperties();	for (var i = 0; i < props.Length; ++i)	{	headRow.CreateCell(i).SetCellValue(props[i].Name);	}	for (var i = 0; i < data.Count; ++i)	{	var row = sheet.CreateRow(i + 1);	for (var j = 0; j < props.Length; ++j)	{	row.CreateCell(j).SetCellValue(props[j].GetValue(data[i]).ToString());	}	}	using var file = File.Create(path);	workbook.Write(file);	
}

注意:

  • 里面用到了XSSFWorkBook,其中XSSF这个前缀是从Java的POI库传过来的,全称是XML SpreadSheet Format。

    这种前缀在NPOI包中很常见。

  • XSSFWorkbook提供了bool Dispose()方法,但它未实现(因此千万别调用它):

    640?wx_fmt=png

性能测试结果:

次数
分配内存
内存提高
耗时
1
1,598,586,416537,0486590
21,589,239,7287,712
10155
31,589,232,056-5,36810309
4
1,589,237,0647,144
10355
51,589,245,0009,56010594

分配内存稳定在1.48GB的样子,首次内存会提高524KB左右,后面趋于稳定。首次耗时6秒多,后面稳定在10秒多。

EPPlus

void Export<T>(List<T> data, string path)	
{	using var stream = File.Create(path);	using var excel = new ExcelPackage(stream);	ExcelWorksheet sheet = excel.Workbook.Worksheets.Add("Sheet1");	PropertyInfo[] props = typeof(User).GetProperties();	for (var i = 0; i < props.Length; ++i)	{	sheet.Cells[1, i + 1].Value = props[i].Name;	}	for (var i = 0; i < data.Count; ++i)	{	for (var j = 0; j < props.Length; ++j)	{	sheet.Cells[i + 2, j + 1].Value = props[j].GetValue(data[i]);	}	}	excel.Save();	
}

注意,不同于NPOI/Aspose.Cells,EPPlus的下标是基于1的(而不是0)。

次数
分配内存
内存提高
耗时
1
534,970,328156,0483248
2533,610,23214,8962807
3533,595,9367,6482853
4
533,590,7764,408
2742
5533,598,44011,2802759

分配内存约508MB,耗时首次稍长,约3.2秒,后面稳定在2.7-2.8秒。

OpenXML

void Export<T>(List<T> data, string path)	
{	using SpreadsheetDocument excel = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook);	WorkbookPart workbookPart = excel.AddWorkbookPart();	workbookPart.Workbook = new Workbook();	WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();	worksheetPart.Worksheet = new Worksheet(new SheetData());	Sheets sheets = excel.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());	Sheet sheet = new Sheet	{	Id = excel.WorkbookPart.GetIdOfPart(worksheetPart),	SheetId = 1,	Name = "Sheet1"	};	sheets.Append(sheet);	SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();	PropertyInfo[] props = typeof(User).GetProperties();	{    // header	var row = new Row() { RowIndex = 1 };	sheetData.Append(row);	row.Append(props.Select((prop, i) => new Cell	{	CellReference = ('A' + i - 1) + row.RowIndex.Value.ToString(),	CellValue = new CellValue(props[i].Name),	DataType = new EnumValue<CellValues>(CellValues.String),	}));	}	sheetData.Append(data.Select((item, i) => 	{	var row = new Row { RowIndex = (uint)(i + 2) };	row.Append(props.Select((prop, j) => new Cell	{	CellReference = ('A' + j - 1) + row.RowIndex.Value.ToString(),	CellValue = new CellValue(props[j].GetValue(data[i]).ToString()),	DataType = new EnumValue<CellValues>(CellValues.String),	}));	return row;	}));	excel.Save();	
}

注意,因为`OpenXML`比较偏低层,东西比较复杂,所以我们慢慢说:

  • 对于一些对象,它需要创建相应的Part,如WorksheetPart;

  • Excel可以使用SharedStringTable来共享变量值,适合相同字符串非常多的场景。

    但此示例共享变量值收益很低,但会极大地增加代码复杂性(普通用户可能很难写出),因此本示例未使用SharedStringTable;

  • 它基于单元格位置标识,如B3(第三行第二列),因此索引方式比EPPlus/NPOI都要复杂;

  • 代码示例中使用'A' + i - 1来计算位置标识,因此这个示例不能用于超过26列(字母数)的数据;

  • 代码使用LINQ(而不是循环)来枚举所有行/列,可以让代码在已经非常复杂的情况下,更简洁一点;

    经测试,将LINQ改成for循环对性能结果变化影响极其微小。

测试结果如下:

次数
分配内存
内存提高
耗时
1
556,937,896145,8324009
2555,981,2163123783
3555,985,9362,7603884
4
555,984,3841,8723869
5555,989,1203,8803704

内存占用约530MB左右,第一次比后面多1MB的样子,耗时3.7-4.0秒之间。

Aspose.Cells

void Export<T>(List<T> data, string path)	
{	using var excel = new Workbook();	Worksheet sheet = excel.Worksheets["Sheet1"];	PropertyInfo[] props = typeof(User).GetProperties();	for (var i = 0; i < props.Length; ++i)	{	sheet.Cells[0, i].Value = props[i].Name;	}	for (var i = 0; i < data.Count; ++i)	{	for (var j = 0; j < props.Length; ++j)	{	sheet.Cells[i + 1, j].Value = props[j].GetValue(data[i]);	}	}	excel.Save(path);	
}

注意,Aspose.Cells像Excel软件一样,提供了Sheet1/Sheet2/Sheet3三个默认的工作表,因此取这三个工作表时,不要创建,而是取出来。

性能测试结果如下:

次数
分配内存
内存提高
耗时
1
404,004,9443,619,5203316
2357,931,6486,0482078
3357,934,7447,2162007
4
357,933,3766,2802017
5357,933,3606,4242007

Aspose.Cells首次占用内存385MB,用于3.3秒,后面每次降低为内存341MB,用时2.0秒。

总结

四种导出Excel库的横向评测数据如下,数据取5次数值的内存消耗中位数

,百分比以EPPlus的测试数据为100%基准:

次数
分配内存
内存占比
耗时‍
耗时占比
基准(仅反射)
9,853,9361.85%1334.82%
NPOI1,589,237,064297.83%10355375.32%
EPPlus533,598,440100%2759100%
OpenXML
555,985,936104.19%3884140.78%
Aspose357,933,36067%200772.74%

可以得出以下结论:

  1. Demo基于反射,但反射总损耗的性能不高,内存、耗时均不超过5%;

  2. NPOI的性能表现是所有项目中最差的,每次需要分配1.5GB的内存和超过10秒的耗时;

  3. EPPlus表现不错,内存和耗时在开源组中表现最佳;

  4. 收费的Aspose.Cells表现最佳,内存占用最低,用时也最短;

  5. 较为底层的OpenXML表现非常一般,比EPPlus要差,更不能与收费的Aspose相提并论;

我的感想

在真的愿意尝试一下之前,人们很容易相信自己的直觉。底层库,通常能带来更大的可扩展性,能做出上层库很难做的事来。底层库有时性能会更快,就像更底层的C/C++比上层的JavaScript更快一样。但事情也不都如此,如

  • 更高层的React.js能在性能上将较底层的DOM操作比下去

  • 数据库基于集合的操作也比基于游标的操作要快得多

在导出Excel这个例子中,我了解到Excel的xlsx格式是非常复杂的、多个xml的集合。如果基于xml做抽象——也是很正常的做法,拼出6万/10列的数据,需要至少60万个xml标签做拼接,很显然这需要分配/浪费大量内存,因此性能上不来。

我基于以下几点无责任猜测:Aspose内部可能没xml做抽象,而是纯数据做抽象(就像React.js那样),然后再统一写入到Excel文件。因此性能可以达到其它库达不到的目标:

  1. Aspose.Cells对xml等实现相关技术只字未提(可能因为要支持多种文件格式);

  2. Aspose.Cells是先在内存中创建,再写入文件/流(NPOI也是);

  3. Aspose.Cells创建Excel时要求客户直接使用Workbook类(NPOI也是);

  4. Aspose.Cells完全隐藏了Excel的位置(如B3)信息,下标从0开始(NPOI也是)

比较这几点,NPOI也与Aspose.Cells有几分相似,但导出不到6MB的`Excel`它内存分配居然高达1.5GB,是后者的444%!毕竟迭代更新了这么多年了,代码质量我相信应该没问题。因此我再次无责任推测:这可能因为它是从Java那边移植过来的。

我的选择/推荐

在我做这个性能评测前,我一直使用的是EPPlus,因为我不喜欢NPOI有第三方依赖,也不喜欢NPOI那些“XSSF”之类的前缀命名,也显然不会去费心思写那么多费力不讨好的OpenXML代码。

更别提这次评测发现EPPlus的性能确实不错,唯一的缺点就是它单元格下标从1开始的设计。即便如此,我还是首选推荐EPPlus。

近期也经常使用Aspose.Cells这种商业库,它的功能强大,API清晰好用,这个评测也证明它的性能卓越。除了高昂(https://purchase.aspose.com/pricing/cells/net)的价格,没别的缺点了。乃有钱客户/老板的不二之选!

出处:微信公众号【DotNet骚操作】原文链接:https://www.cnblogs.com/sdflysha/p/20190824-dotnet-excel-compare.html

觉得好看,请点这里↓↓↓


http://www.ppmy.cn/news/338189.html

相关文章

【java爬虫】jsoup爬取网页数据-搜索算法评测/竞品评测

百度抽奖概率改4个小时频繁黑屏频繁弹出源码的前端FE T8李森:请云端高level的同学参加会议。。。对,我级别到了。。。 666666 业务背景:如何保证搜索算法的好坏?所以有了竞品评测,自己的APP采用接口的方式抓取前6个卡…

字符串分割表值函数评测

/* Microsoft SQL Server 2017 (RTM-CU5) (KB4092643) - 14.0.3023.8 (X64) Mar 2 2018 18:24:44 Copyright (C) 2017 Microsoft Corporation Enterprise Edition: Core-based Licensing (64-bit) on Windows 10 Pro 10.0 <X64> (Build 15063: ) */ --备用函数 …

Memcached客户端性能评测报告

转载&#xff1a;http://wenku.baidu.com/view/944935a15901020206409c08 Memcached客户端性能评测报告 1. Memcached客户端简介 本次memcached客户端评测以JAVA开源客户项目为评测对象&#xff0c;分别选择Memcached-Java-Client、spymemcached、xmemcached、alisoftxpl…

海尔简爱s11 Linux,360度影音神器 海尔简爱S11笔记本评测

360度影音神器 海尔简爱S11笔记本评测 2017年02月23日 00:31作者:孙端编辑:孙端文章出处:泡泡网原创 分享 在触控操作极大普及的今天,笔记本电脑产品得益于半导体制作工艺的精进,获得了前所未有的便携体积和操作方式。笔记本平板二合一的产品汲取了笔记本的丰富可操作性以…

LeetCode笔记:Weekly Contest 280

LeetCode笔记&#xff1a;Weekly Contest 280 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 题目一 给出题目一的试题链接如下&#xff1a; 2169. Count Operations to Obtain Zero 1. 解题思路 这…

入手评测 华为2021款MatePad Pro 10.8和12.6的区别

MatePad Pro 10.8英寸&#xff1a;机身尺寸为246x159x7.2mm&#xff0c;机身重量约为460克。 MatePad Pro 12.6英寸&#xff1a;机身尺寸为286.5x184.7x6.7mm&#xff0c;机身重量约为609克。 平板电脑选华为2021款MatePad Pro 10.8还是12.6这些点很重要看过你就懂了http://hua…

移动端芯片性能评测论文出炉

苏黎世联邦理工学院曾经开发了一款 AI Benchmark 应用&#xff0c;用于测试不同安卓设备和芯片的深度学习性能。近期&#xff0c;他们联合谷歌、高通、华为、联发科以及 Arm 发布了一篇 AI Benchmark 综合测试结果的论文&#xff0c;对超过 10000 部移动设备进行了定量 Benchma…

linux netgear usb,家用四槽位 NETGEAR ReadyNAS NV+评测

【IT168评测中心】NETGEAR网件在推出了面向企业级用户的四槽位ReadyNAS NVX之后,很快推出了其兄弟产品:面向家庭/普通用户的ReadyNAS NV+,从型号上看,它们很相近,实际上,ReadyNAS NV+除了可以用于家庭应用之外,也可以用于小型工作组或者部门: ReadyNAS NV+的外观就和Re…

车路协同自动驾驶数据集DAIR-V2X

一、DAIR-V2X数据集简介 自动驾驶安全面临巨大挑战&#xff0c;单车智能存在驾驶盲区、中远距离感知不稳定等问题&#xff0c;导致自动驾驶车辆可运行设计域&#xff08;ODD&#xff09;受限&#xff0c;单车智能自动驾驶落地受阻。车路协同将助力保障自动驾驶安全运行。而数据…

SNPE分析与评测 (2)

一、AIP Runtime AIP (AI Processor) Runtime是Q6、HVX和HTA三者在执行模型时候的一层软件抽象。 1、部署前提条件&#xff0c;让模型在AIP上执行的前提条件&#xff1a; 1&#xff09;看硬件设备是否支持&#xff08;查看前文中支持SNPE处理器的硬件列表&#xff09;&#xf…

x390开机键_【ThinkPadX390评测】ThinkPad X390 4G版全球首测:全时在线超长续航的便携商务利器(全文)_ThinkPad X390_笔记本评测-中关村在线...

X240之后&#xff0c;我已经很多年不再关注ThinkPad X系列了。现如今把我又拉回来的&#xff0c;是这台ThinkPad X390 4G版。由于中间的断层&#xff0c;我并不知道X200系列已经没有了&#xff0c;一搜之下才发现&#xff0c;原来X280是最后一代X200系列。自那之后&#xff0c;…

初探BERTPre-trainSelf-supervise

初探Bert 因为一次偶然的原因&#xff0c;自己有再次对Bert有了一个更深层地了解&#xff0c;特别是对预训练这个概念&#xff0c;首先说明&#xff0c;自己是看了李宏毅老师的讲解&#xff0c;这里只是尝试进行简单的总结复述并加一些自己的看法。 说Bert之前不得不说现在的…

联想ThinkPad升级BIOS和EC新手教程

2020年3月&#xff0c;我有机会到联想总部北京W1的Thimkpad测试实验室工作&#xff0c;所以对Thinkpad笔记本电脑开发过程的升级BIOS、EC、ME有所了解。 进入BIOS界面的方式各不相同&#xff0c;针对不同厂家的机器有不同的进入方式&#xff0c;通常进入方式会在开机画面有所提…

HW-HJ74参数解析

题目描述 在命令行输入如下命令&#xff1a; xcopy /s c:\ d:\&#xff0c; 各个参数如下&#xff1a; 参数1&#xff1a;命令字xcopy 参数2&#xff1a;字符串/s 参数3&#xff1a;字符串c:\ 参数4: 字符串d:\ 请编写一个参数解析程序&#xff0c;实现将命令行各个参数…

mingw-w64 全网最全

离线安装 下载 win32-seh版 官网&#xff1a;MinGW-w64 进入官网 --> 菜单栏 --> download --> ctrlf 搜SourceForge --> 下载页如下图 页面需要拉到最底下 MinGW-w64 离线包安装方法 win32版使用windows的线程库&#xff0c;性能更好。posix版使用pthread线程…

深入了解WM_SIZE

在窗口大小发生改变时&#xff0c;系统往窗口发送WM_SIZE消息&#xff0c;WPARAM指出窗口新的状态&#xff0c;LPARAM给出窗口新的大小。窗口的状态有三种&#xff1a;SIZE_MINIMIZE&#xff0c;SIZE_MAXIMIZE&#xff0c;SIZE_RESTORED。系统根据当前窗口的状态&#xff0c;在…

MSYS2工具链方便快捷的安装方法

文章目录 背景快捷方法 背景 曾经安装mingw编译器的时候习惯输入的命令是&#xff1a; pacman -Syu gcc然后一个一个的安装编译器需要的东西。 快捷方法 今天意外发现有一个一次全部安装的方法&#xff1a; pacman -Syu mingw-w64-i686-toolchain真是省掉不少时间&#xf…

关于M93C56-WMN6TP

M93C56-WMN6TP 可工作在 - 40 C to 85 C环境温度下&#xff0c;采用 SO-8封装方式。 制造商: STMicroelectronics 产品种类: EEPROM 存储容量: 2 Kbit 组织: 256 x 8 封装 / 箱体: SO-8 接口类型: Microwire 最大时钟频率: 2 MHz 电源电压&#xff08;最大值&#xff09;: 5.5…

浅谈DWM【1】

现在&#xff0c;越来越多的软件提供了透明磨砂玻璃效果。典型的例子是软媒的魔方和软媒的闪游&#xff1a; 笔者这系统可算是后现代主意义——Vista桌面壁纸中的Windows 7~~ 步入正题。 给大家晾一下dwmapi.h的内容 dwmapi.h /* *\ Copyright (c) Microsoft Corporation. All …

WMI_02_常用WMI查询列表

WMI_02_常用WMI查询列表 1.硬件相关2.操作系统相关 1.硬件相关 Win32_Processor, // CPU 处理器 Win32_PhysicalMemory, // 物理内存条 Win32_Keyboard, // 键盘 Win32_PointingDevice, // 点输入设备&#xff0c;包括鼠标。 Win32_FloppyDrive, // 软盘驱动器 Win32_DiskDriv…
最新文章