としおの読書生活

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

カテゴリ: 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

本記事では、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を使用するのがいいみたいです。




3753817_s

今までVisual Studioをインストールしている環境でしか、C#をコンパイルしたことがなかったのですが、Visual Studioがない環境でもC#をコンパイルしたいと思い方法を調べました。

今回は、VSCodeを使ってコンパイルしていきます。



.NET Frameworkのパスと通す


C#をコンパイルするためには.NET Frameworkが必要です。

Windowsではデフォルトで.は.NET Frameworkはデフォルトでインストールされています。

C:\Windows\Microsoft.NETにアクセスするとFrameworkとFramework64がありそれぞれ32bit用と64bitようになります。

キャプチャ

今回は64bit用の「v4.0.30319」のパスを通していきます。

パスはコントロールパネル>システムとセキュリティ>システム>システムの詳細設定>環境変数 から通すことができます。

環境変数には「C:\Windows\Microsoft.NET\Framework64\v4.0.30319」を追加してください。



C#のプログラムをコンパイルする


パスが通せたところでC#のプログラムをVSCodeでコンパイルしていきましょう。

まずはVSCodeを起動して、コードが読みやすくなるように拡張機能をインストールしていきます。

拡張機能の検索ボックスで「C#」と入力して検索して、一番上に現れる拡張機能をインストールします。

キャプチャ

これでC#のコードが読みやすくなりました。

今回は、以下のサンプルコードをコンパイルします。

using System;

class Hello
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
    }
}

ファイル名は何でもいいのですが、今回は「Hello.cs」としておきます。

コンパイルしたいC#のコードができたら、コードが置いているディレクトリにいどうしてターミナルに以下のコマンドを入力してください。

csc .\Hello.cs

これだけでコンパイルは完了です。

コンパイルが終わると実行ファイルができるはずなので実行してみるとターミナルに「Hello World」と表示されるはずです。



まとめ


C#をコンパイルするのは難しいと思っていたのですが、やってみたらむちゃくちゃ簡単でした。

本記事で分からないことがあればコメントをください。





↑このページのトップヘ