无法通过Microsoft.Office.Interop.PowerPoint正常中止未知密码

本文关键字:PowerPoint 常中止 未知密码 Interop Office Microsoft | 更新日期: 2023-09-27 18:21:37

尝试使用Microsoft.Office.Interop.PowerPoint打开PPT文件并保存为PDF(或其他文件类型)以进行大批量作业。适用于没有密码的文件。对于有密码的文件,我永远不会知道,我只想优雅地失败。但是,PowerPoint会打开对话框提示,即使我的代码中止了打开该线程的线程,在手动关闭该提示之前,我也不能使用PowerPoint,因此阻止了对其他文件的进一步处理。

建议?

我的代码的基础如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using Microsoft.Office;
using Microsoft.Office.Interop.PowerPoint;
using MT = Microsoft.Office.Core.MsoTriState;
namespace PowerPointConverter
{
    public class PowerPointConverter : IDisposable
    {
    Application app;
    public PowerPointConverter()
    {
        app = new Microsoft.Office.Interop.PowerPoint.Application();
        app.DisplayAlerts = PpAlertLevel.ppAlertsNone;
        app.ShowWindowsInTaskbar = MT.msoFalse;
        app.WindowState = PpWindowState.ppWindowMinimized;
    }
    public bool ConvertToPDF(FileInfo sourceFile, DirectoryInfo destDir)
    {
        bool success = true;

        FileInfo destFile = new FileInfo(destDir.Name + "''" +
        Path.GetFileNameWithoutExtension(sourceFile.Name) + ".pdf");
        Thread pptThread = new Thread(delegate()
        {
        try
        {
            Presentation ppt = null;
            ppt = app.Presentations.Open(sourceFile.FullName, MT.msoTrue, MT.msoTrue, MT.msoFalse);
            ppt.SaveAs(destFile.FullName, PpSaveAsFileType.ppSaveAsPDF, MT.msoFalse);
            ppt.Close();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ppt);
        }
        catch (System.Runtime.InteropServices.COMException comEx)
        {
            success = false;
        }
        });
        pptThread.Start();
        if (!pptThread.Join(20000))
        {
        pptThread.Abort();
        success = false;
        }
        return success;
    }

    public void Dispose()
    {
        Thread appThread = new Thread(delegate()
        {
        try
        {
            if (null != app)
            {
            app.Quit();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
            }
        }
        catch (System.Runtime.InteropServices.COMException) { }
        });
        appThread.Start();
        if (!appThread.Join(10000))
        {
        appThread.Abort();
        }
    }
    }
}

无法通过Microsoft.Office.Interop.PowerPoint正常中止未知密码

将此VBA转换为[anything],您就可以开始了。

Dim oPres As Presentation
On Error Resume Next
Set oPres = Presentations.Open("c:'temp'open.pptx::BOGUS_PASSWORD::")
If Not Err.Number = 0 Then
    MsgBox "Blimey, you trapped the error!" _
        & vbCrLf & Err.Number & vbCrLf & Err.Description
End If

更通用的:

Presentations.Open "filename.ext::open_password::modify_password"

如果你给一个有密码的文件传递一个故意伪造的密码,你会得到一个可捕捉的错误,但PPT不会弹出对话框。如果你给一个没有密码的文件一个密码,它就会打开。

这应该适用于新的或旧的二进制格式文件,我被告知它早在2003年的版本中就可以使用。

感谢Steve的回答。这确实奏效了。

在我们尝试将ProtectedViewWindow用于此目的之前,但这实际上不起作用,在某些情况下退出得很好:

        try {
            windowId = pptApp.ProtectedViewWindows.Open(pptPath, 
                          PRESENTATION_FAKE_PASSWORD).HWND;
        } catch (Exception ex) {
            if (!ex.Message.Contains("could not open")) {
                // Assume it is password protected.
                _conversionUtil.LogError(
                      "Powerpoint seems to be password protected.",
                      _conversionRequest, ex);
            }
        }

基于您的解决方案的代码运行得很好,不需要打开PP一个不必要的时间进行验证:

        Presentation presentation;
        try {
            presentation = pptApplication.Presentations.Open(_localPptPath +  
                  "::" + PRESENTATION_FAKE_PASSWORD + "::", MsoTriState.msoTrue, 
                  MsoTriState.msoFalse, MsoTriState.msoFalse);
        } catch (Exception e) {
            // if error contains smth about password - 
            // assume file is password protected.
            if (e.Message.Contains("password")) {
                throw new ConversionException(
                    "Powerpoint seems to be password protected: " + e.Message, 
                    ConversionStatus.FAIL_PASSWORD_PROTECTED);
            }
            // otherwice rethrow it
            throw;
        }