1985年からCを勉強し始め、ウィンドウズ3.x時代からTurbo C++でC++も学習しましたが、68歳になった今でも新しいこと(C#)を学ぶのはまた楽しからずや、です。しかし、...C#はC++に似ていて非なるものなので下手に持っているC++の知識が邪魔することも確かで、違いがあるたびに確認するのですが、C#は初心者なので、いろいろなサイトで確認しても必ずしも同じ答えではなく、且つC#がVer 1.0からVer 11に変化していることも問題を複雑に

しています。

 

例えば、BCCSkeltonやECCSkelton(つまりC++)では、(プロジェクト名).hでクラスとメンバー変数の定義を行い、メンバー関数はコードが長いのでプロトタイプ宣言だけ行って、(プロジェクト名)Proc.hで「(クラス名)::(関数){}」で実装(具体定義)していました。

 

【(プロジェクト名).h】

class foo : public ancester

{

    public:    //アクセス修飾子にまとめて書けた

    int m_bar;

    bool zot(char*);

};

 

 

【(プロジェクト名)Proc.h】

bool foo::zot(charr* str) {

 

    ...

    return TRUE;

}

 

しかし、C#では名前空間に厳格で、その中でクラス定義を完結("partial"を使っても)しなければならないので、クラス定義から外出しして後で"::"をつかって定義するようなことはできないよう(まだ断言できないのですが...おそらく)です。また細かいことですが、クラス定義のアクセス修飾子の使い方とか、最後の':'やクラス定義最後の';'がいらないとか、ビミョーな点で異なることがあります。

 

まぁ、ウィンドウプログラムはてこずりそうだけど、コンソールではそんなに変わらないよね、と思っていたら、本日「猫でも」の例題を4つまとめたサンプルを作っていて面白いエラーに遭遇しました。

 

    int i;

    for(int i = 0; ... ; ...) {

    }

というプログラムで、「ローカルの変数 'i' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'i' の意味が変更されるのを避けるためです。」というエラーが出ました。

C++であれば「ブロック内は別世界」なので、

{

    int i;

    {

        int i;

        {

            int i;

        }

    }

}

これらのi'sは皆別物と認識されますが、C#ではそうではないようです。(単なる警告ではなく、「別の意味を持つ 'i' の意味が変更されるのを避ける」ということで、同一を認識されるのでしょう。)

 

「似て非なるもの」(注)、まだまだ当分楽しめそうです。

注:ウェブで見ていると「C#でWin32 APIを呼び出す」という記事が結構多いです。高級言語となったC#がより低級なAPIを使うために自らを貶めているように感じる一方、C++はアッセンブラーみたいに危ないことでもなんでもできるんだなぁ、と感じられます。

 

色々とノリの悪いMSCompAssプログラミング、今回は不注意からまたバグを出しました。

 

1.まず当初(Version 1.0)のコードでは、ソースコードを読み込み、それをMSCompAssを使ってcsc.exeでコンパイルしますが、出力先を指定していなかったのでカレントディレクトリーであるMSCompAss.exeのあるフォールダーに出力してしまいます。

 

2.それに気が付いて、慌ててcsc.exeの"/out:(ファイル名)"オプションを使い、ソースファイル名(フルパス+ファイル名.csまたはvb)の拡張子を".exe"に交換して出力する仕様にしましたが、今度はその長々とした"/\out:"オプションが気に入らなくなり、

 

3.「現在仕掛っているソースファイルのあるフォールダーへ移動して、(他のソースコードが読み込まれるまでは)そこにいてexeファイルも出力する仕様にしました。

 

4.その際、プログラムに与えられる引数を切り出すと共にフルパスファイル名も分解するCARGクラスを使ったのは良いですが、あまり考えずに次のようにコーディングしました。

 

    //フルパスファイル名g_FileNameからファイルパスをg_TargetPathに記録
    Arg = g_FileName.ToChar();    //CSTRクラスインスタンスのg_FileNameにはソースのフルパスファイル名が入っている
    g_TargetPath = Arg.Path();     //Path()はchar*でファイルパスのみを返す
 

5.そして今朝、C#サンプルプログラムのソースコードが入っている「C#」フォールダーを「C# Programing」に変更した途端、そのフォールダーの直上のフォールダーに出力されるようになりました。(注)

注:勘がよい方はもうお分かりと思いますが、「(パス)\C#\(プログラム名)」を分解して最後の'\'以降を外すPath()を使って「(パス)\C#」を取得していましたが、CARGのArgに「(パス)\C# Programing\(プログラム名)」を渡すと、[C#」と「Programing」の間の空白文字で別の引数と認識され、Path()関数には「(パス)\C#」までが渡されるため、パス名は最後の'\'以降が外されて「(パス)」になってしまいます。

 

6.なら、フルパスファイル名を分解する場合にはOSが行うように「""」で囲めばよいじゃない、というのが正解ですが、実はCARGクラスには元々そういう使い方をすることを想定して、

char* GetLongName(char*);

引数にスペースがあればダブルコーテーションをつける

ファイルパス、ネームの文字列

char* GetQuatoOff(char*);

引数にダブルコーテーションがあればこれをとる

ファイルパス、ネームの文字列

という関数を予め用意していました。しかし、それも「20年前」で今は耄碌した爺さんはすっかり忘れていた、という次第です。

 

従って正解は、

 

    //フルパスファイル名g_FileNameからファイルパスをg_TargetPathに記録
    Arg = Arg.GetLongName(g_FileName.ToChar());
    g_TargetPath = Arg.Path();
 

とすることでした。(なお、当然のことですが、本日修正パッケージをアップしましたので、早晩修正版がアップされるでしょう。)

 

最終形となったMSCompAssを使ってC#の基本的な文法を学び始めました。

csc.exeは(vbc.exeもそうなんでしょうが)コンパイラーでありながら、リンクやラナンやらの手間がなくスピーディに即exeファイルを輩出してくれるので、シンプルなMSCompAssを使って簡単なコンソールプログラムをコンパイル、実行していると、まるで若い頃にBasicインタープリターでプログラミングを勉強していたころを思い出します。(やはり単純なプログラムをサクサクやるならVisual Studioでは重いでしょう。)

 

さて、コンソールプログラムで基本的なことを学びながら勉強をしていますが、ソースコードはコピペするだけなので、そのオリジナルコードを使っていろいろと遊ぶのが私の仕事です。たとえば、C#ではC++の"using namespace"のように、

 

using System;

 

で始めるのが定番なんですが、この意味はC++でいえば、恰も

#include    <System.h>
#pragma comment(lib, "System.lib") 
としているようなもので、DLLをロードして関数や定数の定義が使えるようになるようだな、とC++と比較して納得しています。

 

また、C#はその名の通り、CやC++に文法等は極めて近いのですが、より現代的、洗練されていて、ポインター参照などは"unsafe"と宣言してそのコンテキストで直接メモリーを触る以外は「検証可能なセーフコード」になっているそうです。

ではエラーはどうやって出るのでしょうか?以下はオリジナルの例題コードに私が書き込みをしたものです。

 

    public static void Main()
    {
        char[] chararray = new char[3];
        chararray[0] = 'a';
        chararray[1] = 'b';
        chararray[2] = 'c';
        Console.WriteLine("char 配列名のみを出力");    //改行コードを入れなくても改行されます
        Console.WriteLine(chararray);
        //Console.WriteLine("({}を使って)char 配列名{0}を(変数埋め込みで)出力", chararray);
        //ハンドルされていない例外、としてエラーとなる


        string str;
        str = new string(chararray);
        Console.WriteLine("stringに代入して{0}を出力", str);

        char[] title = {'猫', 'で', 'も', 'わ', 'か', 'る'};
        string strTitle = new string(title);
        Console.WriteLine(strTitle);
        Console.WriteLine("最初の文字は{0}なのでstringはutf-16なのだろう", title[0]);    //char[0]の1文字は「猫」です。

        string strx = "C#プログラム";
        int n = strx.Length;
        Console.WriteLine("「{0}」の文字数は{1}です", strx, n);

        char c = strx[1];
        Console.WriteLine("「{0}」の2番目の文字は「{1}」です", strx, c);
        Console.ReadKey();
    }
 

C#ではプログラム内にメモリー領域を確保して変数を持つ場合(値型)とヒープ領域に変数領域を確保してそれを参照する場合(参照型)があるということで、(おそらくutf-16の洗練された)文字列変数Stringは参照型で、8bitの値型として残るcharとの差異を↑のように実験しています。"chararray"というchar配列(NULL終端はありません)を出力するとちゃんと文字列が表示されますが、文字列の中に埋め込む形にすると例外処理となります。(ただしセーフコードなので落ちません。)

 

また、C#ではコンソールから数値入力を直接受け付けず、文字列から数値へ変換するようですが、「変換できない文字を入力されたらどうなるのかな?」という疑問を持ったら即実験して、新しいメソッドを知る、という勉強をしています。(↓の赤字部分)例えば次の例では、Console.ReadLine()がnullを返すのはコンソールの場合Ctrl-Zであり、空行確認は if(takasa != null) と書いてはいけない、とか、オリジナルではコメントアウトしたParseメソッドをつかったheight = double.Parse(takasa);ですが、これだと数値へ変換できない文字列が入力された場合、(C++のtry~catchのように)例外エラーメッセージが出て終わるので、TryParseというメソッドを使ってエラー処理ができることを学習しています。

 

    public static void Main()
    {
        double baseline = -1, height = -1, area = -1;    //値を代入して初期化しなで、そのままメソッドで使うとCS0165「未割り当てのローカル変数が使用されました」エラーとなる
        string teihen, takasa;
        while (true)
        {
            Console.Write("高さ:");
            takasa = Console.ReadLine();
/* ReadLineメソッドは、リダイレクトやパイプで渡される内容が終端(EOF)に達した場合や、コンソールアプリケーションにおいてCTRL+Zによって入力を中断した場合など、それ以上標準入力から読み込める文字列がない場合にはnull/Nothingを返します。-Microsoft Docsから*/
            if(takasa != "") {    //if(takasa != null) にはならない
                if(!double.TryParse(takasa, out height)) {        //変換できない場合falseが返る
                //height = double.Parse(takasa);                //エラー処理がない
                    Console.WriteLine("変換に失敗したので終了します。");
                    break;
                }

            }
            Console.Write("底辺:");
            teihen = Console.ReadLine();
            if(teihen != "") {
                if(!double.TryParse(teihen, out baseline)) {    
//変換できない場合falseが返る
                //baseline = double.Parse(teihen);                //エラー処理がない
                    Console.WriteLine("変換に失敗したので終了します。");
                    break;
                }
            }

            area = baseline * height / 2.0;
            Console.WriteLine("高さ{0}、底辺{1}の三角形の面積は{2}です。",
                height, baseline, area);
        }
        Console.ReadKey();
    }

時には新PCのキーボード(Win10機と配置がやや異なります)に慣れていないことから、

 

        Console.WriteLine("myarray[0, 0] = {0}", myarray[0, 0]);
        Console.WriteLine("myarray[0, 1] = {0}", myarray[0, 1]);
        Console.WriteLine("myarray[0, 2] = {0}", myarray[0, 2]);
        Console.WriteLine("myarray[1, 0] = {0}", myarray[1, 0]);
        Console.WriteLine("myarray[1, 1] = {0}", myarray[1, 1]);
        Console.WriteLine("myarray[1, 2] = {0}", myarray[1, 2]);
 

というオリジナルのコードを、

        
        Console.WriteLine("\r\nfor文で書き直します。\r\n");

        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 3; j++) {
                Console.WriteLine("myarray[{0}, {1}] = {2}", i, j, myarray[i, j]);
            }
        }

に書き直したら、
//array02.cs(20,56): error CS1061: 'int' に 'myarray' の定義が含まれておらず、型 'int' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
というエラーが出て焦りましたが、その原因は、

//→原因は"j,"と書くところ"j."と書いたためメソッドと認識されてしまった。
というタイポ(', '→'. ')だったというお粗末もありました。

 

いずれにせよ、現在は個人用の実用的なアプリのアイデアがないのでBCCSkelton、ECCSkeltonでのプログラミングは少しお休みして、もう少しの間MSCompAssで遊んでみます。

 

主にオプション設定でVersion1.1に修正を行いましたが、実際に動かしてみるとユーザーインターフェースが不味かったり、プロセスが残ったりしたので、再修正を行いました。


今回最大の修正内容はコンパイルしたプログラムの実行部分であり、前は(実行プログラムからのテキスト出力を取得する)CCMDEDITクラスを通じての実行でしたが、ウィンドウプログラムなどはプロセスが終了しない不具合があり、今回は単純にWinExeで済ませ、コンソールプログラムはDOS窓から出力を見るBatchGoodスタイルにしました。(注)
注:ということで、コンソールプログラムの出力結果を見たい場合、DOS窓が直ぐに閉まらないようにする為に、Main()の最後にCやC++のgetch()に相当する、Console.ReadKey()を追加するよう推奨します。

色々と段取りが悪くてすみません。最終的にこんな風になりました。

今朝のブログに書いた通り、C#の勉強用とはいえ、コンパイラーのオプションをすべて手書きに任すのも忍びなく、先だっての出力先の問題を踏まえて、vbc.exeとの互換性も考え、以下のようにしました。

 

1.出力関連

(1)出力先は「/out:(出力ファイル)」というオプションがあり、焦って改造した奴はこれを使っていましたが、勉強用程度のものならソースファイルと同じフォールダーで何ら問題が無いこと、このオプションは文字列が長くなりすぎることから、コンパイル時にカレントディレクトリーをソースファイルのところに移動し、終了後元に戻る形にして「/out」オプションは採用しませんでした。

(2)ターゲットはコンソールアプリ、ウィンドウズアプリ(注1)は当然選択対象にし、DLLも一応入れておく必要があるということで、この三択(実際は未選択を入れて四択、以下同じ)だけにしました。実際に利用できるオプションはこれより多い(注2)ですが、そのような出力は手作業で入力するか、MSCompAssには手が余るようでしたらVisual Studioを使ってください。(以下同じ)

注1:後でテストとしてHello World!のコンソールプログラムをウィンドウズアプリでコンパイルするとちゃんとコンパイルされコンソールにも正しく表示されますが、色々とウィンドウズ用にくっついているらしく、ファイルサイズは100KB程増えました。

注2:その為にオプションをしているすダイアログには「主要オプション指定」というキャプションを振っています。

 

2.リソース

正直、C#でウィンドウズプログラムも作ったことが無く、rc.exeで*.resファイルは別建てでつくる必要があり、ここの設定には自信ありません。

Microsoft Docsなどで見ると*.resファイルのリソースもWin32のすべてではないようにも読めます。しかし、一応「/win32res」は入れておきました。(但し、テストでコンソールプログラムのコンパイルで、BCCSkeltonでつくったサンプルのresファイルを喰わせるとちゃんと食べました!リソース部分を単にくっつけるだけのようです。ファイルサイズが変化しました。)

「/win32icon」はプログラムアイコンの指定なんだろうと思っていますが、どうなんでしょう?のちに分かると思います。(笑)→後でテストしてみました。アイコンファイルを指定するとプログラムアイコンになります。

「/resource」は何を入れるのか正直分かりませんが、これも一応入れておきました。

なお、これらは「:(ファイルパス、名)」を追加する必要があるので、「ファイルを開く」ダイアログ(注)で指定できるようにしました。

注:ファイルフィルターは"リソースファイル(*.res)\0*.res\0アイコンファイル(*.ico)\0*.ico\0全てのファイル(*.*)\0*.*\0\0"にしています。

 

3.コード生成

/debugと/optimizeがありますので、単独、組合せの三択にしました。資料では「[+|-]」とあり、この後に+か-記号を付けるようですが、-はオプション無しと同義なので外しました。→後でテストしたら/debug+、/optimize+でちゃんとコンパイルされました。

 

4.警告

0-4の5段階の警告があるそうです。くどいですが一応選択肢に入れました。

 

出来上がりをサンプルプログラムでコンパイルして意図通りの動作をしていることを確認しました。

(余談ですが、/debug+をつけてコンパイルすると(ファイル名).pdbファイルが排出されますね。これでWinDbgも使えるようになるかも、です。)

 

ps. C# 6.0の表記を受け入れない話を今朝書きましたが、コンパイル時の出力を確かめたら、”Microsoft (R) Visual C# Compiler version 4.8.4084.0 for C# 5 Copyright (C) Microsoft Corporation. All rights reserved.”とありますね。新しい奴はロハじゃないのかな?

追記:そのあと、「最新のcsc.exeはロハで手に入るのかな?」とご本家のC#にかかわるcomprehensiveなサイトに行きました。その中の「C#の新機能」に最新版(C# 11)について説明があり、オープンソースの.NET(現在6から7に移行中?)をDLすればよいのだ、とのこと。しかし、訳も分からずに導入する恐怖があり、やはり当分は「C#の歴史に沿って昔のバージョンで遊んでみよう」と考え直しました。

【新PC】のつづき。

なぜか、最初は起動が遅かったWin 11機、最近は明らかにWin 10機よりも早くなってきている。やはり、速度を増すためのリンクファイル等の蓄積が実ってきたのかしら?

また、なぜか昨日Win 10機では「現在メンテナンス中。6時までお待ちください、」というサイトに6時になっていっても同じ表示で入れなかったが、Win 11機はログインできた。こういう時に冗長化の強みを感じますね。

なお、もうアクセサリー等の購入は必要ないだろうと新PC一式のコストを占めたのだけど、PCがAmazonのタイムセールで2万引き、23'で1,920x1,080の富士通のディスプレー(displayportで接続)が9千円弱、マウスとキーボードが2千円強、あと日本用電源コード等でほぼ8万円という感じ。最初店頭で調査をしたので店頭で見定めてから、と思っていましたが外国製や中古等豊富な商品をリアルタイム値引きで買うならネットショッピングは捨てがたいな、という感を強くしました。

 

【MSCompAss】ネタ。

どうも話は簡単ではなく、やはり「蚊を取るのに核ミサイル」ではなく、「ラドンを打ち落とすのに核ミサイル」が正しかったのかもしれません。→要すればC#でガチの開発をするならVisual Studioは必須だな、ということです。その理由はいくつかあります。

 

(1)出力ファイルの一件からオプションを調べたところ、現在の設定はコンソール向けだし、ウィンドウアプリならリソースを必要とするのですが、それは*.resファイルをリンクするようなのでrc.exe(注)でコンパイルしなければなりません。

注:旧Borlandのbrc32系リソースファイルとMicrosoftのrc系リソースファイルでは形式が異なります。現在のEmbarcadero、BCC102ではrc.exeを使うようになっていますね。

(2)警告やシンボルファイルを出力してMicrosoftのデバッガーを使うにはそのオプションを指定する必要がある。

(3)C#はVersion 11まで出ているようですが、ロハの.NET Framework は「v4.0.30319」でcsc.exeがどこまで対応しているかわかりませんが、どうも最新ではないようです。(注)

注:Version 6から使えるようになった「WriteLine($"...{変数1}...{変数2}")」(WriteLine("...{0}...{1}", 変数1, 変数2)と同様)がコンパイラーを通りません。その他でも新し目の表記でエラーが出ます。

 

そんなこんなで、やはりVisual Studioも使おうかな、と2022バージョンを開発拗音Win 10機でDLしようとしたら「64bitオペレーションシステムではない」というエラーが出てしまいました。(これからは開発もWin 11機に移行せざるを得ないのかな。)

いずれにしても腐っていても仕方がないので、MSCompAssには一応簡単なオプション指定機能を付けてC#の勉強は続けていこうかと考えています。

 

さて、MSCompAssというツールでロハ(「只」という漢字の隠語ですね)でWindowsから頂けるC#コンパイラー(csc.exe)が使えるので、所謂「初歩からのC#」を始めていこうかと考えています。

 

何を教科書にするか、ネットを漁ったのですが、一つは私が20年以上前に初めてWin32 APIを学習する際にお世話になった

1.「猫でもわかるプログラミング

とし、一方これでは古いしアカデミック性が高いものも欲しいな、ということで現在ちょっとはまっている

2.「++C++; // 未確認飛行C

にお願いしようかと思っています。とくに後者(注)はプログラミングのみならず、情報工学、数学、物理等についても書かれており、幅広く「ボケ防止」に役立ちそうです。

注:まだ最初の入り口にいる段階ですが、C++との類似点、相違点(注)がよくわかり、特に相違の方が圧倒的で、気を引き締めて再学習しないとだめだな、と感じております。

注:null 条件演算子、null 免除演算子、checked、unchecked、default、delegate、IEnumerable、foreach、yield、from、with等々山ほどあります-大体C#でcharがあるのですが、ワイド文字やロケールはどう扱っているのだろう?

 

一方、MSCompAssについてですが、プログラムの説明を長々とやるには恥ずかしい「BatchGoodのオフセット」なので、概略だけサクッと紹介します。詳しくは今後アップしているパッケージのサンプルにソースも入っていますのでそちらをご覧ください。

【リソース】

BatchGoodのダイアログを流用。メニューとツールバーボタンでわかるように「ファイルを開く、ファイルを閉じる(初期化)、プログラムの終了、ソースファイルの編集、コンパイル、Exeファイルの実行、MSCompAssの設定、csc.exeのオプションを含む使い方説明、バージョン情報」となります。

強いて「売り」を挙げれば、ドラッグアンドドロップ、最小サイズ制限付き可変サイズダイアログ(アンカー付きコントロール)ですかね。

また、ダイアログ下部のCCMDEDITクラスのエディットボックスで、エラーメッセージを含むコンパイル結果はもちろん、コンソールプログラムでも出力が見られます。(↑のイメージ参照)出力表示が多い場合はダイアログを大きくしてください。

 

【MSCompAss.cpp】

モードレスダイアログベースのSkeltonWizard通りのコードです。

 

【MSCompAss.h】

最小サイズ制限用にメンバー変数にm_Width(ダイアログクライアントエリア幅)、m_Height(ダイアログクライアントエリア高さ)を入れています。

BCCSkeltonからは、ツールバー(CTBARクラス)、ステータスバー(CSBARクラス)、コモンダイアログ(CMNDLGクラス)のみならず、コマンドライン(CARG)クラス、iniファイル作成クラス(CINI)、拡張子チェッククラス(CEXTCHK)、CCMDEDITクラスを使っています。

また、外部変数として、

//---------------
//グローバル変数
//---------------
//システム関係(iniファイル用)
CSTR g_OwnPath;            //MSCompAssフォールダーへのパス
CSTR g_IniFile;            //MSCompAss.iniファイルのパス・ファイル名
CSTR g_FileName;        //ソースファイルのパス・ファイル名
CSTR g_HelpFile;        //ヘルプファイルのパス・ファイル名
CSTR g_Csc;                //csc.exeのパス・ファイル名
CSTR g_Vbc;                //vbc.exeのパス・ファイル名
CSTR g_Edit;            //エディターのパス・ファイル名
char* g_Filter;            //フィルター用変数
int g_FileType;            //拡張子用変数(".cs" - 1、".vb" - 2それ以外 - 0)
//ファイル起動用変数
int g_ByFile;            //ドロップファイルがある場合のフラグ
char* g_ptFile = 0;        //入力ファイルパス、名へのポインター
を使っています。

 

【MSCompAssProc.h】

解説すべきポイントは、

(1)iniファイル処理(OnInit()でiniファイルからコンパイラーとエディターの古パスファイル名を読み込みます。また、OnClose()で書き込みます。)

(2)ドラッグアンドドロップ(g_ByFileフラグによる引数付き起動処理とOnDrop()のドラッグアンドドロップ処理)

(3)アンカー付きコントロール(OnInit()でクライアントエリアの初期値を取り、OnSize()関数で変更差分を各コントロール毎に処理します。)

(4)最小サイズ制限付き可変サイズダイアログ(OnMaxMin()関数の定番処理です。)

(5)CCMDEDITのExec()関数処理(注)

でしょうか?

注:このクラスは、プログラムやコマンドを別プロセスを実行し、別スレッドで終了監視してエディットコントロールに結果を出力するクラスです。BatchGoodの時はバッチファイルの実行で起動するプログラム出力をきれいに反映できず、WinExecを敢えて使いましたが、MSCompAssではBCCMakerと同じようにここに出力を表示できました。

 

最後に「ヘルプ情報」(MSCompAssHelp.chm)ですが、csc.exeとvbc.exeのヘルプファイルを資料1、2で載せていますが、私自身が未だよく分かっていないので詳細は不明(笑)です。

 

MSCompAssの説明が雑になりましたが、気持ちはもうC#学習(結構大変そうな予感)に移っているので、ご容赦ください。

 

追補(同日):早速のMSCompAssmの修正です。

MSCompAssにソースファイルをドロップしてコンパイルすると(当たり前ですが)実行ファイルはMSComAssのフォールダーに作られることに気が付き、早速「ヘルプの資料1、2」を調べてC#、VBともに出力ファイルにかかわるオプション"/target:exe"(exeファイルの作成)と"/out:(ファイル名)"が共通であることを確認して、「ソースファイルパスにexeファイルを出力することを規定のオプションにする」ことにしました。(いやなら「オプション」エディットコントロール内のオプション引数を手入力で修正する。)

修正版は本日アップしましたので、DLできるまで少しかかります。なお、それまでにDLされた方はコンパイル時にMSCompAssのフォールダーを確認してください。

なお、↑のイメージも新しくしたMSCompAssのもので、オプションが指定されていることがわかります。
 

今後軽ーくMSCompAssのプログラム説明をしてから、私のC#学習ブログを展開してゆこうかと考えています。

その際に使うツールはMSCompAss、Windows 10、11付属のC#コンパイラー(csc.exe)とエディターですが、私はサクラエディターを使っており、残念ながら標準ではC#のキーワード強調文字列対応ができていないので、本日調べてできるようになりました。以下はそのお裾分け。

 

1.キーワードファイルを取得する

このブログで提供されている↓のキーワードリストテキストファイルを取得します。

 

2.サクラエディターへの設定

私はこのブログを参考に設定しました。これなんかもわかりやすいですね。

なお、両ブログともに強調文字のカラーリングについて詳細に書かれていませんが、C#のキーワードを設定したら、「設定」→「タイプ別設定一覧」で「C#」を選択し、右上の「設定変更」ボタンを押して「タイプ別設定」ダイアログを開き、「カラー」タブをクリックして表示される「色指定」の下の方へ行き、「検索文字列1~」と「強調文字列1~」を色替えしてやるとそれらしい見え方になるので試してみてください。

 

2022/10/02 追記:後で気が付いたのですが、上に加えてコメントの色付けができていなかったので「設定」→「タイプ別設定一覧」で「C#」を選択し、右上の「設定変更」ボタンを押して「タイプ別設定」ダイアログを開き、「カラー」タブの「コメントスタイル」にブロック型の「/*~*/」と行型の「//」を加えてやってください。

 

前回、天下のMicrosoft様の「Visual Studioという、これでもかという充実した開発環境なのに、太っ腹でロハ」なのにもかかわらず、「初心者を何も分からないままにMS側の開発手続きを強制させ、作る喜びを奪っている」などと批判し、大見え切ったからには何もせずにはすまされないだろう、と愚考し、「バッチファイルの単なる自動化」だけのプログラムを作ってみました。

 

題して、

 

"MSCompAss"(Microsoft Compiler Assistant-注)

注:間違ってもMicrosoft's Competitive Ass!、ではないですよ。

 

というC#コンパイラー(csc.exe)、Visual Basicコンパイラー(vbc.exe)にソースファイルを食わせるだけのプログラムです。(笑)

ベースはBatchGoodを最大活用し、一応指定エディターでソースの編集を行い、出来上がった実行ファイルを動かすこともできるようにしています。

 

まぁ、バッチファイルを毎回組んでコンパイルするよりはましな環境になるでしょう。

僕も前からC#にはちょっと関心があったので、これで入門プログラムなどを打ち込んで勉強してみようかな、と思っています。

 

現在csc.exeとvbc.exeのヘルプファイルを入手して、これから「最低限のヘルプファイル」を作ろうかと思っていますので、それが終わり次第パッケージのサンプルに追加してアップする予定です。

 

新PCも目新しさも褪せ、附随ソフトも一通り目を通し、使用環境を前のWin 10マシンと互換状態にしたところで

「Win 11マシンもx64になっただけで、x86のWin 10マシンと基本変わるところなし」

という結論に到達しましたので、またプログラミング中心の話に戻ろうと思います。

 

x64やWin 11を調べていた時に、次のネタを探していて、

 

OSに標準付属のC#/VBコンパイラーでソースコードをコンパイルするには?

 

を見つけ、面白いな、と思いました。というのは、にフリーのMicrosoft Visual Studio Community Editionについて、

「Visual StudioはC++のみならず(というかC++はむしろ今ではマイナーかな)、MSの今日を築いたVisul Basic、現代的なOOPプログラミングを可能とするC#やPython、XMAL等の豊富な開発言語やIDEがあります。私もC++を落として触ってみたのですが、基本的にWin32SDKプログラムの開発に必要なツールはすべてあるのですが、極めて複雑なプロジェクト、ソリューション管理があり、ファイルやフォールダーの構成もお任せでユーザーが勝手にいじれない領域が多いので、正直「アマチュア、小規模開発をホビーとして楽しむユーザー」には(IDEと同じく)重すぎます。

将来職業としてプログラミングを学ぶ方や、きっちりとした知見を備えたい、という方にはお勧めです。」

と書きましたが、「素人のVisual Studioでの開発は、蚊を取るために核ミサイルを発射するようなもの」というのが本音であり、趣味でつまらんプログラムを開発する暇プロには無用の長物と考えたからです。その理由を以下に纏めてみたいと思います。

 

例えばあなたが、プログラミングはおろか、ウィンドウズの技術的な側面についてズブの素人で、これから(趣味として)C#でプログラミングを始めようと思っていると仮定します。(注)

注:そういう場合、CやC++の人は"Hello, world!"を表示するプログラムから入るのが定番なんで、C#でも踏襲するのが筋でしょうね。↑の記事はそういう意味もありますね。

 

ウィンドウズご本家のフリー(無料)の開発環境(IDE)を、ということでVisual Studioの最新版(注)をご本家のサイトからダウンロードします。

注:現在、開発環境のあるWin 10マシンで本原稿を書いていますが、私のVisual Studioは「最新版」だった2019です。MSによれば先週の土曜(2022年9月24日)のリリースで2022が出ていますね。ただ、私はDLする気もないので以下は2019バージョンで話を進めます。

 

心を期待に膨らませ、C#(Visual Basic等他の8つの対応言語でも同じですが)でダウンロードしたVisual Studioを起動してみると、最初に次の画面が出ますね。

「NUnitテストプロジェクト」、「Windows フォームアプリケーション(.NET Framework)」、「Windowsフォームアプリ」、「WPFアプリケーション」、「WPFクラスライブラリー」から選べ、と、こう来ます。

「はぁ???何???」

フォームアプリの二つはどう違うの?WPFって何さ?というのが本音ではないでしょうか?ここらへんで「場違いなところに踏み込んだ感」一杯で心が折れてきますよね?でも、もう一度気合を入れなおして、この後、

「えいやっ!」

と何を選んでも、

「理解していないうちに先に進まされ」

ドツボに嵌って、何か自分が非常に馬鹿で、無知を笑われているような気がして、心は完全に折れ、

「二度とやるかっ、プログラミングなんてっ!」

と感じる可能性は高いのではないでしょうか?

しかし、それはとっても不幸なことです。

 

実際、(自分では20年前結構勉強もしたし、Windowsプログラミングも解っているつもりだった)私も、

 

・「Windows Form

・「.NET Framework(これはVer 4.8で打ち止めだそうです)」

・「WPF(Windows Presentation Foundationの略で、Windows FormがWindows SKDのラッパー、つまりWindowsの出来合い部品の利用ライブラリーであれば、WPFは一段基礎に近い「部品開発もできる、利用ライブラリー開発レベルのライブラリー」といえるかもしれません)」

・「XAML(Extensible Application Markup Languageの略で「ザムル」というのだそうですが、譬えて言うならば、「プログラミングのプログラム言語」ですね)」

・「.NET Core(Win 10、11頃から導入された他OSとのクロスプラットフォームのマネージソフトウェアフレームワークで、今は単に.NETだけの表記になったそうです)」

・「UPF(Universal Presentation Foundationだそうです。もうどうにでもしてくれぃ、という感じですね。)」

 

という、PCがレガシーになり、モバイルが台頭し、モバイルを含め数多のOSやプラットフォームとの互換、接続可能なソフトウェア作りやユーザーインターフェースの作成効率化が求められた結果の技術進歩に殆どついていけていません。

 

しかし、それはプロの世界の話で、個人でプログラミングを楽しむ者たちが、ほんの小さな成果物ができて喜ぶことを妨げてしまっては本末転倒ではないでしょうか?

 

だから私は声を大にして言いたい。

 

「蚊を捕るなら、蚊取り線香で十分なんだよ」、と。

 

それが、

 

OSに標準付属のC#/VBコンパイラーでソースコードをコンパイルするには?

 

を読んで感じたことです。素人の趣味プログラマーは所詮リソース(ユーザーインターフェース-UI)も限られている、サイズも小さな、愚にも付かない、つまらないソフトしか作りませんが、それを作るプロセス、結果のソフトウェアが動作した瞬間の楽しさが全てなんです。言語が何だろうと、見た目やUIがどうであろうと、アルゴリズムがどうであろうと、バグがあろうと、

「プログラミングは作る楽しさ」

なんです。↑の記事は単にコンソールに"Hello, C#"とか"Hello, VB"と出すだけですが、それでもやっぱり楽しいんです。だから、...

貴方もやってみて。

 

次回からは簡単なC#(序にVBも、かな)プログラムのコンパイル用ツールを作り、web上にたくさんあるC#サンプルプログラムを動かせるようにしてみようかと思っています。(それまでは↓のバッチファイルで我慢してください。)

 

【↑のサンプルC#、VBプログラムのコンパイル用バッチファイルの作り方】

(1)システムドライブ(通常「C:」)のWindowsフォールダーの中にMicrosoft.NETフォールダーがあるか、更にその中にFramework(またはFramework64)があるか、更にその中に「v.XXXXXXXXXXX」(v.はVersionの意味、数字の大きな新しいものを選びます)があるかどうか、調べます。

(2)その新しいバージョンのフォールダーの「csc.exe」(VBなら「vbc.exe」)を探し、それを選択して右クリックし、「パスを取得」(Win 11、Win 10なら「プロパティ」でファイル場所とファイル名)でフルパス名を取得します。

(3)ソースファイル(HelloWorld.csまたは.vb)のあるフォールダーで、右クリックによる「新規作成」でテキストファイルを開き、"(csc.exeまたはvbc.exeのフルパス名) HelloWorld.cs(またはvb)"、次の行に"pause"を書き込みます。

(4)テキストファイルの名前を"NETCompile.bat"等にし、ダブルクリックで実行します。ちゃんと"Hello, C#"とか"Hello, VB"とでるかな?

 

【参考サイト-いろんな人が色んな書き方をしていますが、サラッと流した方がよいと思いますよ】

WindowsフォームとWPF両方開発した経験を元に、比較してみる

Windows フォームから WPF へ移行すべきか?

何が同じで、何が違うのか? - Windowsフォームアプリケーション、Windowsフォームアプリ、そしてWPFアプリケーション

WindowsフォームでWPFコントロールを利用するには?

ユニバーサル Windows プラットフォーム (UWP) アプリとは