ファイルやリンクをダブルクリックしたときと同じ動きをC#でさせる

もくじ
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://docs.microsoft.com/hr-hr/dotnet/api/system.diagnostics.processstartinfo.useshellexecute?view=net-6.0

https://atmarkit.itmedia.co.jp/ait/articles/0710/04/news131.html