C# 检测受密码保护的PPT和XLS文档

C# 检测受密码保护的PPT和XLS文档,c#,office-interop,C#,Office Interop,我找到了这个答案,它提供了一个很好的方法来检测DOC和XLS文件的密码保护 //Flagged with password if (bytes.Skip(0x20c).Take(1).ToArray()[0] == 0x2f) return true; //XLS 2003 if (bytes.Skip(0x214).Take(1).ToArray()[0] == 0x2f) return true; //XLS 2005 if (bytes.Skip(0x20B).Take(1).ToArra

我找到了这个答案,它提供了一个很好的方法来检测DOC和XLS文件的密码保护

//Flagged with password
if (bytes.Skip(0x20c).Take(1).ToArray()[0] == 0x2f) return true; //XLS 2003
if (bytes.Skip(0x214).Take(1).ToArray()[0] == 0x2f) return true; //XLS 2005
if (bytes.Skip(0x20B).Take(1).ToArray()[0] == 0x13) return true; //DOC 2005

然而,它似乎并没有涵盖所有的XLS文件,我也在寻找一种方法,以同样的方式检测PPT文件。您知道这些文件类型要查看哪些字节吗?

我将PowerPoint演示文稿保存为.ppt和.pptx,打开时需要密码,打开时需要密码,打开时使用7-Zip,并得出初步结论:

  • 没有密码的.pptx文件始终使用标准的.zip文件格式
  • .ppt文件是复合文档
  • 带有密码的.pptx文件也可组成文档
  • 所有密码复合文档都包含一个名为*Encrypt的条目*
要运行此代码,您需要安装NuGet软件包OpenMcdf。这是我能找到的第一个用于阅读复合文档的C#库

using OpenMcdf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace _22916194
{
    //http://stackoverflow.com/questions/22916194/detecing-password-protected-ppt-and-xls-documents
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var file in args.Where(File.Exists))
            {
                switch (Path.GetExtension(file))
                {
                    case ".ppt":
                    case ".pptx":
                        Console.WriteLine($"* {file} " +  (HasPassword(file) ? "is " : "isn't ") + "passworded");
                        Console.WriteLine();
                        break;

                    default:
                        Console.WriteLine($" * Unknown file type: {file}");
                        break;
                }
            }

            Console.ReadLine();

        }

        private static bool HasPassword(string file)
        {
            try
            {
                using (var compoundFile = new CompoundFile(file))
                {
                    var entryNames = new List<string>();
                    compoundFile.RootStorage.VisitEntries(e => entryNames.Add(e.Name), false);

                    //As far as I can see, only passworded files contain an entry with a name containing Encrypt
                    foreach (var entryName in entryNames)
                    {
                        if (entryName.Contains("Encrypt"))
                            return true;
                    }
                    compoundFile.Close();

                }
            }
            catch (CFFileFormatException) {
                //This is probably a .zip file (=unprotected .pptx)
                return false;
            }
            return false;
        }
    }
}
使用OpenMcdf;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
命名空间_22916194
{
//http://stackoverflow.com/questions/22916194/detecing-password-protected-ppt-and-xls-documents
班级计划
{
静态void Main(字符串[]参数)
{
foreach(args.Where(file.Exists)中的var文件)
{
开关(Path.GetExtension(文件))
{
案例“.ppt”:
案例“.pptx”:
WriteLine($“*{file}”+(HasPassword(file)?“is”:“is not”)+“passworded”);
Console.WriteLine();
打破
违约:
WriteLine($“*未知文件类型:{file}”);
打破
}
}
Console.ReadLine();
}
私有静态bool HasPassword(字符串文件)
{
尝试
{
使用(var compoundFile=新的compoundFile(file))
{
var entryNames=新列表();
compoundFile.RootStorage.VisitEntries(e=>entryNames.Add(e.Name),false);
//就我所见,只有密码文件包含一个名为Encrypt的条目
foreach(entryNames中的var entryName)
{
if(entryName.Contains(“Encrypt”))
返回true;
}
compoundFile.Close();
}
}
捕获(CFFileFormatException){
//这可能是一个.zip文件(=unprotected.pptx)
返回false;
}
返回false;
}
}
}

您应该能够扩展此代码以处理其他Office格式。顶部的结论应该是正确的,除了您需要在CompoundDocument中查找包含*Encrypt*的文件名以外的其他数据(我快速查看了.doc文件,但它的工作方式似乎并不完全相同).

您是如何做到这一点的?我试图挖掘我的旧代码,但我想我只是没有弄明白,最终放弃了。抱歉:(对于xls(x)文件,使用npoi可能是一种选择?请参见此处:-npoi是apache poi的c#端口。在我的一个项目中使用了它,并且它与xls和xlsx文件一起很好地用于检查密码。但是不知道它们是如何做到的。这里可能更深入地了解它们是如何做到这一点的:Take(1)。ToArray()[0]与
.First()相同