【C#】C#を用いてusbipd-winを使ってWSL2にカメラを接続する方法を簡略化する

こちらはusbipd-win v1.x、v2.xに関するものです。
v4.0に関しては新しい記事を書きましたので良かったらそちらもみて下さい。
touch-sp.hatenablog.com

はじめに

usbipd-winを使ってWSL2にカメラを接続する方法は以下の手順です。

  • 管理者権限でコマンドプロンプトを立ち上げる
  • 「usbipd wsl list」コマンドでカメラのBUSIDを調べる
  • 「usbipd wsl attach --busid (busid)」コマンドで接続する




これらの手順をGUIを使って簡略化しました。
使用した環境は以下の通りです。

Visual Studio Community 2022
C# 
Windowsフォームアプリケーション(.NET Framework)




完成図


カメラを選択してEnterキーを押す又はマウスをダブルクリックします。


not attachedならattachします。
attachedならdetachします。


attachする時にディストリビューション(Ubuntuなど)のパスワードを聞かれたら入力して下さい。


usbipd-winのバージョンが2.0以上だとパスワードは聞かれません。

注意点

あらかじめWSL2を立ち上げておかないと何も起きません。

C#コード

フォームにリストボックスだけを配置しました。

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace AttachUSBGUI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            attach_detach();
            Close();
        }

        private void listBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                attach_detach();
                Close();
            }
        }
        private void attach_detach()
        {
            if (listBox1.SelectedIndex != -1)
            {
                string select_string = listBox1.SelectedItem.ToString();
                string busid = select_string.Split(' ')[0];
                if (select_string.Contains("Not attached"))
                {
                    string command = "usbipd wsl attach --busid " + busid;
                    var proc2 = new Process();
                    proc2.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
                    proc2.StartInfo.Verb = "RunAs";
                    proc2.StartInfo.UseShellExecute = true;
                    proc2.StartInfo.Arguments = @"/c" + command;
                    proc2.Start();
                }
                else
                {
                    string command = "usbipd wsl detach --busid " + busid;
                    var proc2 = new Process();
                    proc2.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
                    proc2.StartInfo.Verb = "RunAs";
                    proc2.StartInfo.UseShellExecute = true;
                    proc2.StartInfo.Arguments = @"/c" + command;
                    proc2.Start();
                }
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            var proc = new Process();
            proc.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.Arguments = @"/c usbipd wsl list";
            proc.Start();

            string txtResult = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();

            string[] _kugiri = { "\r\n" };
            string[] arr = txtResult.Split(_kugiri, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 1; i < arr.Length; i++)
            {
                listBox1.Items.Add(arr[i]);
            }
        }
    }
}

コードの解説

アプリを起動させると同時に「usbipd wsl list」コマンドを実行し、結果をリストボックスに格納します。

private void Form1_Load(object sender, EventArgs e)
{
    var proc = new Process();
    proc.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
    proc.StartInfo.CreateNoWindow = true;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.Arguments = @"/c usbipd wsl list";
    proc.Start();

    string txtResult = proc.StandardOutput.ReadToEnd();
    proc.WaitForExit();

    string[] _kugiri = { "\r\n" };
    string[] arr = txtResult.Split(_kugiri, StringSplitOptions.RemoveEmptyEntries);

    for (int i = 1; i < arr.Length; i++)
    {
        listBox1.Items.Add(arr[i]);
    }
}




リストボックスのうちの一つを選択した後はダブルクリックかEnterキーの入力を受け付けます。

private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
    attach_detach();
    Close();
}
private void listBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Enter)
    {
        attach_detach();
        Close();
    }
}




「usbipd wsl attach --busid (busid)」または「usbipd wsl detach --busid (busid)」を管理者権限で実行します。

private void attach_detach()
{
    if (listBox1.SelectedIndex != -1)
    {
        string select_string = listBox1.SelectedItem.ToString();
        string busid = select_string.Split(' ')[0];
        if (select_string.Contains("Not attached"))
        {
            string command = "usbipd wsl attach --busid " + busid;
            var proc2 = new Process();
            proc2.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
            proc2.StartInfo.Verb = "RunAs";
            proc2.StartInfo.UseShellExecute = true;
            proc2.StartInfo.Arguments = @"/c" + command;
            proc2.Start();
        }
        else
        {
            string command = "usbipd wsl detach --busid " + busid;
            var proc2 = new Process();
            proc2.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
            proc2.StartInfo.Verb = "RunAs";
            proc2.StartInfo.UseShellExecute = true;
            proc2.StartInfo.Arguments = @"/c" + command;
            proc2.Start();
        }
    }
}

文字化け対策

文字化けする場合にはエンコードを指定する必要があります。
真ん中の1行を追加して下さい。

proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.StandardOutputEncoding = Encoding.UTF8;
proc.StartInfo.Arguments = @"/c usbipd wsl list";

自分の環境ではusbpid-winのバージョンを2.0以上にすると文字化けが発生しました。