0 と 1 の世界の見習い探検家

カテゴリ: プログラミング日誌

どうも、こんにちは。
あおとです。

PowerShell で Windows 内にインストールされている一番新しいバージョンの .NET Framework の C# のコンパイラを呼び出し、C# のソース ファイルを EXE にコンパイルするコマンドをご紹介します。
2021 年の記事ですが、 .NET Core や .NET 5 ではないです。ごめんなさい。

更新すると言いつつ、この頃全く更新ができていなかったため、久々に更新します。
書くことに意義がある、というスタンスの記事のため、役に立つ内容かどうかは取り敢えず一旦横においておくとして。


結論
$SourceFile="example.cs"
$LatestVersionCSharpCompilerPath=(Get-ChildItem "C:\Windows\Microsoft.NET\Framework\v*\csc.exe" | ForEach-Object { $_.FullName } | Sort-Object)[-1]
Invoke-Expression ($LatestVersionCSharpCompilerPath + " " + $SourceFile)

この 3 行で C# のコンパイラを探してソース ファイルをコンパイルします。


1 行目: $SourceFile="example.cs"
至ってシンプルです。C# のソース ファイルを指定します。フルパスでも良いですし、パラメータで受け取る形にしてあげても OK。

2 行目: $LatestVersionCSharpCompilerPath= ~ (略)
C# のコンパイラ "csc.exe" を検索します。
検索と言っても場所は大体決まっているため、条件に合う csc.exe を列挙したのち、パスをソートし一番最新のモノを引っ張り出しています。

3 行目: Invoke-Expression ~ (略)
コンパイラを実行します。
csc.exe には他のアセンブリ (DLL) の参照や、出力されるアセンブリのタイプを指定するオプションが存在しますが、
例えばプロンプト画面 (黒窓) を使用しない Windows Forms などのアプリをコンパイルする場合は、下記のような形で指定ができます。

Invoke-Expression ($LatestVersionCSharpCompilerPath + " -t:winexe " + $SourceFile)

csc.exe のオプションに関しては、下記記事を参照されたし。
カテゴリ別の C# コンパイラ オプションの一覧 | Microsoft Docs https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/compiler-options/listed-by-category

以上。

イメージ 1


今度こそ最後の投稿です。
Yahoo! ブログのページ ソースをまるっと取得するツールのバイナリ リリースを公開しました。

Simple Downloader for Yahoo! ブログ - ソフトウェア | 0と1の世界の見習い探検家
http://www.a32kita.net/software/ybsimpledl/

急ごしらえのため、現在はページのソースデータを取得する範囲に留まっておりますが、
今後ソースデータから Yahoo! ブログ公式の移行ツールの対象とならないコメントなどのデータを個人で保存するために抜き取るツールなども鋭意開発中です。

本ツールは、 Yahoo! ブログ公式の移行ツールを使用していない移行前のブログを対象としております。
また、パブリックに公開されている記事のみが対象となります。

今までありがとうございました。
ご訪問いただいた皆様、当ブログとこれまで友だち関係で居てくださった皆様に大変感謝を申し上げす。
また、このような素晴らしいブログ サービスを提供してくださりました Yahoo! JAPAN 様に、改めて感謝申し上げます。

今後ともよろしくお願いいたします。


ブログ移転のお知らせ

いつもご訪問頂きありがとうございます。
Yahoo! ブログのサービス終了に伴い、ブログを移転いたします。
移転先: http://blog.a32kita.net/
詳細は、こちらの記事をご覧ください。

ブログ移転のお知らせ

いつもご訪問頂きありがとうございます。
Yahoo! ブログのサービス終了に伴い、ブログを移転いたします。
移転先: http://blog.a32kita.net/
詳細は、こちらの記事をご覧ください。

Yahoo! ブログでは最後の更新となります。

イメージ 1

先月下旬、 Yahoo! ブログ公式の移行ツールではサポートされないトラックバックやコメントなどのデータを「個人用に取得する」ツールを開発していると紹介いたしましたが、
ごめんなさい。
間に合いませんでした。

言い訳としてはお盆の間も思いの外忙しかったや、 d! アニメで古いアニメ漁ってたらうっかりハマってしまった等々いろいろございますが、納期を守れないのはエンジニアとしてまだまだ未熟という証ですね ((

とはいえ、何も無いわけではないんです。
先程 master にマージしていまこんな状態、、

a32kita/YBlogLoader
https://github.com/a32kita/YBlogLoader

以下の機能の実装はできました
・ブログの基本データ (タイトル、開設日、著者名) を取得する機能
・「すべての記事」をクロールして、投稿記事の ID を片っ端から取得する機能
・投稿記事の ID から投稿先書庫などを取得する機能

…すべてスクレイピングの力技です。
ということでビルド済みバイナリでの公開は許してください (

以上の実装できた機能をもとに、とりあえず全ての記事のソースを取得するだけの「Simple Downloader」なるツールは一応動く状態にしておきました。
最新の記事から順番に HTML ソースを片っ端から PC に DL するだけのツールです。

イメージ 2

こんな感じで書庫別に HTML ファイルが落ちてきます。

Windows 向けで Visual Studio などの C# のビルド環境をお持ちの方は、どうぞお好きにビルドしてみてください。
完全にサービスが終了する 12 月まで少しずつアップデートを続けます。


投稿機能が無効化される前にこれだけ置いていきますね。
というわけで皆様お元気で。

では。

以前よりアナウンスされておりましたTwitterのUserStreamAPIの公開終了がいよいよ実施されます。
これにより、大多数のサードパティ製Twitterクライアントが致命的なダメージを食らうことになります。

幸いなことに(?)、私はUserStreamについては無影響です。
以前はkarno氏のKrileにお世話になっておりましたが、この頃はブラウザでtwitter.comを使うか、スマホでは公式クライアントでしたので。
また、現在Webサイトにて公開しているTwitter関連ソフトウェアの中にもUserStreamを使用しているアプリケーションはございません。

ただし今回のAPI改定、実はUserStreamだけではないんです。
もう1つ大きく変更が加わるのがDM(Direct Message)…。
こちらは公開終了ではなく代替の別のAPIへの移行という形になります。

公開しているソフトウェアの中ではDM関連は使用しておりませんが、私が個人的にサーバで動かしているシステムでは使用しているため、こちらは改修するか除去する他ないでしょうね(

かなり以前からアナウンスされておりましたが、実際に停止されて影響が出始めてからでないと、対応する気が起きないんですよね、、あくまでも趣味ですから(


しかしながらこのTwitterAPI、9月には今度はルールの改定があり、そこではAPIの使用自体がかなり厳しくなりそうです。
UserStreamについては、以前から私もTwitter社にとってマネタイズ面含めてメリットが無いと感じており、こちらの停止については納得できる部分もございます。
しかしながら、APIの使用条件自体の改定は、、
スパムの原因となるアプリケーションを遮断することが目的とのことですが、パクツイ垢とかあれだけ野放しになってる状況で、どうも痒いところに手がとどかない対応が続いており、個人的にはやや不満です。。
まぁ、何を言っても所詮は無料で使わせてもらっているサービス。
文句は言えませんね。

はい。

長々と愚痴のような駄文、失礼しました。
後日、API騒動で再びTwitterユーザー間で再燃しているMastodon関連についての記事も書きます。

では。

XAMLはWPFアプリケーションの開発において、UIのデザインや複数のコントロールなどで利用する背景デザインなどをまとめたResourceDictionaryを記述す際に利用するマークアップ言語です。
本記事では、通常、クラスライブラリには追加できないResourceDictionaryなどのXAML定義ファイルを追加し、またこれをUserControlのXAMLから利用したり、C#のコード上でResourceDictionaryをロードする方法を紹介致します。


クラスライブラリでXAMLを記述する

Visual Studioでプロジェクトを作成する際、クラスライブラリを選択すると追加項目の一覧に「ResourceDictionary」の項目が表示されません。

イメージ 1
図1 クラスライブラリで追加可能なWPF関連項目

クラスライブラリとして作成したプロジェクトとは別に「WPFアプリ」としてソリューションを作成し、その中で作成したResourceDictionaryのXAMLファイルをコピーする方法などもあるかと思います。
本記事では、テキストファイルとしてプロジェクトに追加した項目をResourceDictionaryなどを定義可能なXAMLの項目へ変更する方法をご紹介致します。

(1)参照の追加

ResourceDictionary型をはじめとするWPF関連の型が定義されているアセンブリや、XAMLを扱う上で必要になる各種機能を提供してくれるアセンブリを参照に追加する必要があります。
以下の項目をプロジェクトの参照に追加して下さい。
  • PresentationCore
  • PresentationFramework
  • System.Windows
  • System.Xaml
  • WindowsBase

(2)ファイルの追加


イメージ 2
図2 テキストファイルの追加

まず、クラスライブラリのプロジェクトへ「テキストファイル」を追加します。
その際、ファイル名を「***.xaml」という形で拡張子を「xaml」にします。

イメージ 3
図3 無効なマークアップ

追加すると、「無効なマークアップ」というエラーがデザイン画面に表示されます。

拡張子を「txt」のまま追加した場合、通常のテキストエディタモードでファイルが開かれてしまいます。
その際は、拡張子を修正した後、項目のプロパティを以下に示した図のように変更して下さい。

イメージ 4
図4 XAML項目のプロパティ

表1 XAMLファイルとして扱わせるためのファイルのプロパティ値
項目名
設定値
カスタム ツール
XamlIntelliSenseFileGenerator
カスタム ツールの名前空間
変更不要
ビルド アクション
Page
出力ディレクトリにコピー
コピーしない(変更不要)

こうすることで,プロジェクトに追加したファイルは,XAMLとして扱われるようになります.
具体的には,Visual Studioで編集する際は,XAML専用のモードで開かれ,また,ビルド時にはXAMLの定義データとして正しくビルドされるようになります.

(4)XAMLの記述

あとは、通常通りResourceDictionaryを定義していきます。

イメージ 5
図5 XAMLによるResourceDictionaryの記述


【解説】ビルド アクション「Page」

図4に示したとおり、XAMLファイルのビルドアクションは「Page」に設定する必要があります。
このPageについて解説をば。

XAMLの記述によって定義されたデータは、ビルド時に特殊な処理が行われます。

イメージ 6
図6 XAMLの扱い

XAMLファイルは通常のC#コードとは違い、ILコードには変換されません。出力されたアセンブリをildasmで定義したResourceDictionaryなどを探してみると、クラスとして扱われていないのがわかるかと思います。
※UserControlやWindowなどのXAML定義はロード用・コード記述用のクラスが作成されます。

XAMLはビルド時に「BAML」というXAMLを読み込みやすくバイナリデータ化したものに変換され、出力されるアセンブリに格納されます。
その際変換元となったXAMLファイルに基づき、BAMLデータにも識別名が振られるようです。これは実行時にBAMLからインスタンスを作成する際に利用しますが、詳細については後述します。

どうやら、その「BAMLへ変換,並びにBAMLデータのアセンブリへの埋め込み」という指示を表しているのがビルドアクション「Page」のようです。
やや検証不足気味ですが。。

やや余談ですが、XAMLとBAML、実行時に生成されるインスタンスは次のような処理関係になります。

イメージ 7
図7 XAML、BAML、インスタンスの関係

XAMLデータをファイルなどのStreamから読み込んでインスタンスを生成する「XamlReader」というクラスが実は存在しております.
しかし後でも触れますが,XAMLなどをはじめとするXMLデータのパース及びロードには実行コストが発生します.

ビルド時に予め,XAMLを読み込みやすいBAMLに変換することで,実行時に余計なロードコストが発生することを防いでいるようです.
XAMLをC#コードに変換して,そのあとに通常のコードと一緒にILにコンパイルするような仕組みを取っていると思っていたのですが,そうではなかったんですね...

XAMLを利用する(XAML)

UserControlなどのXAMLで、定義したResourceDictionaryを利用する場合は図7のように記述します。

イメージ 8
図8 ResourceDictionaryの参照

ResourceDictionaryのプロパティ「Source」にXAMLのUriを指定することで参照することが可能です。
XAMLのUriについては、後述の「XAMLを参照する際のUriについて」をご覧ください。
ソリューションをビルドするまでは、ResourceDictionaryの定義内容がUserControlのデザイナに反映されない場合がございます。

すでにUserControl内で定義したResourceDictionaryと合わせて利用したい場合は、新しくResourceDictionaryを作成し、MergedDictionariesで追加してあげると良いでしょう。

イメージ 9
図9 UserControlで定義したResourceDictionaryと合わせて利用する

XAMLを利用する(C#コード)

XAMLで定義したResourceDictionaryなどをC#のコード上で利用したい場合は、まずロードしてインスタンスを作成する必要があります。
ロードは、 System.Windows.Application 名前空間の LoadComponent メソッドを利用します。

イメージ 10
図10 LoadComponentの利用

Application.LoadComponent(new Uri("SampleClassLibrary;component/sampleresources.xaml", UriKind.Relative));

LoadComponentメソッドは指定したUriのXAMLをロードしてインスタンス化してくれるメソッドです。
戻り値はObject型になっておりますが、例えば、ResourceDictionaryを定義したXAMLをロードした場合は、そのままResourceDictionaryにキャストすることが可能です。

このとき指定するUriについては、後述の「XAMLを参照する際のUriについて」をご覧ください。

【解説】XAMLを参照する際のUriについて

XAMLの定義を利用するためには、XAMLのUriを指定して、ロードする必要があります。
Uriは通常Web上のコンテンツやローカルファイルのパスなどを指定する際に用いる型ですが、どうもWPFではアセンブリ内に格納された特殊なリソースを参照する際にも利用可能なようです。

その際のUriは文字列から初期化しますが、構文は次のとおり。
[アセンブリ名];component/[プロジェクト内でのパス(すべて小文字で)]

アセンブリ名は、恐らく出力アセンブリファイル名かプロジェクト名がこれに該当するのですが、通常はこの2つは一致するため、どちらが正解かは未検証です。
また、プロジェクト内でのパスも実際のcsprojファイルからの相対パスになるのか、あるいはcsproj内での論理パスになるのかは未検証です。既存のXAMLファイルをリンクで取り込んだ際は注意が必要です。

Uriの例

前述のサンプル「SampleClassLibrary」ではプロジェクトのルートに「SampleResources.xaml」を追加しました。
これを参照する際のUriは
SampleClassLibrary;component/sampleresources.xaml
になります。

また、プロジェクト内で「SampleDir」というディレクトリを作成し、その中に「Hoge.xaml」を定義した場合のUriは
SampleClassLibrary;component/sampledir/hoge.xaml
になります。

この辺は、通常のUserControlに対してVisualStudioが自動生成したラッパクラスの中身を見ただけなので、もっと深く調べる必要がありそうですね。

余談「ControlTemplateをXAMLで定義してみた」

コードから参照して利用する場合、ResourceDictionary以外でもXAMLに定義することが可能です。

イメージ 11
図11 ControlTemplateを定義してみた例

ControlTemplateは、XAMLで記述する場合、XAMLからのロードの都合もあり、通常はResourceDictionary内で定義しますが、ControlTemplateをコードから呼び出して利用したい状況が発生しましたので、ResourceDictionaryを省略して直接定義してみました。
正攻法とは言えないでしょうが、ControlTemplateを直接XAMLで定義すると、デザイナが仕事をしてくれるんですね。便利かも(?)

ちなみに、サンプルイメージの配色がTheドイツ国旗って感じですが、実験用にわかりやすい配色がないか考えたら偶然ドイツ国旗が頭をよぎっただけです。
ドイツ国旗シンプルでかっこいいですけど、それをイカしたUIに活用するだけのデザイン力は僕にはありません。
あ、ちなみにドイツ国旗の3色のうち一番下の部分って黄色じゃなくて正確には金色みたいですね。

余談「Application.LoadComponentとXamlReader」

ぶっちゃけ頑張ってBAMLとしてアセンブリに挿入させることにこだわらずとも、リソースとしてぶちこんだXAMLファイルを実行時にXamlReaderでLoadしちゃうなんて手もなくはないです。
というか、この方法を思いつかなかった時は、そうしていました。

しかし、通常のリソースとしてXAMLデータを添付した場合、若干ちゃんとBAMLに変換させたときよりも時間がかかるようです。
そらそうですよね。
BAMLってのはビルド時にXAMLを読み込んで最適化した結果なのですから。

あとファイルサイズが変わります。
BAMLのほうがファイルサイズ小さいです。
リソースとしてXAMLファイルを取り込むとXAMLのソースがそのまま出力ファイル内に取り込まれます。
テキストエディタでバイナリを眺めるという意味不明な習性を持っている僕と致しましては、圧倒的にBAMLのほうがかっこいいバイナリになります(意味不明)


では。

このページのトップヘ