9

C# WinForms アプリケーションから PowerPoint と Excel を自動化しています。私がしているのは、PowerPoint からスライドを読み込んで Excel に保存し、両方のアプリを終了することです。Excel は正常に終了しますが、PowerPoint は終了しません。問題は、最初に変換するときは終了しませんが、再度変換すると終了します。

これが私のコードです

try
{
    PowerPoint.Application ppApp;
    PowerPoint.Presentation ppPres;
    List<Company> companies = new List<Company>();

    ppApp = new PowerPoint.Application();
    ppApp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
    ppApp.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized;

    ppPres = ppApp.Presentations.Open(fileTxtBox.Text,
                                      Microsoft.Office.Core.MsoTriState.msoFalse,
                                      Microsoft.Office.Core.MsoTriState.msoFalse,
                                      Microsoft.Office.Core.MsoTriState.msoTrue);

    int slides = ppPres.Slides.Count;

    for (int slide = 1; slide <= slides; slide++)
    {
        int rows = 1;
        PowerPoint.Cell cell;
        int shape = 1;

        for (; shape < ppPres.Slides[slide].Shapes.Count; shape++)
        {
            if (ppPres.Slides[slide].Shapes[shape].HasTable == Microsoft.Office.Core.MsoTriState.msoTrue)
            {
                cell = ppPres.Slides[slide].Shapes[shape].Table.Cell(1, 1);

                if (cell.Shape.TextFrame.TextRange.Text.Trim().ToLower().Contains("realized"))
                {
                    rows = ppPres.Slides[slide].Shapes[shape].Table.Rows.Count;
                    break;
                }
            }
        }

        Company comp = new Company(rows);
        InitializeCompany(ref comp, ppPres.Slides[slide]);
        companies.Add(comp);
    }

    SaveInExcel(companies);

    ppPres.Close();
    ppPres = null;
    ppApp.Quit();
    ppApp = null;

    return;
}

catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

finally
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
}
4

7 に答える 7

12

Microsoft Office アプリケーションをシャットダウンするのは、最初は難しいように思えるかもしれませんが、操作の正しい順序を確立してしまえば、実際にはまったく難しくありません。

MS Office アプリケーションのリリースは、次の 2 段階で安全かつ効果的に行うことができます。

(1) 最初に、名前付き変数内で参照を保持していないすべてのマイナー オブジェクトを解放します。これを行うには、GC.Collect() を呼び出してから GC.WaitForPendingFinalizers ( )を呼び出します。Visual Studio Tools for Office (VSTO) を使用している場合、COM オブジェクトを正常に解放するには、このコマンドのペアを2 回呼び出す必要があることに注意してください。ただし、VSTO を使用していないため、一度呼び出すだけで十分です。

(2) 次に、所有している各変数でMarshall.FinalReleaseComObject()への呼び出しを使用して、名前付き変数を介して保持しているオブジェクトを明示的に解放します。

COM コンポーネントに必要なすべての変数を明示的に解放することを忘れないでください。1 つでも見逃すと、MS Office アプリケーションがハングします。コードには、PowerPoint アプリケーションへの参照を保持する 3 つの名前付き変数ppApp( 、ppPres、および) があるようcellです。

これをすべて考慮に入れると、クリーンアップは次のようになるはずです。これはusing System.Runtime.InteropServices、名前空間内またはコード ドキュメントの上部のいずれかを利用します。

// using System.Runtime.InteropServices

// Cleanup:
GC.Collect();
GC.WaitForPendingFinalizers();

Marshal.ReleaseComObject(cell);

ppPres.Close();
Marshal.ReleaseComObject(ppPres);

ppApp.Quit();
Marshal.ReleaseComObject(ppApp);

試してみてください。これでうまくいくはずです... (うまくいかない場合は、さらに多くのコードを表示する必要があるかもしれません。) 詳細については、Excel アプリケーションを適切にリリースする方法について詳しく説明します。

C# で Excel 相互運用オブジェクトを適切にクリーンアップする方法

これが役立つことを願って、それがどうなるか教えてください...

-- マイク

于 2009-06-11T16:03:04.157 に答える
2

最近、ガベージコレクションからオブジェクトの終了とクローズまで、何もうまくいかないことに気付きました。だから私は代替案を思いつきました。仕事が終わったら実行中のプロセスを見つけ、コードでそれを殺しました。

コード:

 Process[] pros = Process.GetProcesses();
  for (int i = 0; i < pros.Count(); i++)
   {
   if (pros[i].ProcessName.ToLower().Contains("powerpnt"))
        {
          pros[i].Kill();
        }
   }
于 2013-06-11T06:57:07.837 に答える
1

Power Point アプリケーション インスタンスを表示しているように見えますが、そうでない場合は、表示されていないダイアログが表示されている可能性があります。おそらく、変更の保存ダイアログです。アプリが非表示で実行されている場合は、表示して、そのようなダイアログがポップアップし、Power Point が閉じられないかどうかを確認します。

于 2009-06-11T14:55:18.920 に答える
0

ppAppオブジェクトに対してQuit()を呼び出した後、次のことを試してください。

System.Runtime.InteropServices.Marshal.ReleaseComObject(ppApp);

約束はありませんが、うまくいくかもしれませんし、まったく何もしないかもしれません。Office COM を適切に閉じることは、私にとってブードゥー教のようなものでした。

于 2009-06-11T15:00:00.610 に答える
0

Office-365 アプリケーションを管理するために VS2019 で VSTO を使用していますが、Powerpoint を除いて、「Application.Quit()」を使用してすべてが完全に機能します。

PP がフリーズすることもあれば、終了するまで何秒間も大量の「ThreadException」が発生することもあります (実際にそのスレッドを中止すると思います)。そして、上記のすべてのコードと、Google で見つけた他の多くのヒントをテストしましたが、うまくいきませんでした。

これは汚い解決策ですが、プレゼンテーションが保存された直後に機能し、PP を閉じます。

ただし、私のソリューションは、カスタム RIBBON GROUP のボタンのクリック イベントによって開始されることをお勧めします。それ以外の場合は、プログラムで PP ウィンドウを「見つけて」選択する必要があります (それにフォーカスを置きます)。

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

SendKeys.Send("%{F4}")

それはすべての人々です...

于 2021-07-14T23:24:45.847 に答える