如何在 .NET 中利用 Shell32 库作为 COM 导入 – 一个巧妙的小技巧






4.57/5 (6投票s)
使用 Shell32 库将文件或文件夹写入 Zip 文件。
引言
您是否曾想知道如何在不使用第三方库的情况下压缩文件?虽然这可能看似毫无意义,但我将解释如何做到。
背景
我之所以努力实现这一点,是为了能够使用 ExpressMaint 工具并压缩我的数据库。因此,我在这里写下了我在 Code Project 上的第一篇文章。
解构 Zip 文件
首先,这是一个技巧,所以我们需要了解 Zip 文件是如何制作的。为了演示,我使用了一个十六进制编辑器(二进制编辑器)来向您展示。
我在一个文件夹中右键单击,创建了一个空的 Zip 文件。

太好了,现在我们看到一个 22 字节的空 Zip 文件。
然后,我们添加一个包含文本“Hello World”的文本文件,以供比较。

对于那些想更好地理解 *.zip 文件头构成的人来说,这是头部的分解:
- 本地文件头签名 4 字节 (0x04034b50)
- 提取所需版本 2 字节
- 通用目的位标志 2 字节
- 压缩方法 2 字节
- 最后修改文件时间 2 字节
- 最后修改文件日期 2 字节
- crc-32 4 字节
- 压缩后大小 4 字节
- 未压缩大小 4 字节
- 文件名长度 2 字节
- 额外字段长度 2 字节
- 文件名(可变大小)
- 额外字段(可变大小)
好的,看看这个,我们显然不需要处理头部中的以下字段,因为对于空文件我们只需要 22 字节。
- 未压缩大小 4 字节
- 文件名长度 2 字节
- 额外字段长度 2 字节
好了,理论够了,让我们玩得开心点……
我之所以给这篇文章加上“巧妙的小技巧”的后缀,是因为我们将使用 Shell32.dll 将文件或文件夹复制到目标 Zip 文件中,而这是 Windows 原生支持的功能。
这留下了一个缺陷;我们需要一个目标文件……我们将手动创建它,因此需要了解理论。
如何在 VB.NET 和 C# 中创建 *.zip 文件。
VB.NET
Public Sub CreateZipFile(ByVal Filename As String) 'create a new empty zip file
'Create Header of Zip File
Dim Encoder As New System.Text.ASCIIEncoding
Dim Header As String = "PK" & Chr(5) & Chr(6)
Header = Header.PadRight(22, Chr(0))
'Save file - Make sure your file ends with .zip!
My.Computer.FileSystem.WriteAllBytes(Filename, Encoder.GetBytes(Header), False)
End Sub
C#
public void CreateZipFile(string filename)
{
//Create the header of the Zip File
System.Text.ASCIIEncoding Encoder = new System.Text.ASCIIEncoding();
string sHeader = "PK" + (char)5 + (char)6;
sHeader = sHeader.PadRight(22, (char)0);
//Convert to byte array
byte[] baHeader = System.Text.Encoding.ASCII.GetBytes(sHeader);
//Save File - Make sure your file ends with .zip!
FileStream fs = File.Create(filename);
fs.Write(baHeader, 0, baHeader.Length);
fs.Flush();
fs.Close();
fs = null;
}
那么我们到底完成了什么?我们创建了一个空的 Zip 文件,这与在 Windows 的文件夹中右键单击并选择“**新建**”>“**压缩(zipped)文件夹**”是相同的。
现在我们有了创建空 *.zip 文件的函数,就可以将数据复制到文件中了。
您需要向您的 shell32.dll 文件添加一个引用,该文件位于您的 System32 文件夹中。
由于并非所有运行 Windows 的计算机设置都相同,因此这是查找 Windows 文件夹(包括驱动器号)的方法。

现在我可以看到我的 Windows 文件夹在 C 盘,文件夹是 Windows。我现在知道我要找的文件在 C:\Windows\System32。
在我们的 Visual Studio 项目中,我们需要为此文件添加一个引用,因此在解决方案资源管理器中右键单击您的项目,然后选择“添加引用”。

然后选择“浏览”,并找到文件。

如何在 VB.NET 和 C# 中将文件或文件夹复制到 *.zip 文件。
VB.NET
Public Sub ZipFile(ByVal Input As String, ByVal Filename As String)
Dim Shell As New Shell32.Shell
'Create our Zip File
CreateZipFile(Filename) 'Create a new .zip file
'Copy the file or folder to it
Shell.NameSpace(Filename).CopyHere(Input)
'Wait until the File/Folder has finished writing to zip file...
Do Until Shell.NameSpace(Filename).Items.Count =
Shell.NameSpace(Input).Items.Count
System.Threading.Thread.Sleep(200)
System.Diagnostics.Debug.Print("Waiting...")
Loop
End Sub
C#
public void ZipFile(string Input, string Filename)
{
Shell32.Shell Shell = new Shell32.Shell();
//Create our Zip File
CreateZipFile(Filename);
//Copy the file or folder to it
Shell.NameSpace(Filename).CopyHere(Input,0);
//If you can write the code to wait for the code to finish, please let me know
System.Threading.Thread.Sleep(2000);
}
}
结论
虽然这并不实用,因为您需要编写逻辑来处理现有的 Zip 文件,但写这篇文章很有趣,希望有人觉得它很有启发性。