65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Windows Shell API 和 C# 压缩 Zip 文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (31投票s)

2005年10月24日

公共领域

3分钟阅读

viewsIcon

465538

downloadIcon

6871

使用 C# 中的 Windows Shell API 压缩 Zip 文件,而无需显示复制进度窗口。

Sample Image

引言

这是我编写的关于解压缩 Zip 文件的文章的后续文章。 使用此代码,您可以使用 C# 中的 Windows Shell API 压缩 Zip 文件,并且无需显示上面的复制进度窗口。 通常,当您使用 Shell API 压缩 Zip 文件时,即使您设置了选项告诉 Windows 不显示它,它也会显示复制进度窗口。 为了解决这个问题,您可以将 Shell API 代码移动到单独的可执行文件中,然后使用 .NET Process 类启动该可执行文件,并确保将进程窗口样式设置为 'Hidden'。

背景

是否曾经需要压缩 Zip 文件,并且需要比许多免费压缩库更好的 Zip? 也就是说,您需要压缩文件夹和子文件夹以及文件。 Windows Zipping 可以压缩不仅仅是单个文件。 您所需要的只是以编程方式让 Windows 静默压缩这些 Zip 文件的方法。 当然,您可以花费 300 美元购买其中一个商业 Zip 组件,但如果您只需要压缩文件夹层次结构,那么很难击败免费软件。

使用代码

以下代码显示了如何使用 Windows Shell API 压缩 Zip 文件。 首先,创建一个空的 Zip 文件。 为此,创建一个正确构造的 byte 数组,然后将该数组另存为扩展名为 '.zip' 的文件。 我怎么知道将哪些字节放入数组中? 好吧,我只是使用 Windows 创建了一个 Zip 文件,其中压缩了一个文件。 然后我用 Windows 打开了 Zip,并删除了压缩文件。 这给我留下了一个空的 Zip。 接下来,我在十六进制编辑器 (Visual Studio) 中打开了空的 Zip 文件,并查看了十六进制字节值,并使用 Windows Calc 将它们转换为十进制,并将这些十进制值复制到我的 byte 数组代码中。 源文件夹指向您要压缩的文件夹。 目标文件夹指向您刚刚创建的空的 Zip 文件。 此代码将压缩 Zip 文件,但也会显示复制进度窗口。 要使此代码工作,您还需要设置对 COM 库的引用。 在“引用”窗口中,转到“COM”选项卡,然后选择标记为“Microsoft Shell Controls and Automation”的库。

//Create an empty zip file
byte[] emptyzip = new byte[]{80,75,5,6,0,0,0,0,0, 
                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

FileStream fs = File.Create(args[1]);
fs.Write(emptyzip, 0, emptyzip.Length);
fs.Flush();
fs.Close();
fs = null;

//Copy a folder and its contents into the newly created zip file
Shell32.ShellClass sc = new Shell32.ShellClass();
Shell32.Folder SrcFlder = sc.NameSpace(args[0]);
Shell32.Folder DestFlder = sc.NameSpace(args[1]); 
Shell32.FolderItems items = SrcFlder.Items();
DestFlder.CopyHere(items, 20);

//Ziping a file using the Windows Shell API 
//creates another thread where the zipping is executed.
//This means that it is possible that this console app 
//would end before the zipping thread 
//starts to execute which would cause the zip to never 
//occur and you will end up with just
//an empty zip file. So wait a second and give 
//the zipping thread time to get started
System.Threading.Thread.Sleep(1000);

本文附带的示例解决方案演示了如何将此代码放入控制台应用程序中,然后启动此控制台应用程序来压缩 Zip 文件,而无需显示复制进度窗口。

下面的代码显示了一个按钮单击事件处理程序,其中包含用于启动控制台应用程序的代码,以便在压缩期间没有 UI

private void btnUnzip_Click(object sender, System.EventArgs e)
{
    //Test to see if the user entered a zip file name
    if(txtZipFileName.Text.Trim() == "")
    {
        MessageBox.Show("You must enter what" + 
               " you want the name of the zip file to be");
        //Change the background color to cue the user to what needs fixed
        txtZipFileName.BackColor = Color.Yellow;
        return;
    }
    else
    {
        //Reset the background color
        txtZipFileName.BackColor = Color.White;
    }

    //Launch the zip.exe console app to do the actual zipping
    System.Diagnostics.ProcessStartInfo i =
        new System.Diagnostics.ProcessStartInfo(
        AppDomain.CurrentDomain.BaseDirectory + "zip.exe");
    i.CreateNoWindow = true;
    string args = "";

    
    if(txtSource.Text.IndexOf(" ") != -1)
    {
        //we got a space in the path so wrap it in double qoutes
        args += "\"" + txtSource.Text + "\"";
    }
    else
    {
        args += txtSource.Text;
    }

    string dest = txtDestination.Text;

    if(dest.EndsWith(@"\") == false)
    {
        dest += @"\";
    }

    //Make sure the zip file name ends with a zip extension
    if(txtZipFileName.Text.ToUpper().EndsWith(".ZIP") == false)
    {
        txtZipFileName.Text += ".zip";
    }

    dest += txtZipFileName.Text;

    if(dest.IndexOf(" ") != -1)
    {
        //we got a space in the path so wrap it in double qoutes
        args += " " + "\"" + dest + "\"";
    }
    else
    {
        args += " " + dest;
    }

    i.Arguments = args;
    

    //Mark the process window as hidden so 
    //that the progress copy window doesn't show
    i.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;    
    System.Diagnostics.Process p = System.Diagnostics.Process.Start(i);
    p.WaitForExit();
    MessageBox.Show("Complete");
}

关注点

  • 它是免费的!
  • 您可以使用 Windows 创建 Zip 文件,而不是使用昂贵的 Zip 库来处理文件夹层次结构。
  • 无论是否显示复制进度窗口,均可使用。
  • 使用 Windows Shell API,它具有许多有趣的 Windows 集成可能性。
© . All rights reserved.