explorerの/selectに「/」区切りのパスは無効

Windows

ファイルを閲覧・編集するアプリケーションを
作っていると必ず欲しくなるのが「フォルダを開く」機能です。

Windowsであれば、エクスプローラ(explorer.exe)を
呼び出すことでフォルダを開く機能を実装できます。

特に、ファイルを選択した状態で
エクスプローラを起動したい場合は、
以下の書式に従ってコマンドライン引数を渡すことで実現できます。

explorer /select,[開きたいパス]

詳しい引数についての解説はこちらを参考にしてください。

しかし、この[開きたいパス]には
パス区切り文字が「\」でなければならない
という制約があります。

わたくしさんさめは
これに気づかず1時間くらい悩みました。

サンプルコードを交えて備忘録として残しておきます。

スポンサーリンク

/selectの使い方がダメだったコード例

私は当初以下のようなメソッドを作って、
フォルダを開く機能を実装していました。

public static void OpenExplorer(string path)
{
    // 渡されたパスのファイルが存在するなら
    if (System.IO.File.Exists(path))
    {
        // エクスプローラでファイルを選択された状態で開く
        using (Process.Start("explorer", $"/select,{path}"))
        { }
    }
}

しかし、このコードでは
正常に開かないケースがありました。

実際に区切り文字を変えたテストケースを作って確認

次のような、シンプルなWPFアプリを作って確認してみました。

サンプルコードは以下です。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <Button Content="D:\Users\threeshark\a.txt"
                Click="Button_Click"/>
        <Button Content="D:/Users/threeshark/a.txt"
                Click="Button_Click"/>
        <Button Content="D:\Users\threeshark/a.txt"
                Click="Button_Click"/>
    </StackPanel>
</Window>
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (!(sender is Button btn)) { return; }

            var path = btn.Content.ToString();

            OpenExplorer(path);
        }

        public static void OpenExplorer(string path)
        {
            if (System.IO.File.Exists(path))
            {
                using (Process.Start("explorer", $"/select,{path}"))
                { }
            }
        }
    }
}

このアプリケーションを実行して、
実際にボタンを押してみます
(gifアニメです)

どのボタンを押しても
エクスプローラが起動することから、
File.Existsによるチェックは通っていることが分かります。

しかし、実際には
全てのパス区切り文字が「\」である、
一番上のボタンのみ
が、
正常にファイルが選択された状態で
エクスプローラが起動しています。

「/」でも「\」でも/selectが動くようにしたコード例

直感的には、
File.Existsがtrueを返すパスであれば、
普通にエクスプローラも開けて欲しいところです。

というわけで、最初のコードを改造して以下のようにしました。

public static void OpenExplorer(string path)
{
    if (System.IO.File.Exists(path))
    {
        using (Process.Start("explorer", $"/select,{path.Replace('/', '\\')}"))
        { }
    }
}

Replace(‘/’, ‘\\’)を実行して、
パス区切り文字を\に置き換えています。

これで全てのボタンで期待通りの動作をするようになりました。
(再びgifアニメです)

いい感じですね。
Replaceでなくても、Path.GetFullPathでも
期待通りに動きます。

まとめ

まとめです。

  • explorer.exeの/selectオプションを使うと
    ファイル選択した状態での「フォルダを開く」機能が実装可能
  • Windowsはパス区切り文字が「\」でも「/」でも
    認識してくれるがexplorer.exeは「\」のみ受け付ける
  • あらかじめパス区切り文字を
    「\」に統一しておけば期待通りに動作する

最後までお読みいただきありがとうございました。

コメント

タイトルとURLをコピーしました