お手軽リレー接点出力

最近の案件でリレー接点出力を1点だけ制御する必要があったため、「DSD TECH」の「SH-UR01A」というUSB接続のリレー接点出力を使用しました。
仮想COM通信でコマンドを送信するだけで制御が出来るので、とても簡単です。

普段はコンテックなどのI/Oデバイスを使用しますが、1,2点程度の場合は「SH-UR01A」のほうがお手軽そうです。

DataGridViewの列幅オートサイズモードによって描画速度が遅い場合の対策

DataGridViewの列幅オートサイズモード(AutoSizeColumnsMode)がAllCellsなどのようにセルの内容によってオートサイズするモードの場合、セルのValueの設定回数が多いと描画が遅くなります。

これを改善するために、列幅オートサイズモードを一旦Noneに変更する拡張メソッドを作成しました。
これにより劇的に速度改善しました。

/// <summary>処理実行中に列幅のオートサイズを停止します。セルのValueの設定回数が多い場合、オートサイズ処理が遅いため、一旦オートサイズを停止することで高速化を行います。</summary>
public static void SuspendColumnAutoSize(this DataGridView dgv, System.Action action) {
    //注意:AutoSizeRowsModeは対象外。Noneに変更しただけで遅いため
 
    //finallyで行う処理
    System.Action finallyAction = () => { };
    //AutoSizeColumnsModeがNoneなどでない場合はNoneに変更する
    if (dgv.AutoSizeColumnsMode.EqualsAny(DataGridViewAutoSizeColumnsMode.None, DataGridViewAutoSizeColumnsMode.Fill).Not()) {
        var mode = dgv.AutoSizeColumnsMode;
        finallyAction += () => dgv.AutoSizeColumnsMode = mode;
        dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    }
    //列のAutoSizeColumnsModeがNoneなどでない場合はNoneに変更する
    foreach (var col in dgv.Columns.ToList()) {
        if (col.AutoSizeMode.EqualsAny(DataGridViewAutoSizeColumnMode.None, DataGridViewAutoSizeColumnMode.NotSet, DataGridViewAutoSizeColumnMode.Fill).Not()) {
            var mode = col.AutoSizeMode;
            finallyAction += () => col.AutoSizeMode = mode;
            col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
        }
    }
    //処理実行
    try {
        action();
    } finally {
        finallyAction();
    }
}

UAC(ユーザアカウント制御)などの有効/無効を取得

UAC(ユーザアカウント制御)や、「UACによる管理者昇格時の同意プロンプト表示」の有効/無効によって処理を変えたい場合があったので取得方法を調べました。

結果、レジストリを調べれば良いことが分かりました。簡単ですね。

以下のプロパティを実装してみました。

/// <summary>UAC(ユーザアカウント制御)が有効か</summary>
public static bool? IsUacEnabled {
    get {
        try {
            var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
            if (key == null) return null;
            var value = key.GetValue("EnableLUA");
            if (value == null) return null;
            return value.Equals(1);
        } catch {
            return null;
        }
    }
}
 
/// <summary>UACによる管理者昇格時の同意プロンプト表示が有効か</summary>
public static bool? IsAdminConsentPromptEnabled {
    get {
        try {
            var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
            if (key == null) return null;
            var value = key.GetValue("ConsentPromptBehaviorAdmin");
            if (value == null) return null;
            return value.Equals(0).Not();
        } catch {
            return null;
        }
    }
}

DisposeActionクラス

C#で後処理を行いたい場合にfinallyブロックに記載することが良くあります。
途中でreturnで抜けても、例外発生しても必ずfinallyブロックが実行されるので安心です。

たとえば以下のように記載します。


try {
    //ここで処理Aを実行
    counter++;
    //ここで処理Bを実行
} finally {
    counter--;
}

処理Aのあとにcounterを+1し、処理Bを実行後にcounterを-1するコードです。
これだと処理Aでreturnや例外発生するとcounterが-1されて正しく動作しないです。
このコードだと、処理Aだけtryブロックの外側で実行するだけで良いですが、そうもいかない場合も多々あったり。

というわけで、DisposeActionクラスを作ってみました。
いたってシンプルなクラスで、コンストラクタで与えたラムダ式をDisposeメソッド内で実行するだけです。
以下のように使用します。


//ここで処理Aを実行
counter++;
using var _ = new DisposeAction(() => counter--);
//ここで処理Bを実行

先程の問題が解決し、行数が減り、コードも見やすくなったのではなかろうかと思います。

DisposeActionのインスタンスは不要なので、本当は以下のように書けると良いのですが。現状のC#では出来ないです。


using new DisposeAction(() => counter--);

社内ライブラリをGit+VisualStudio2022に移行

弊社で開発しているソースコードのバージョン管理はVisualSourceSafeを惰性で使い続けいました。
数年前からは新規プロジェクトはGitを使用していますが、古いソフトはVisualSourceSafeのままです。

社内ライブラリもVisualSourceSafeだったのですが、VisualStudio2022がVisualSourceSafeに対応していないため、この週末にGit+VisualStudio2022に移行しました。
予想していたより問題も起こらず、すんなりと移行完了。単体テストも全てクリア。

こんなに簡単なら、もっと早くに移行しておけばよかった。

ほかのプロジェクトも徐々にVisualSourceSafeからGit+VisualStudio2022に移行を進めていきます。
VisualStudio2022でないと「GitHub Copilot」も使用できないですし。

「GitHub Copilot」で効率的なコーディング

「GitHub Copilot」とは、コーディング中にAIがコード例を提示してくれる、今後のソフトウェア開発を大きく変える革新的なツールです。
弊社でも最近このツールを使用しております。
VisualStudio標準のAI補完機能「InteliCode」よりも柔軟にコード例を提示してくれます。

自分が書いたコードを学習し、適切なコード例を提案してくれます。
開発者は、Copilotが提供するコード例を参考にしながら、より迅速かつ正確なコードを作成することができます。
これにより、開発の生産性が向上し、バグのリスクを低減することができます。

Copilotはまだ新しいツールであり、正しくないコードを提案することもあります。
しかし、Copilotの精度は徐々に向上していくことが期待できますので、今後が楽しみです。

アプリからWindows共有フォルダを作成する方法

先日、ある案件でアプリからWindows共有を作成する必要がありました。

調査しました結果、コマンドラインで以下の2つを実行すれば良いことがわかりました。


net share <共有名>=<共有するフォルダのフルパス> /grant:everyone,full
icacls <共有するフォルダのフルパス> /grant everyone:(OI)(CI)F

C#の場合、これをProcessクラスを使用して実行すれば良いだけです。
案外簡単に出来てしまいます。

ただし、管理者権限が必要なので、それだけ注意です。

ChatGPTを使用して自作ソースコードの説明やサンプルコードを作成

今回は、ChatGPTをソフト開発に活用できないかと考えてみました。
例えば、ソースコード一式を与えて、クラスやメソッドの使い方のサンプルを作成してもらうことはできないでしょうか。
また、単体テストも自動作成してもらうことはできないでしょうか。

ChatGPTに以下の質問をしてみました。


以下のC#コードについて、簡単な説明と、サンプルコードを作成してください。

public static Color Blend(this Color color, Color blendColor, double ratio) {
    if (ratio.IsBetween(0.0, 1.0).Not()) throw new FormatException();
    int a, r, g, b;
    a = color.A + ((blendColor.A - color.A).ToDbl() * ratio).ToInt();
    r = color.R + ((blendColor.R - color.R).ToDbl() * ratio).ToInt();
    g = color.G + ((blendColor.G - color.G).ToDbl() * ratio).ToInt();
    b = color.B + ((blendColor.B - color.B).ToDbl() * ratio).ToInt();

    return Color.FromArgb(a, r, g, b);
}

これに対して、以下の回答になりました。


・拡張メソッドとは、既存のクラスに新しいメソッドを追加する機能です。この場合、ColorクラスにBlendメソッドを追加しています。
・Blendメソッドは、引数として、混ぜる色(blendColor)と混ぜる比率(ratio)を受け取ります。
・ratioは0.0から1.0の範囲でなければなりません。そうでない場合は、FormatExceptionをスローします。
・混ぜる色と元の色の各成分(A, R, G, B)について、比率に応じた加重平均を計算します。例えば、R成分の場合は、color.R + ((blendColor.R - color.R).ToDbl() * ratio).ToInt()となります。
・計算した各成分の値を使って、新しいColorオブジェクトを作成して返します。

static void Main(string[] args)
{
    // 色を作成する
    Color red = Color.FromArgb(255, 0, 0);
    Color green = Color.FromArgb(0, 255, 0);
    Color blue = Color.FromArgb(0, 0, 255);

    // 色を混ぜる
    Color purple = red.Blend(blue, 0.5); // 紫色
    Color yellow = red.Blend(green, 0.5); // 黄色
    Color cyan = green.Blend(blue, 0.5); // シアン色

    // 色を表示する
    Console.WriteLine("Red: {0}", red);
    Console.WriteLine("Green: {0}", green);
    Console.WriteLine("Blue: {0}", blue);
    Console.WriteLine("Purple: {0}", purple);
    Console.WriteLine("Yellow: {0}", yellow);
    Console.WriteLine("Cyan: {0}", cyan);
}

完全にメソッドの内容を理解して説明とサンプルコードを作成しています。すばらしいです。
今回はとても単純なメソッドで試しましたので簡単でしたが、実際の業務のコードはこんなに単純ではないのでこんなにうまくは行きません。
しかし、これらのことが実現できれば、開発工数の削減につながりますし、品質も向上する可能性があります。

ChatGPTはまだ研究段階の技術であり、実際にソフト開発に適用するにはさまざまな課題があります。
例えば、ソースコードの構造や文法を正しく理解できるか、サンプルやテストが正確かつ有用か、セキュリティや著作権の問題はないかなどです。
これらの問題を解決するためには、ChatGPTの性能や限界を詳しく調査する必要があります。

弊社では、ChatGPTをソフト開発に応用するための研究を進めております。今後も最新の情報をお届けしていきます。

ChatGPTに自作ソースコードを与えて色々試す

今回もChatGPTの話です。

自分が作成したソースコードをChatGPTに与えてどのようなことが出来るか試しました。
本家ChatGPTとBingChatで試しています。

(1)XMLコメントを作成

質問内容

以下のC#コードのXMLコメントを日本語で作成して

public static Color Blend(this Color color, Color blendColor, double ratio) {
    if (ratio.IsBetween(0.0, 1.0).Not()) throw new FormatException();
    int a, r, g, b;
    a = color.A + ((blendColor.A - color.A).ToDbl() * ratio).ToInt();
    r = color.R + ((blendColor.R - color.R).ToDbl() * ratio).ToInt();
    g = color.G + ((blendColor.G - color.G).ToDbl() * ratio).ToInt();
    b = color.B + ((blendColor.B - color.B).ToDbl() * ratio).ToInt();
    return Color.FromArgb(a, r, g, b);
}

結果 ChatGPT

結果 BingChat

ちゃんとコードを理解してXMLコメントを作成できています。
すばらしいです。

(2)サンプルコードを作成
質問内容

以下のC#のBlendメソッドの使用例を作成して

public static Color Blend(this Color color, Color blendColor, double ratio) {
    if (ratio.IsBetween(0.0, 1.0).Not()) throw new FormatException();
    int a, r, g, b;
    a = color.A + ((blendColor.A - color.A).ToDbl() * ratio).ToInt();
    r = color.R + ((blendColor.R - color.R).ToDbl() * ratio).ToInt();
    g = color.G + ((blendColor.G - color.G).ToDbl() * ratio).ToInt();
    b = color.B + ((blendColor.B - color.B).ToDbl() * ratio).ToInt();
    return Color.FromArgb(a, r, g, b);
}

結果 ChatGPT

結果 BingChat

これも完璧です。

—–

このようなことが出来るのであれば、自力でドキュメントやサンプルコードなどを用意しなくても良くなるので、今よりも開発に専念できます。
とりあえずは、ChatGPTを使用して自動でXMLコメントを挿入するVisualStudioプラグインを作成したいですね。

bingのチャット検索(ChatGPT)

bingのチャット検索(ChatGPT)が流行っているので試してみました。

■C#でSQLiteを使用するコードを依頼
コードだけではなく、必要なライブラリやコネクション文字列の例も教えてくれました。

■上記の質問のあとに、他のコード例を依頼
ちゃんと続きの会話と理解してSQLiteのコード例を教えてくれました。

■上記コードをVB.netに変換
コード変換を行うWEBサイトを使用して変換してくれました。

■結果
今回のチャット内容は簡単なものなので実際にはどれほど役に立つかはまだわかりませんが、ちょっとした調べ物などをお願いして開発の労力を減らせそうに思います。
良い開発パートナーになりそうです。