programming:cs:cs_tips

C# Tips

nameofで取れる。nameofが使えなければ、Expressionとラムダ式を組み合わせると取れる。

NDesk.Optionsが超便利。MIT/X11ライセンスなのも素敵。

Microsoft.Office.Interop.Excel.Applicationでエクセルのシートを操作中に、例外などで異常終了するとexcel.exeがゾンビプロセス化し残り続ける事がある。更に悪い事にExcel.Applicationのプロセスはタスクバーには表れないので、気づいた時には大量のゾンビexcel.exeが存在し、1つずつタスクマネージャで殺していく簡単なお仕事に追われることになる。

この問題は中々根が深くて──というか原因はCOMの解放漏れなんだけど、解放漏れがCでいう所のfreeし忘れなんて明白なものではなく“コードの書き方”ひとつで出来てしまうのが困り物。というわけで、少々行儀は悪いが強制的にガベコレを走らせ、それでもプロセスが残っていたらkillする方向で対策する。

class KillExcelApp
{
    using Excel = Microsoft.Office.Interop.Excel;
    void ProcExcel()
    {
        Excel.Application excelApp = null;
        System.Diagnostics.Process excelProcess = null;
        try
        {
            excelApp = new Excel.Application();
            excelProcess = GetExcelProcess(excelApp);
 
            // Excel.Applicationを使った処理
            ...
 
            // Excel.Applicationを閉じる
            excelApp.Quit();
            excelApp = null;
            // 念のため待ってみる
            System.Threading.Thread.Sleep(2000);
            GC.Collect();
            System.Threading.Thread.Sleep(2000);
        }
        finally
        {
            GC.Collect();
            // Excelが残ってたら強制終了
            if (excelProcess.HasExited == false)
            {
                excelProcess.Kill();
            }
        }
    }
 
    [DllImport("user32.dll")]
    static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
    System.Diagnostics.Process GetExcelProcess(Excel.Application excelApp)
    {
        int id;
        GetWindowThreadProcessId(excelApp.Hwnd, out id);
        return System.Diagnostics.Process.GetProcessById(id);
    }
}

他にいい方法があったら教えてください。

参考サイト:

パーミッション的には全く問題ない場所で、System.IO.File.Copyで新たにファイルをコピーしたあと、同じファイルに上書きコピーしようとするとSystem.UnauthorizedAccessException例外が発生する事がある。 そんな時はCopyで作成したファイルに対してFile.SetAttributes(file, FileAttributes.Normal)してやる。

C#の列挙型は何もしなければint型なので32bit以上の値は扱えないが、longないしulongでenumを作る(正しいC#用語は何と言うんだろう?)と64bitになる。更にフラグの定義では「1L」を使うのがミソ。ただの「1」だと32bit値と見なされ、32ビット以上のシフトが回転してしまう。

enum Flag64 : long
{
    Bit0  = 1 << 0,
    Bit1  = 1 << 1,
    Bit32 = 1 << 32,
    Bit33 = 1L << 33,
}
 
Flag64 b0 = Flag64.b0;    // b0  == Flag64.Bit0,  (long)b0  == 1
Flag64 b1 = Flag64.b1;    // b1  == Flag64.Bit1,  (long)b1  == 2
Flag64 b32 = Flag64.b32;  // b32 == Flag64.Bit0,  (long)b32 == 1
Flag64 b33 = Flag64.b33;  // b33 == Flag64.Bit33, (long)b33 == 8589934592
  • programming/cs/cs_tips.txt
  • 最終更新: 2017-12-13 11:37
  • by Decomo