2013-07-09 2 views
2

Пытается использовать Microsoft.Office.Interop.PowerPoint для открытия файлов PPT и сохранения в виде PDF (или других типов файлов) для больших пакетных заданий. Отлично работает с файлами, у которых нет пароля. С файлами, у которых есть пароль, который я никогда не знаю, я просто хочу изящно потерпеть неудачу. Тем не менее, PowerPoint откроет диалоговое окно, и даже когда мой код прервет нисходящий поток, этот поток я не могу использовать PowerPoint до тех пор, пока это приглашение не будет закрыто вручную, и дальнейшая обработка других файлов будет заблокирована.Невозможно изящно прервать неизвестный пароль через Microsoft.Office.Interop.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(); 
     } 
    } 
    } 
} 
+0

Вы можете отправить сообщение WM_CLOSE во всплывающее окно PowerPoint после ожидания разумного промежутка времени; что, вероятно, вынудит его отменить. – RogerN

ответ

4

Перевести на VBA [любой], и вы должны быть хорошо идти.

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" 

Если передать защищенный пароль файлу намеренно поддельный пароль, вы получите Перехватываемую ошибку, но РРТ не выскакивает диалоговое окно. Если вы передадите пароль без пароля, он просто откроется.

Это должно работать с новыми или старыми двоичный формат файлов, и я сказал, что работает в версиях еще в 2003

+0

Это сработало отлично! Большое спасибо Стиву. – user1919308

+1

Мое удовольствие; на самом деле, спасибо за вопрос. Я знал, что вы можете использовать этот синтаксис, чтобы открыть презентацию, если знаете пароль, но не поняли, пока не спросите, что прохождение фиктивного пароля вызовет ошибку с ловушкой, а не диалоговое окно. Хорошая вещь, чтобы знать. –

+0

Спасибо за ваше решение! Когда я даю поддельный пароль, он, очевидно, генерирует исключение. Есть ли способ сказать, что это исключение «плохой пароль»? например путем анализа кода ошибки? Сообщение довольно общее. – silent

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; 
     } 
Смежные вопросы