using System;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop.PowerPoint;
using static OfficeImageReducer.ClassMyCommon;

/// <summary>
/// メインフォームに関する処理
/// </summary>
namespace OfficeImageReducer
{
    /// <summary>
    /// メインウインドウフォーム
    /// </summary>
    public partial class FormMain : Form
    {
        /// <summary>
        /// ZIP解凍用の一時ファイルネーム
        /// </summary>
        private string ZipFileName;

        /// <summary>
        /// ZIP解凍用の一時解凍先フォルダネーム
        /// </summary>
        private string ExtractPath;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public FormMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// フォームロードイベント
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void FormMain_Load(object sender, EventArgs e)
        {
#if false
            // 多重起動チェック
            //Process.GetProcessesByName メソッド
            //指定したプロセス名を共有するリモートコンピュータ上の
            //すべてのプロセスリソースに関連付けます。
            string pn = System.Diagnostics.Process.GetCurrentProcess().ProcessName; //Process.ProcessName プロパティ(プロセスの名前を取得します)
            if (System.Diagnostics.Process.GetProcessesByName(pn).GetUpperBound(0) > 0)
            {
                //! 多重起動しているならばエラーメッセージ表示して終了
                MessageBox.Show("すでに起動しています。", TITLE + " エラーメッセージ",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                Environment.Exit(0);
            }
#endif
            frmMain = this;
            //! フォームの右上ボタンと左上の右クリックメニューをカスタマイズ
            FormControlBoxCustomize(this);
            Log = new ClassLog(textBox1);
            this.Text = TITLE + " " + VERSION;
            //! オープニングメッセージを表示
            button1.PerformClick();
            // 表示開始後0.5秒は最前面にもってくる
            Show();
            TopMost = true;
            WaitTickCount(500);
            TopMost = false;
        }

        /// <summary>
        /// [About]ボタンクリックイベント
        /// プログラムタイトル　バージョン　オープニングメッセージを表示
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void button1_Click(object sender, EventArgs e)
        {
            Log.Put(
                 "----------------------------------------------------------------\r\n"
                + TITLE + " " + VERSION + "\r\n"
                + OPENING_MSG
                + "\r\n"
                + "----------------------------------------------------------------\r\n"
                );
        }

        /// <summary>
        /// [Clear Log]ボタンクリックイベント
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void button2_Click(object sender, EventArgs e)
        {
            Log.Clear();
        }

        /// <summary>
        /// [Quit]ボタンクリックイベント
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void button3_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// ログテキストエリアのドラッグエンターイベント
        /// ドラッグエンターされたものがファイルの場合のみ、ドラッグを受け付ける
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void textBox1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop) == true)
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        /// <summary>
        /// ドロップされた時の処理
        /// </summary>
        /// <param name="sender">イベントを発生させたオブジェクトへの参照</param>
        /// <param name="e">処理されるイベントに応じた特定のオブジェクト</param>
        private void textBox1_DragDrop(object sender, DragEventArgs e)
        {
            Color textBox1BackColor = textBox1.BackColor;

            //! 作業中はさらにドラッグ＆ドロップできないようにする
            textBox1.Enabled = false;
            textBox1.BackColor = this.BackColor;

            //! ドラッグされたファイル・フォルダのパスを格納
            string[] strFileNames = (string[])e.Data.GetData(DataFormats.FileDrop, false);

            //! ひとつずつoffice2007ファイルをメイン処理に渡す。
            foreach (string strFileName in strFileNames)
            {
                Main_Process(strFileName);
                WaitTickCount(100);
            }

            textBox1.Enabled = true;
            textBox1.BackColor = textBox1BackColor;
        }

        /// <summary>
        /// フォルダを再帰的に下りて全ファイルの属性を削除
        /// </summary>
        /// <param name="dirInfo">dirInfo フォルダ操作用インスタンス</param>
        private void RemoveReadonlyAttribute(DirectoryInfo dirInfo)
        {
            try
            {
                //基のフォルダの属性を変更
                if ((dirInfo.Attributes & FileAttributes.ReadOnly) ==
                    FileAttributes.ReadOnly)
                    dirInfo.Attributes = FileAttributes.Normal;
                //フォルダ内のすべてのファイルの属性を変更
                foreach (FileInfo fi in dirInfo.GetFiles())
                    if ((fi.Attributes & FileAttributes.ReadOnly) ==
                        FileAttributes.ReadOnly)
                        fi.Attributes = FileAttributes.Normal;
                //サブフォルダの属性を回帰的に変更
                foreach (DirectoryInfo di in dirInfo.GetDirectories())
                    RemoveReadonlyAttribute(di);
            }
            catch (Exception ex)
            {
                Log.Put("Error:RemoveReadonlyAttribute():ex.Message\r\n" + ex.Message);
                Log.Put("Error:RemoveReadonlyAttribute():ex.StacTrace\r\n" + ex.StackTrace);
            }
        }

        /// <summary>
        /// 作業終了後のクリーンアップ処理
        /// 作業用フォルダとZIPが残っていれば削除
        /// </summary>
        private void CleanUp()
        {
            if (ExtractPath != "")
            {
                try
                {
                    if (Directory.Exists(ExtractPath))
                    {
                        //DirectoryInfoオブジェクトの作成
                        DirectoryInfo di = new DirectoryInfo(ExtractPath);

                        //フォルダ以下のすべてのファイル、フォルダの属性を削除
                        RemoveReadonlyAttribute(di);

                        //フォルダを根こそぎ削除
                        //di.Delete(true);
                        Directory.Delete(ExtractPath, true);
                    }
                }
                catch (Exception ex)
                {
                    Log.Put("Error:CleanUp():ex.Message\r\n" + ex.Message);
                    Log.Put("Error:CleanUp():ex.StacTrace\r\n" + ex.StackTrace);
                }
            }

            if (ZipFileName != null)
            {
                File.Delete(ZipFileName);
            }
        }

        /// <summary>
        /// PNGファイルの中に透明色（tRNSチャンク）透過色（αチャンネル）があるか判定する
        /// </summary>
        /// <param name="PngFileName">フルパス付きPNGファイルネーム</param>
        /// <returns>0:透明色透過色なし 1:tRNSチャンク透明色あり 2:αチャンネル透過色あり</returns>
        private int PngTransCheck(string PngFileName)
        {
            //Log.Put("tRNS Chunk Check:" + PngFileName);
            string[] StrArray;
            StrArray = PngFileName.Split('\\');
            string SplitPngFileName = StrArray[StrArray.Length - 1];

            int fileSize = 0; //ファイルのサイズ
            int bufPos = 0; //データ格納用配列内の追加位置
            Byte[] buf = null; //データ格納用配列を仮確保
            //Array.Resize(ref buf, 1);

            using (FileStream fs = new FileStream(PngFileName, FileMode.Open, FileAccess.Read))
            {
                fileSize = (int)fs.Length; //ファイルのサイズ
                Array.Resize(ref buf, fileSize); //データ格納用配列サイズ決定

                int readSize; //Readメソッドで読み込んだバイト数
                int remain = fileSize; //読み込むべき残りのバイト数

                while (remain > 0)
                {
                    //1024Bytesずつ読み込む
                    readSize = fs.Read(buf, bufPos, Math.Min(1024, remain));
                    bufPos += readSize;
                    remain -= readSize;
                }
            }

            //buf[] をチェック
            bufPos = 8; //8byte目から確認
            int ChunkSize;
            while (bufPos < fileSize)
            {
                ChunkSize = (buf[bufPos] << 24) + (buf[bufPos + 1] << 16) + (buf[bufPos + 2] << 8) + buf[bufPos + 3];
                //Log.Put("chunksize=" + ChunkSize.ToString);
                bufPos += 4;
                if (buf[bufPos] == 't' && buf[bufPos + 1] == 'R'
                    && buf[bufPos + 2] == 'N' && buf[bufPos + 3] == 'S')
                {
                    Log.Put("tRNSチャンクを検出しました。透明色があります。");
                    Log.Put("tRNS chunk was detected. There is a transparent color.");
                    //Log.Put(SplitPngFileName + " has tRNS chunk.");
                    return 1;
                }
                bufPos += 4;
                bufPos += ChunkSize;
                bufPos += 4;
            }

            // PNG(BMP)ファイルオープン
            using (Bitmap bmp = new Bitmap(PngFileName))
            {
                if (bmp.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb
                || bmp.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
                {
                    //アルファチャンネルのあるＰＮＧフォーマット

                    System.Drawing.Imaging.BitmapData bmpdat;

                    bmpdat = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size),
                        System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

                    Array.Resize(ref buf, bmp.Width * bmp.Height * 4); //データ格納用配列サイズ決定
                    System.Runtime.InteropServices.Marshal.Copy(bmpdat.Scan0, buf, 0, buf.Length);
                    int PixelX;
                    int PixelY;

                    for (PixelY = 0; PixelY < bmp.Height; PixelY++)
                    {
                        System.Windows.Forms.Application.DoEvents();
                        for (PixelX = 0; PixelX < bmp.Width; PixelX++)
                        {
                            Byte Alpha; //αチャンネル 0:透明 ～ 255:完全不透明
                            Byte Red;
                            Byte Green;
                            Byte Blue;

                            Alpha = buf[(PixelY * bmp.Width + PixelX) * 4 + 3];
                            Red = buf[(PixelY * bmp.Width + PixelX) * 4 + 2];
                            Green = buf[(PixelY * bmp.Width + PixelX) * 4 + 1];
                            Blue = buf[(PixelY * bmp.Width + PixelX) * 4 + 0];
                            if (Alpha < 255)
                            {
                                Log.Put("αチャンネルを検出しました。透過色があります。");
                                Log.Put("Alpha channel was detected. There is a transparent color.");
                                //Log.Put(SplitPngFileName + " has alpha chunnel.");
                                //Log.Put("X,Y ARGB = " + PixelX + "," + PixelY + "," + Alpha + "," + Red + "," + Green + "," + Blue);
                                //!αチャンネル255未満を検出したら１を返す (0:透明 ～ 255:完全不透明)
                                return 2;
                            }
                        }
                    }
                }
            }

            return 0;
        }

        /// <summary>
        /// メイン処理
        /// </summary>
        /// <param name="OrgFileName">Office2007形式のフルパス付ファイルネーム</param>
        private void Main_Process(string OrgFileName)
        {
            //! ファイルの存在確認を行い、なければ終了。引数がフォルダ名だった場合も終了
            if (File.Exists(OrgFileName) == false)
            {
                return;
            }

            // ログにパスを表示
            Log.Put("====================");
            Log.Put(OrgFileName);
            System.Windows.Forms.Application.DoEvents();

            // PNGからJPGへ変換されたファイル数
            UInt32 JPGcount = 0;
            // ZIP解凍用の一時ファイルネーム
            ZipFileName = Path.GetDirectoryName(OrgFileName) + "\\~OfficeImgRedTemp.zip";
            // ZIP解凍用の一時解凍先フォルダネーム
            ExtractPath = Path.GetDirectoryName(OrgFileName) + "\\~OfficeImgRedExtract";
            // Office2007系ファイルの中にあるコンテンツの管理ファイル
            string CurrentTypesFileName = ExtractPath + "\\[Content_Types].xml";

            CleanUp();

            //! office2007ファイルでなければ終了
            string FileExtension = OrgFileName.Substring(OrgFileName.Length - 5).ToLower();
            if ((FileExtension != ".xlsx") &&
                (FileExtension != ".xlsm") &&
                (FileExtension != ".pptx") &&
                (FileExtension != ".pptm") &&
                (FileExtension != ".docx") &&
                (FileExtension != ".docm"))
            {
                Log.Put("office2007 ファイル以外には対応していません。");
                Log.Put("It is not a OFFICE2007 file.");
                return;
            }

            // ファイルの拡張子をピリオドなしで格納
            FileExtension = OrgFileName.Substring(OrgFileName.Length - 4).ToLower();

            Log.Put("analyzing...");

            try
            {
                // 前の処理の残骸残っていればクリーンナップ
                CleanUp();

                //! office2007ファイルをZIPファイルへリネームコピー
                File.Copy(OrgFileName, ZipFileName);
                // ZIP解凍作業用フォルダ作成
                try
                {
                    Directory.CreateDirectory(ExtractPath);
                }
                catch (Exception ex)
                {
                    Log.Put("作業用フォルダの作成に失敗しました。:" + ex.Message);
                }

                // ZIP解凍
                // リューション エクスプローラー内、[参照設定] から
                // ZipFile クラスを含む DLL(System.IO.Compression.FileSystem.dll) を手動で追加すること
                ZipFile.ExtractToDirectory(ZipFileName, ExtractPath, Encoding.GetEncoding("shift_jis"));

                // 解凍したZIPの中に [Content_Types].xml があるかどうか確認する。
                if (!(File.Exists(CurrentTypesFileName)))
                {
                    // 存在しないならクリーンアップして終了。
                    Log.Put("対象ファイルの解析ができません。");
                    CleanUp();
                    return;
                }

                // PNGを格納しているパス
                string MediaPath;
                if (Directory.Exists(ExtractPath + "\\xl\\media\\"))
                {
                    MediaPath = ExtractPath + "\\xl\\media";
                }
                else if (Directory.Exists(ExtractPath + "\\ppt\\media\\"))
                {
                    MediaPath = ExtractPath + "\\ppt\\media";
                }
                else if (Directory.Exists(ExtractPath + "\\word\\media\\"))
                {
                    MediaPath = ExtractPath + "\\word\\media";
                }
                else
                {
                    Log.Put("ファイルの中にメディア格納フォルダがありません。");
                    Log.Put("There is no media folder in the file.");
                    CleanUp();
                    return;
                }

                // フルパス付PNGファイル名
                string[] MediaFileNames = Directory.GetFiles(MediaPath, "*.png");
                if (MediaFileNames.Length == 0)
                {
                    Log.Put("ファイルの中にPNG(BMP)ファイルがありません。");
                    Log.Put("There is no PNG(BMP) in the file.");
                    CleanUp();
                    return;
                }
#if false
                foreach (string MediaFileName in MediaFileNames)
                {
                    Log.Put(MediaFileName);
                }
#endif
                // *.rels リレーションファイルすべてをリストアップ
                string[] RelsFileNames = Directory.GetFiles(ExtractPath, "*.rels", SearchOption.AllDirectories);
#if false
                foreach (string RelsFileName in RelsFileNames)
                {
                    Log.Put(RelsFileName);
                }
#endif
                // 作業用文字列の配列
                string[] StrArray;
                // ファイル読み出しデータ格納用文字列
                string Result = String.Empty;

                // 取得したPNGファイルの処理をする
                foreach (string MediaFileName in MediaFileNames)
                {
                    StrArray = MediaFileName.Split('\\');
                    // パスなしPNGファイル名を格納
                    string SplitMediaFileName = StrArray[StrArray.Length - 1];
                    Log.Put("---");
                    Log.Put(SplitMediaFileName);

                    // PNGファイルのサイズを取得
                    long Medialen = new FileInfo(MediaFileName).Length;

                    // 作業用JPGファイル
                    string TmpJpgFileName = MediaPath + "~OfficeImgRedtemp.jpg";

                    //PNGファイルを開く
                    try
                    {
                        //前回の作業ファイルが残っていれば削除する
                        File.Delete(TmpJpgFileName);

                        //PNGに透過透明がある場合はJPG化せず、次のPNGファイルを処理する
                        if (0 != PngTransCheck(MediaFileName))
                        {
                            //Log.Put("透過色");
                            continue;
                        }
                        // PNG(BMP)ファイルオープン
                        using (Bitmap bmp = new Bitmap(MediaFileName))
                        {
                            //JPEG形式で保存する
                            bmp.Save(TmpJpgFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                        }
                    }
                    catch
                    {
                        // 不正なBMP/PNGであればオープン時に例外が発生する。
                        File.Delete(TmpJpgFileName);
                        // 次のPNGファイルの処理へ
                        continue;
                    }

                    // 生成されたJPGファイルサイズを格納
                    long Jpglen = new FileInfo(TmpJpgFileName).Length;

                    // 生成されたJPGファイルがもとのPNGより20%以上縮小された場合はJPGを採用する
                    if (Jpglen > (Medialen * 0.8))
                    {
                        // 生成されたJPGファイルがもとのPNGより20%以上縮小されなかった場合
                        Log.Put("JPG化してもサイズが小さくなりませんでした。");
                        Log.Put("The data size was not become smaller.");
                        File.Delete(TmpJpgFileName);
                    }
                    else
                    {
                        // 生成されたJPGファイルがもとのPNGより20%以上縮小された場合
                        // フルパス付JPGファイル名
                        string NewMediaFileName = "";
                        int j;
                        for (j = 0; ; j++)
                        {
                            // フルパス付JPGファイル名候補を格納
                            if (j == 0)
                            {
                                NewMediaFileName = MediaFileName.Substring(0, MediaFileName.Length - 4) + ".jpeg";
                            }
                            else
                            {
                                NewMediaFileName = MediaFileName.Substring(0, MediaFileName.Length - 4) + "(" + (j - 1).ToString() + ").jpeg";
                            }

                            // 一時ファイネームのJPGを正式なファイル名に変更する。
                            if (File.Exists(NewMediaFileName) == true)
                            {
                                // JPGファイルネームがかぶった場合は9999回までリトライするが、それでもだめだった場合はあきらめる
                                if (j > 9999)
                                {
                                    break;
                                }

                                // JPGファイルネームがかぶった場合はリトライ
                                continue;
                            }
                            else
                            {
                                // リネームする
                                File.Move(TmpJpgFileName, NewMediaFileName);
                                // もとからあったPNGファイルを削除
                                File.Delete(MediaFileName);
                                break; // forループ脱出
                            }
                        }
                        if (j > 9999)
                        {
                            // 9999回までリトライしてだめならあきらめて次のPNGファイルを処理する。
                            File.Delete(TmpJpgFileName);
                            continue;
                        }

                        StrArray = NewMediaFileName.Split('\\');
                        // フルパスなしJPGファイル名を格納
                        string SplitNewMediaFileName = StrArray[StrArray.Length - 1];
                        //Log.Put(SplitMediaFileName + " was converted to " + SplitNewMediaFileName + ".");
                        Log.Put(SplitMediaFileName.Split('.')[0] + " was converted to JPG.");
                        // JPGに変換したPNGファイルの数をカウント
                        JPGcount = JPGcount + 1;

                        System.Windows.Forms.Application.DoEvents(); //ログ表示更新の為

                        // リレーションファイル内のPNGファイル名をJPGファイル名にする
                        foreach (string RelsFileName in RelsFileNames)
                        {
                            // リレーションファイルの中身を読みだす
                            Result = String.Empty;
                            using (StreamReader Reader = new StreamReader(RelsFileName, Encoding.GetEncoding("shift-jis")))
                            {
                                Result = Reader.ReadToEnd();
                                //Log.Put(Result);
                            }

                            // リレーションファイルの中にPNGファイルネームがある場合はJPGファイルネームに置換して上書き
                            if (Result.IndexOf(SplitMediaFileName) >= 0)
                            {
                                //Log.Put(Result);
                                Result = Result.Replace(SplitMediaFileName, SplitNewMediaFileName);
                                //上書モードでリレーションファイルを開く
                                using (StreamWriter Writer = new StreamWriter(RelsFileName, false, Encoding.GetEncoding("shift-jis")))
                                {
                                    // リレーションファイル上書き
                                    Writer.Write(Result);
                                    //Log.Put(Result);
                                }
                            }
                        }
                    }
                }

                if (JPGcount == 0)
                {
                    Log.Put("JPG化すべきデータはありませんでした。");
                    Log.Put("There is no image data to be converted to JPG.");
                    return;
                }

                // ExtractPath + "\[Content_Types].xml の中に拡張子jpegを追記する
                Result = String.Empty;
                using (StreamReader Reader = new StreamReader(CurrentTypesFileName, Encoding.GetEncoding("shift-jis")))
                {
                    Result = Reader.ReadToEnd();
                }
                //追加する文字列 <Default Extension="jpeg" ContentType="application/jpeg"/>
                if (Result.ToLower().IndexOf("default extension=\"jpeg\"") >= 0)
                {
                    //すでに拡張子jpegが登録されているので変更不要
                }
                else
                {
                    Result = Result.Replace(
                                 "<Default Extension=\"xml\" ContentType=\"application/xml\"/>",
                                 "<Default Extension=\"xml\" ContentType=\"application/xml\"/><Default Extension=\"jpeg\" ContentType=\"application/jpeg\"/>");
                    //上書モードでShift-JISファイルを開く
                    using (StreamWriter Writer = new System.IO.StreamWriter(CurrentTypesFileName, false, Encoding.GetEncoding("shift-jis")))
                    {
                        Writer.Write(Result);
                        //Log.Put(Result);
                    }
                }

                // 再圧縮する前に、JPEG化まえのZIP書庫を削除する
                File.Delete(ZipFileName);

                // ZIP書庫を作成する　サイズ優先
                //ZipFile.CreateFromDirectory(ExtractPath, ZipFileName, CompressionLevel.Optimal, false, Encoding.GetEncoding("shift_jis"));
                // ZIP書庫を作成する　処理速度優先
                ZipFile.CreateFromDirectory(ExtractPath, ZipFileName, CompressionLevel.Fastest, false, Encoding.GetEncoding("shift_jis"));

                // 圧縮前の office2007 ファイルをリネームする　例 aaaa.xlsx -> aaaa(0).xlsx
                for (int i = 0; ; i++)
                {
                    // リネームするファイル名
                    string NewOrgFileName
                    = OrgFileName.Substring(0, OrgFileName.Length - 5) + "(" + i.ToString() + ")" + OrgFileName.Substring(OrgFileName.Length - 5);

                    if (i >= 10000)
                    {
                        File.Delete(NewOrgFileName);
                    }

                    if (File.Exists(NewOrgFileName) == true)
                    {
                        // ファイルの存在確認を行い、すでに存在すれば、リトライ
                        continue;
                    }
                    else
                    {
                        // リネーム処理して終了
                        File.Move(OrgFileName, NewOrgFileName);
                        break;
                    }
                }

                // 一時ZIPファイルネームをもとのoffice2007ファイルネームにする。
                File.Move(ZipFileName, OrgFileName);

                //! officeで保存しなおす
                try
                {
                    FileExtension = OrgFileName.Substring(OrgFileName.Length - 5).ToLower();
                    if ((FileExtension == ".xlsx") || (FileExtension == ".xlsm"))
                    {
                        var xls = new Microsoft.Office.Interop.Excel.Application();
                        xls.Visible = false;
                        //開いて保存して終了するだけ
                        var book = xls.Workbooks.Open(OrgFileName);
                        book.Save();
                        book.Close();
                        xls.Quit();
                    }
                    if ((FileExtension == ".docx") || (FileExtension == ".docm"))
                    {
                        var word = new Microsoft.Office.Interop.Word.Application();
                        word.Visible = false;
                        //開いて保存して終了するだけ
                        var doc = word.Documents.Open(OrgFileName);
                        doc.SaveAs2();//  強制上書き
                        doc.Close();
                        word.Quit();
                    }
                    if ((FileExtension == ".pptx") || (FileExtension == ".pptm"))
                    {
                        var powerpoint = new Microsoft.Office.Interop.PowerPoint.Application();
                        //開いて保存して終了するだけ ２番目と３番目の引数は既定値。４番目の引数が非表示で開く。
                        var ppt = powerpoint.Presentations.Open(OrgFileName, Microsoft.Office.Core.MsoTriState.msoFalse,
                            Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoFalse);
                        ppt.Save();
                        ppt.Close();
                        powerpoint.Quit();
                    }
                }
                catch
                {
                }

                Log.Put("作業終了しました。");
                Log.Put("It is finished.");
            }
            catch (Exception ex)
            {
                Log.Put("Error:Main_Process():ex.Message\r\n" + ex.Message);
                Log.Put("Error:CleanUp():ex.StacTrace\r\n" + ex.StackTrace);
            }
            finally
            {
                CleanUp();
            }
        }
    }
}