もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
自分が作ったプログラムのexeと同じ階層に、あらかじめ指定のファイルを配置しておきたい場合に、 下図のように、ソリューションエクスプローラーにファイルを追加して、そのプロパティで「出力ディレクトリにコピー」を「常にコピーする」にしておくと、ビルドしたときに、自動的に、exeと同じ階層に、そのファイルがコピーされてくれる。
この画像では、例としてpngファイルにしたが、 今回は、pngではなく、別のexeを抱え込んで、かつあらかじめ配置はせずに、
- アプリ(exe)にその別のexeファイルを抱え込んでおいて、
- 通常はその別のexeは見えないようにしておいて、
- アプリの任意のタイミングでそのexeファイルを具現化?して、
- そのexeファイルを実行する
ようなことをしたい。
前提
- .NET6
- コンソールアプリ使用
やり方
VisualStudioの「リソース」の機能を使った。
リソースを追加する
まず、プロジェクトを右クリックし、[追加] > [新しい項目]を押す。
出てきた選択画面で、「リソースファイル」を選ぶ。
そうすると、プロジェクトの下に「Resource1.resx」ができる。
ソリューションエクスプローラーの中の「Resource1.resx」をダブルクリックすると、リソースの画面が開く。 ここまでは、以前調べたローカライズのためのreswと同じやり方。
下記の画面が開いたら、アクセス修飾子「public」にする。
次に、「リソースの追加」を押し、「既存のファイルの追加」を押す。
今回は、「別のexe」として、ファイル比較でよく使うDF.exeでやってみるので、出てきた選択画面で、DF.exeを選ぶ。
そうすると、自動で「Resources」フォルダができて、その中に今選択したファイルが入る。
resx画面の方で追加したファイルをクリックして選択すると、下図のようなプロパティが表示される。
Typeが「System.Byte[]」になっている。
Resource1.Designer.cs
を開くと、追加したリソースがこんな感じで定義されている。
byte[]
のリソースになっている。
これで、リソースの追加は終わり。
追加したリソースをコードから呼ぶ
下記のようなコードを書いた。
using System.Diagnostics; namespace BinTorikomi { internal class Program { private static string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); static void Main(string[] args) { // リソースを取ってくる var exe = Resource1.DF; // 出力先のパスを決める var outputExePath = Path.Combine(desktopPath, "DF2.exe"); // リソースを書き出す using (var fs = new FileStream(outputExePath, FileMode.Create)) using (var sw = new BinaryWriter(fs)) { sw.Write(exe); } // 書き出したファイルを実行する Process.Start(outputExePath); Console.ReadLine(); } } }
まず、これで、元のDF.exeを全部バイナリにしたバイト列を取れる。(型はbyte[]
)
var exe = Resource1.DF;
それを取れたら、あとは、DF.exeを復元するには、ただそのバイト列をファイルとして書き出せばよい。 (書き出し方の参考→ファイルに文字列/バイナリデータを読み書きする)
で、書き出したら、Process.Start
でそのファイルを実行する。
これで出来上がり。
参考
ファイルに文字列/バイナリデータを読み書きする