【C#】7zip(Sfx)で自己解凍exeを作成する

2018年2月8日C#,開発

おはようございます。

予告通り、今回は「7zip」を利用して自己解凍形式の実行ファイルを作成してみます。

プログラムは前回のものを流用します。

【C#】7zip を使って圧縮ファイルを展開する

スポンサーリンク

自己解凍形式について

7zip形式の圧縮ファイルと、設定ファイルをひとまとめにして実行ファイルとし、
ファイルの展開後に任意のプログラムを実行することができます。

主にインストーラーなんかに使われているようです。詳しくは調べてみてください。

画面の修正

自己解凍exe出力ボタンの追加

自己解凍exe出力ボタンを追加します。

SFXのDLLをダウンロードして配置

https://ja.osdn.net/projects/sevenzip/downloads/64455/7z920_extra.7z/

dllの追加

パッケージエクスプローラーで、ダウンロードした「7zS.sfx」をプロジェクトに追加します。

※参照の追加ではありません

設定ファイルの作成

config.txt

;!@Install@!UTF-8!
Title="VisualStudioSolution実行"
BeginPrompt="自己解凍exeを実行しますか?"
Directory=""
ExecuteFile=".\\archive\\WpfApp1.sln"
RunProgram=""
;!@InstallEnd@!

作成したファイルは、実行ファイルから参照できる場所においてください。

プログラムの修正

新規メソッドの追加

自己解凍exeを出力する処理を追加します。

            /// <summary>
            /// 自己解凍exeを出力します.
            /// </summary>
            /// <param name="filePath"></param>
            /// <returns></returns>
            private int OutputSelfExtractFile(string filePath, string outputDir)
            {
                // 指定したディレクトリにフォルダ構成を保持した形で出力
                string strCommandLine = "copy /b 7zS.sfx + " + "config.txt + " + filePath + " " + outputDir + "\\SelfExtract.exe";
    
                // コマンドプロンプトで実行
                Process p = new Process();
                //ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定
                p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
                //出力を読み取れるようにする
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardInput = false;
                //ウィンドウを表示しないようにする
                p.StartInfo.CreateNoWindow = true;
                //コマンドラインを指定("/c"は実行後閉じるために必要)
                p.StartInfo.Arguments = @"/c " + strCommandLine;
    
                //起動
                p.Start();
    
                //出力を読み取る
                string results = p.StandardOutput.ReadToEnd();
    
                //プロセス終了まで待機する
                //WaitForExitはReadToEndの後である必要がある
                //(親プロセス、子プロセスでブロック防止のため)
                p.WaitForExit();
                p.Close();
    
                return 0;
            }

新規イベントの追加

追加したボタンのクリック時の処理を追加します。

            /// <summary>
            /// 自己解凍exe出力ボタンクリックイベント.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSfx_Click(object sender, EventArgs e)
            {
                int count = 0;
    
                // 選択されたファイルを解凍
                var selectedItems = listView1.SelectedItems;
                foreach (ListViewItem item in selectedItems)
                {
                    // ファイルの情報を取得
                    FileInfo fi = new FileInfo(item.Name);
                    FileVersionInfo vi = FileVersionInfo.GetVersionInfo(item.Name);
    
                    // shell32で取得
                    string type = "";
                    SHFILEINFO shinfo = new SHFILEINFO();
                    IntPtr hSuccess = SHGetFileInfo(item.Name, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
                    if (hSuccess != IntPtr.Zero)
                    {
                        type = shinfo.szTypeName;
                    }
    
                    // 圧縮ファイルの判定
                    // shll32、FileInfo、FileVersionInfoなどから判定できる
                    // if (vi.FileDescription.IndexOf("7Z") > -1)
                    // if (fi.Attributes == FileAttributes.Archive)
                    // ファイル種別で判定
                    if (type.IndexOf("7Z") > -1)
                    {
                        MessageBox.Show(item.Name + "の自己解凍exeを作成します。", "自己解凍exe出力処理");
                        int ret = OutputSelfExtractFile(item.Name, fi.DirectoryName);
                        if (ret != 0)
                        {
                            MessageBox.Show(item.Name + "の自己解凍exe出力に失敗しました。", "自己解凍exe出力処理");
                        }
                        count++;
                    }
                }
    
                // 展開を実行したかどうかでメッセージを変更
                if (count == 0)
                {
                    MessageBox.Show("自己解凍する対象が存在しません。", "自己解凍exe出力処理");
                }
                else
                {
                    MessageBox.Show("自己解凍exeの出力が完了しました。", "自己解凍exe出力処理");
                }
            }

起動してみる

起動、「7zip」形式のファイルを選択し、「自己解凍exe出力」ボタンをクリックします。

確認メッセージ
完了メッセージの表示
出力されたファイル

圧縮ファイルと同じディレクトリに「SelfExtraxt.exe」が出力されます。

自己解凍exeの実行

出力された「SelfExtraxt.exe」を実行してみます。

プログレスの表示

プログレスも表示されます。

まとめ

色々使いどころはあるかと思います。

7-zip32.dll には内蔵されている自己解凍処理もあり、そちらは設定ファイルを画面から設定できたりもするので気になる方は調べてみてください。

ではでは。

 

スポンサーリンク


関連するコンテンツ

2018年2月8日C#,開発C#,WindowsForms,サンプルプログラム

Posted by doradora