としおの読書生活

田舎に住む社会人の読書記録を綴ります。 主に小説や新書の内容紹介と感想を書きます。 読書の他にもワイン、紅茶、パソコン関係などの趣味を詰め込んだブログにしたいです。

タグ:C#

3753817_s

C#からDOSコマンドなどの別プロセスを実行する方法が分からず、方法を調べたので忘備録として記録します。


C#でコマンドを実行する


結論からになりますが以下のコードでDOSコマンドを実行することができます。

using System;
using System.Diagnostics;

class ExecuteCom
{
    public static void Main()
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe""/k dir");
        Process.Start(processStartInfo);
    }
}

コードの簡単な説明になりますが、ProcessStartInfoの第一引数にコマンド、第二引数にコマンドの引数を与えてあげて、Process.Start()をコールすることでコマンドを実行することができます。

今回はdirコマンドを実行してみた例になります。



コマンドが終了するまで待つ方法


先ほどのコードではコマンドを終了することを待たずにプログラムが進んでしまいます。

そこで、同期的にコマンドを実行させたい場合は、process.WaitForExit()を使いましょう。

先ほどのコードを改造して同期的にコマンドを実行しているサンプルコードは以下の通りです。(クラス名などは変わっていないため省略しています。)

ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe""/k dir");
Process process = Process.Start(processStartInfo);

// プロセスが終了するまで待機
process.WaitForExit();
// プロセスを終了させる
process.Close();

process.WaitForExit()の後に書いているprocessStartInfo.Close()はプロセスを終了させるためのコマンドです。

これをコールしないとゾンビプロセスが残ってしまうのでコールし忘れには気を付ける必要があります。



コマンドプロンプトを非表示にする


コマンドを呼びだすたびにコマンドプロンプトの窓が起動するのが嫌な場合、ProcessStartInfoクラスのプロパティを変更することで非表示にすることができます。

変更するプロパティは以下の二つです。

  • CreateNoWindow
  • UseShellExecute

先ほどのコードを改造してコマンドプロンプトが表示されないようにしていきます。

ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe""/k dir");
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
Process process = Process.Start(processStartInfo);

これでコマンドプロンプトのウィンドウが開かなくなりました。



まとめ


C#のプログラムからコマンドを実行したい場合、ProcessクラスProcessStartInfoクラスを使えばよいことが分かりました。

出力結果などをC#側で取得する方法などもあり色々できそうなので気になる方は調べてください。







3753817_s

本記事ではVisual Studioを使ってWPFの開発環境を構築する方法を紹介していきます。



Visual Studioのダウンロード


最初にVisual Studioをインストールします。

すでにインストール済みの人は読み飛ばしてもらっても大丈夫です。

Visual Studioは以下のリンクからダウンロードできます。



コミュニティ版は学生、個人利用者、オープンソース貢献者は無償で使用できるみたいです。マイクロソフトは心が広いですね。

以下の画面の赤で囲まれている部分をクリックすることでダウンロードすることができます。

キャプチャ

ダウンロードが完了したらインストーラを起動してください。

インストーラを起動したら続行をクリックします。

キャプチャ

次に.NET デスクトップ環境にチェックを入れてインストールボタンをクリックしてください。

そうするとインストールが始まります。

キャプチャ

キャプチャ

インストールが完了すると一度PCの再起動を求められるので再起動してください。

キャプチャ

再起動がしたらデスクトップからメニューを開いてVの項目にあるVisual Studio2019を起動してください。

キャプチャ

起動するとマイクロソフトアカウントでのサインインが求められるのでサインインしてください。

アカウントがない場合は、アカウントを作成してください。

キャプチャ

サインインすると配色の設定が聞かれるので好みの色に設定してVisual Studioの開始をクリックします。

キャプチャ

以下の画面が起動したらVisual Studioが起動できたためインストールは完了です。

キャプチャ



WPFプロジェクトを作成する


Visual StudioがインストールできたろことでWPFのプロジェクトを作成していきます。

以下の画面から新しいプロジェクトの作成をクリックしてください。

キャプチャ

検索ボックスにWPFと入力して、以下の画像の赤枠で囲っているWPFアプリケーションを選択して次へをクリックしてください。

Visual Basic用などと間違えないように注意してください。

キャプチャ

プロジェクト名や場所は適当なものを入力して次へをクリックしてください。今回はデフォルトのままで進みます。

キャプチャ

ターゲットフレームワークもなんでもいいのですが今回は現時点で最新の5.0を使用します。

ターゲットフレームワークが選択できたら作成をクリックしてください。

キャプチャ

以下の画面が表示されたらWPFプロジェクトの作成は完了です。

キャプチャ





Hello Worldアプリを作成する


プロジェクトが作成できたら、ボタンを押したら画面にHello Worldと表示する単純なアプリを作成します。

ここではあくまでアプリを実行することを目的とするのでコードの意味などは説明しません。

MainWindow.xamlのコードを以下に示します。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <StackPanel>
            <Label x:Name="Label1" Margin="10" Height="40" Width="200" HorizontalContentAlignment="Center"/>
            <Button Content="ボタン" Height="40" Width="80" Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.csのコードを以下に示します。

using System.Windows;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object senderRoutedEventArgs e)
        {
            Label1.Content = "Hello World!!";
        }
    }
}

このコードを張り付けて、実行ボタンを押すとアプリが起動します。

キャプチャ

キャプチャ

ボタンをクリックすると画面中央にHello Worldと表示されます。

キャプチャ



まとめ


Visual StudioをインストールしてWPFでHello Worldアプリを作成するまで1時間ほどでできました。

関係ないですがいつの間にかホットリロード機能が付いたんですね!








3753817_s

本記事では、C#で数値を文字列に変換する方法と文字列を数値に変換する方法を紹介します。



数値を文字列に変換する


数値を文字列に変換したい場合、ToStringメソッドを使用しましょう。

例えばint型の値をstring型に変化する場合以下のように書くことができます。

int nNum = 5;
string strTemp = nNum.ToString();

また、ToStriongはint型だけではなく、uint、doubleなど様々な方に使うことができます。

double型の値をsttring型に変換する例を以下に示します。

double dNum = 3.14;
strTemp = dNum.ToString();




文字列を数値に変換する



Parseメソッドを使った方法


最初に文字列を数値に変換する方法としてParseメソッドを使った方法を紹介します。

文字列をint型の値に変換した場合、以下のように書くことができます。

string strNum = "10";
int nNum = int.Parse(strNum);

Parseメソッドも先ほど紹介したToStringメソッドのようにuin型やdouble型など様々な型への変換に使うことができます。

string strNum = "3.14";
double dNum = double.Parse(strNum);

Parseメソッドの欠点として数字以外の文字列を引数として与えると例外が発生します。

例えば以下のような場合例外が発生します。

string strNum = "aaa";
int nNum = int.Parse(strNum);


この例外を防ぐ手段としてTryParseメソッドを使いましょう。

TryParseメソッドは第1引数に変換したい文字列、第2引数に文字列を変換した値を格納する変数を渡します。

また戻り値は成功した場合はTrue、関数内で例外が発生した場合はFalseが返ってきます。

TryParseメソッドで文字列をint型に変換した例を以下に示します。

int nNum = 0;
string strNum = "10";
bool bRet = int.TryParse(strNumout nNum);

以下のように数字以外の文字列を与えても先ほどのParseメソッドのように例外は発生しません。

int nNum = 0;
string strNum = "aaa";
bool bRet = int.TryParse(strNumout nNum);






Convertクラスを使った方法


文字列を数値に変換する方法としてParseメソッドの他にConvertクラスを使った方法があります。

Convertクラスを使って文字列をint型に変換するコードは以下の通りです。

string strNum = "10";
int nNum = Convert.ToInt32(strNum);


ちなみにConvertクラスに数値以外の文字列を与えた場合、Parseメソッドと同じように例外が発生します。

string strNum = "aaa";
int nNum = Convert.ToInt32(strNum);

これだけ見るとConvertクラスはParseメソッドと変わらないように見えますが、Convertクラスは引数としてnullが与えられても例外が発生しないとう特徴があります。

以下のように引数にnullを与えた場合、0が返ってきます。

string strNum = null;
int nNum = Convert.ToInt32(strNum);




まとめ


数値を文字列に変換したい場合、ToStringメソッドを使いましょう。

文字列を数値に変換する方法はParseメソッドTryParseメソッドConvertクラスの三つの方法がありました。

数値以外の文字列が与えられる可能性がある場合は、例外に強いTryParseメソッドを使いましょう。

それ以外の場合は、nullが引数として入力される可能性があるかどうかでParseメソッドとConvertクラスを使い分けましょう。






3753817_s

C#でParallel.ForEachを使ってlistオブジェクトにaddでパラメータを追加してみたところ自分が想定していた動作が行われませんでした。

C#ってすごく便利だから、Parallel.ForEachを使ったら排他制御ぐらい勝手にしてくれるだろうとか思い込んでいたのですがそうではないみたいです。

なので今回、C#で排他制御を行う方法を調べたので忘備録として記録しておきます。



排他制御の行い方


C#も他の言語と同じようにマルチスレッドで動作させる場合には、排他制御の実装が必要になります。

排他制御を行わなかった場合、listに全ての変数が追加されないなど実際の処理内容が自分が想定しているものと違う風になってしまいます。

C#で排他制御を行うためにはlock構文を使えばいいみたいです。

lock構文の使い方ですが、以下のように使います。

lock(変数名)
        {
            処理1
            処理2
            …
        }

スレッドの実装も楽々なC#ですが、排他制御の実装まですぐにできるなんてさすがですね。



Parallel.ForEachでlistにaddするサンプルコード


Parallel.ForEachと先ほど紹介したlock構文を使って、listにデータをaddしていくsampleコードを以下に示します。

ちなみに今回のサンプルコードはスレッドなしで作成されたリストのようそを並列処理で別のリストに追加するというコードなのであまり意味がないコードですがサンプルなので気にしないでください。

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class LockSample
{
    private static object lockTest = new object(); //ロック処理用オブジェクト
    public static void Main()
    {
        
        List<intnumList = new List<int>();
        List<intparralellList = new List<int>();

        for(int i=0i<100000; ++i){
            numList.Add(i);
        }

        // lock処理を使って追加する。
        Parallel.ForEach(numListnum =>
        {
            lock(lockTest)
            {
                parralellList.Add(num);
            }
        });

        Console.WriteLine("numList Count = " + numList.Count);
        Console.WriteLine("parralellList Count = " + parralellList.Count);
    }
}







まとめ


Parallel.ForEachでListオブジェクトを操作するには排他制御が必要でした。

C#では排他制御はlock構文で簡単に実装できるので、意図しない動作を起こさないために並列処理を行うときは排他制御を忘れないようにしましょう。







3753817_s

C#で開発していてTEMP環境変数を取得する方法を調べたのでまとめます。



GetEnvironmentVariableを使う


C#では環境変数を取得する関数として、GetEnviromentVariableが用意されています。

この関数を使ってTEMP環境変数を取得するサンプルコードは以下の通りです。

string strTemp = Environment.GetEnvironmentVariable("TEMP");

この方法の欠点として一部の環境で、例外が発生する可能性があることです。

私もVisual Studio2017の.NET Framework 4.5.2の環境で上記の方法でTEMP環境変数を取得しようとしたろころ例外が発生しました。

コマンドプロンプトなどでTEMP環境変数が存在するか確認したところ存在していたので、環境変数の設定とかが悪いというわけではないようです。

そこで例外が発生しない方法を調べたところ以下の方法がいいことが分かりました。



GetTempPathを使う


GetEnviromentVariableで例外が発生した環境でGetTempPathを使用したところTEMP環境変数を取得することができました。

この関数を使ってTEMP環境変数を取得するサンプルコードは以下の通りです。

string strTemp = Path.GetTempPath();

調べていたら多くの方がTEMP環境変数を取得するためにこちらの関数を使った方が良いという意見をかかれていたため、今後使う機会があればこちらを使用していきたいと思いました。



まとめ


C#でTEMP環境変数を取得する方法は二種類ありましたが、GetTempPathを使用するのがいいみたいです。




↑このページのトップヘ