もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
エクスプローラーでファイル名をダブルクリックしたときと同じように、拡張子に関連付けられたアプリでそのファイルを開くような動作を、C#のコードからしたい。
やり方
Process
クラスと、そのメンバのStartInfo
プロパティを使う。
サンプルコード
using System.Diagnostics; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { var proc = new Process(); //proc.StartInfo.FileName = @"C:\Bz.lnk"; proc.StartInfo.FileName = @"C:\SomeLog.log"; proc.StartInfo.UseShellExecute = true; proc.Start(); } } }
proc.StartInfo.UseShellExecute
をtrueにしていると、エクスプローラーでファイル名をダブルクリックしたときの動きをしてくれる。
上のコードだと、.log
を開くときにメモ帳をつかうようにWindowsで関連づけられていたら、メモ帳でそのlogを開く。
上のコードのコメントアウトした部分のように、なにかのexeへのショートカットもこれで開ける。
(エクスプローラーで見たら、ショートカットの拡張子.lnkは見えないが、コマンドプロンプトのdir
コマンドで見ると見える。)
公式ドキュメントではこう書かれている
ProcessStartInfo.UseShellExecute
をtrueにすると、WindowsのRunダイアログ(win+Rキーで出てくるヤツ)でそのファイルを開いた時と同じ動作をするとある。
個人的に、Runダイアログで開く≒ファイルをダブルクリックするということで、「そのファイルを既定のアプリを使って開く」ということだと思ってるので、掲題の動作はこれでできると思われる。
また、UseShellExecute
をfalseにしているときは、.exe
ファイルのみ実行できるとある。
あんまり理解できてないが、UseShellExecute
のShellというヤツは、「既定の動作」を取り仕切ってる奴、みたいなイメージなのか。
何気にはまったメモ
Processクラスをnewしたときのproc.StartInfo.UseShellExecute
をtrueにしておかないと、上記コードはうまく動かず、下記のようなエラーがでる。
.net Framework4.8では、UseShellExecuteがデフォルトtrueなのだが、.NET6ではデフォルトfalseなので、もしproc.StartInfo.UseShellExecute = true;
の1行を忘れると動かない。(関連MSDocs)
.NetFrameworkの時代のコードを.NET6で使おうと思ったときなどは要注意。
参考
Process クラスの説明
https://docs.microsoft.com/hr-hr/dotnet/api/system.diagnostics.process.-ctor?view=net-6.0
UseShellExecute プロパティの説明。 .netFW4.8ではデフォルトtrue、.netCoreアプリだとデフォルトfalse、とある。
https://atmarkit.itmedia.co.jp/ait/articles/0710/04/news131.html