2

尝试使用 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();
        }
    }
    }
}
4

2 回答 2

5

将此 VBA 转换为 [whatever],您应该一切顺利。

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 年的版本。

于 2013-07-10T02:05:29.770 回答
0

感谢史蒂夫的回答。这实际上奏效了。

在我们尝试为此目的使用 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;
        }
于 2014-06-06T16:06:55.957 回答