やる気駆動型エンジニアの備忘録

WPF(XAML+C#)の話題を中心に.NET/Android/CI やたまに趣味に関するブログです

(WPF)App CenterにWPFが対応したので使ってみた

devblogs.microsoft.com

上記ページでApp Centerに WPF/WinForms が対応したとのことなので早速使ってみました。 私自身これまで App Center を使ったことがなかったため、このエントリでは導入から Analytics までをチュートリアル形式で記載しています。

開発環境

開発環境はこんな感じ。

なお、2019年8月8日時点で App Center の WPF/WinForms はプレビュー版のみの提供となっています。 そのため、.NET Coreには対応していません。 .NET Framework 4.5以上が対象となっています。 今後は.NET Core 3.0にも対応予定とのことなので期待したいところです。App Center のロードマップについては以下を参照してください。

github.com

また、今回私は以下のページを参考にしています。

docs.microsoft.com

App Centerの設定

App Center を開き、[Add new] - [Add new app] を選択して以下の様に OS は Windows, Platform は WPF を選択します。あとは[Add new app] を選択します。

f:id:iyemon018:20190808221428p:plain

[Settings] を開いて右上のメニューから [Copy app secret] を選択します。 ここでコピーした Secret は後ほど使うのでエディタにでもコピペしておいてください。

f:id:iyemon018:20190808221948p:plain

さて、これで App Center の準備は整いました。

アプリに組み込む

次はアプリです。 適当に.NET Framework 4.5以上の WPF アプリを作成してください。

まずは、NuGet から App Center のパッケージを取得します。

Install-Package Microsoft.AppCenter.Analytics -Version 2.2.1-preview
Install-Package Microsoft.AppCenter.Crashes -Version 2.2.1-preview

これを実行すると大量のアセンブリが追加されるのでしばらく待ちます。

準備が整ったらApp.xaml.csを以下のようにします。 まずは、アプリ セッションを開始して App Center と接続できることを確認します。 using は忘れずに。

namespace AppCenter.Wpf
{
    using System.Windows;
    using Microsoft.AppCenter;
    using Microsoft.AppCenter.Analytics;
    using Microsoft.AppCenter.Crashes;

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            AppCenter.Start("<ここに Secret を貼り付ける>", typeof(Analytics), typeof(Crashes));
        }
    }
}

以上! 簡単ですね。

このままアプリを起動すると App Center の[Analytics] - [Overview] は次のようになります。

f:id:iyemon018:20190808222745p:plain

まずはこれでアプリが App Center に接続できたことを確認できたので、もうちょっと触ってみます。

チュートリアルはいくつかあるのですが、わかりやすいのが Event だったのでこちらを実装します。 ちなみに以下のページを参考にしています。

docs.microsoft.com

Event には以下のようなコードを追加して予めどのようなイベントが有るのかを定義します。

// 第一引数は name, 第二引数は parameter
Analytics.TrackEvent("Video clicked", new Dictionary<string, string> {
    { "Category", "Music" },
    { "FileName", "favorite.avi"}
});

MS Docs ページとコードのコメントを読む限りだとname, parameterには以下のような制限があるようです。 元の文章が英語なので間違ってたらごめんなさい…

  • Event に定義できる数は最大で 200 個。これはnameに最大 200 種類のイベント名称を定義できるということ。
  • nameは最大 256 byte まで。
  • 1種類の Event につき、プロパティ パラメータは 5 つまで。これはparameterに 5 種類のプロパティ名を設定できるということ。
  • parameterのプロパティ名は最大 64 byte まで。

実質 Event 名称 : 200 x パラメータ 5 で 1000 種類のイベントを計測することができそうです。

これをApp.xaml.csに追加します。

namespace AppCenter.Wpf
{
    using System.Collections.Generic;
    using System.Windows;
    using Microsoft.AppCenter;
    using Microsoft.AppCenter.Analytics;
    using Microsoft.AppCenter.Crashes;

    public partial class App : Application
    {
        #region Methods

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            AppCenter.Start("<ここに Secret を貼り付ける>", typeof(Analytics), typeof(Crashes));

            Analytics.TrackEvent("Example", new Dictionary<string, string>
                                            {
                                                {"Category", "Music"}, {"FileName", "favorite.avi"}
                                            });
        }
    }
}

例えば上記のExampleイベントを App Center で取得するには以下のようにします。

Analytics.TrackEvent("Example");

あとはこれを画面からボタンクリックなどのイベントハンドラから呼び出してやればOKです。

namespace AppCenter.Wpf
{
    using System.Collections.Generic;
    using System.Windows;
    using Microsoft.AppCenter.Analytics;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TestButton_OnClick(object sender, RoutedEventArgs e)
        {
            Analytics.TrackEvent("Example");
        }

        private void MusicEventButton_OnClick(object sender, RoutedEventArgs e)
        {
            Analytics.TrackEvent("Example", new Dictionary<string, string> {{"Category", "Music"}});
        }
    }
}

Analytics.TrackEventメソッドの第二引数にプロパティ名を指定することでより詳細なイベントの振り分けができそうです。

さて、これでアプリを起動して何回かボタンを押すと、 App Center の[Analytics] - [Events] は以下のようになります。

f:id:iyemon018:20190808224726p:plain

Exampleというイベントが追加されました。 イベントをクリックするとさらに詳細な情報を取得できます。

f:id:iyemon018:20190808224917p:plain f:id:iyemon018:20190808224934p:plain

Event はうまく使えばユーザーの利用状況とかかなり具体的かつ正確に収集できそうです。

最後に

さて、他にもクラッシュログとかプッシュ通知、アプリの自動配布なんかもあるそうです。 クラッシュログは Android の Crashlytics みたいなイメージでしょうか? アプリの自動配布もこれまでは Click once しかなかったので、代替案になるかも検証していきたいと思っています。

ちなみに今回のサンプルは App Center 初利用の私でも 1時間程度で組み込むことができました。

まだまだ App Center は触り始めたばかりで勉強不足な部分が多々あるので、もう少し色々触ってみようと思います。

Surface Bookがモニターアーム+ノートPCスタンドで快適に使えるようになった

私は自宅の開発環境はSurface Bookを使っています。 SurfaceなのでもちろんSurface Dockも使っています。

自宅の環境で悩んだ末にモニターアーム+ノートPCスタンドの環境が自分にピッタリだったので紹介したいと思います。

これまでの問題点

私は開発するときはできるだけ作業スペースを確保したいのですが、ノートPCってキーボードが邪魔じゃないですか? Surface Bookのいいところは、キーボードとディスプレイが分離型であることとディスプレイを前後入れ替えても問題なく使用できるところにあると思っています。 なので、ディスプレイを通常とは逆向きに接続して作業スペースを確保するように使用していました。

f:id:iyemon018:20190714191928j:plain

ただ、これでもテーブルとの接地面積は結構広く、ちょくちょくSurface Bookの位置を調整することがありました。 これが面倒だったのでどうにかできないかなーといろいろ調べてみました。

モニターアーム+ノートPCスタンドを使ってみた

で、調べた結果、すでに使ってたモニターアームに取り付けられるノートPCスタンドを見つけました。

設置するとこんな感じになります。

f:id:iyemon018:20190714192001j:plain

ディスプレイを反転して使ってるのはモニタの高さと合わせるためです。 Surface Book以外のコンバーチブルでないノートPCだとそのまま乗せるしかないのですがこういうところが地味に便利ですね。

さて、モニターアームに取り付けるということはある程度の高さがります。 なので地震なんかで揺れたりすると落ちたりするのかと思いましたが、ガッチリ固定することができるため問題ありません。 手で位置を調整しても気にならないレベルです。

f:id:iyemon018:20190714192031j:plain

モニターアームに乗せることでテーブル上の作業面積が広がりました。

これで快適ですね!!

さいごに

これ、会社にも導入したいなーと思ってたんですが、会社のデスクはモニターアームが設置できない構造になっているため、あえなく断念しています。 利用しているテーブルの構造やノートPCによっては使用できないパターンはあるかもしれませんので、現在の環境で利用できるかどうかきちんと確認する必要があります。

特に、モニターアームはクランプ式とグロメット式があるため、どちらの設置方法で使うかによって利用不可能なシーンも有ることでしょう。 参考程度に私が使用しているモニターアームはこちらです。

みなさんも試行錯誤してベストな作業環境を作ってみてください。

Azure Pipelines で.NET Core 3.0 Preview をビルドする

前回.NET FrameworkWPF プロジェクトを.NET Core 3.0 Preview へ移行したのですが、そのときAzure Pipelines ではビルドできないと思っていました。

iyemon018.hatenablog.com

しかし、@kkamegawa さんからのアドバイスを頂き、自動ビルドができることがわかりました。

今回はその手順をまとめます。

実行手順

まずはgrobal.jsonファイルを作成します。 このファイルは実行環境に複数の.NET Core SDK が存在する場合にgrobal.jsonに定義したバージョンのSDKを使用する事ができます。

docs.microsoft.com

grobal.jsonを作るにはプロジェクト フォルダ上でコマンドプロンプトを起動して以下のコマンドを実行します。

dotnet new globaljson --sdk-version <.NET Core のバージョン>

例えば.NET Core Preview4 の場合は以下のようになります。

dotnet new globaljson --sdk-version 3.0.100-preview4-011223

次にAzure Pipelines に.NET Core SDK Installer タスクを追加します。 タスクの設定はこんな感じ。

f:id:iyemon018:20190422221050p:plain

YAML だとこんな感じ。

steps:
- task: DotNetCoreInstaller@0
  displayName: 'Use .NET Core runtime 3.0.0-preview4-27615-11'
  inputs:
    version: '3.0.100-preview4-011223'

この.NET Core のバージョンは以下のページを参照してください。 注意すべき点としてSDK とRuntime でバージョン番号の表記が若干異なります。 タスクのPackage to installの種別を確認しておきましょう。

github.com

なお、.NET Core 3.0 なのでVS 2019 にしないとビルドできませんのでご注意を。

あとはビルドをキューに登録して実行すればOKです。

(WPF).NET Framework で作ったアプリを.NET Core 3.0 Preview へ移行した

.NET Framework で作成していたWPF アプリを.NET Core 3.0 Preview へ移行してみました。 というのもxUnit.NET でテストコードを書いていたんですが、.NET Framework だとテストを実行するにはxunit.console.runner を実行するしかなく、Azure Pipelines でバージョンアップ時に書き換えるのがめんどいしカバレッジも自力で集計・レポート作成設定しないといけないのでなかなかに辛いのです。 で、せっかくVS 2019 Community もリリースされたので使ってみようと思いました。

なお、このエントリで試したことは2019年4月21日時点のものです。

.NET Framework版のプロジェクト構成

移行前のソリューション構成です。

f:id:iyemon018:20190421152109p:plain

それぞれのプロジェクト構成はこんな感じ。

プロジェクト名 フレームワーク 用途
Cartica.App .NET Framework 4.7.1 アプリのエントリポイント。起動時のexe。
Cartica.Controls .NET Framework 4.7.1 UI 関連の機能。
Cartica.Core .NET Standard 2.1 ビジネスロジックとか。
Cartica.Domain .NET Framework 4.7.1 ドメイン関連の機能とか値オブジェクトとか。
Cartica.Domain.Net .NET Framework 4.7.1 ドメイン関連のうちWEB API 使うものとか。
Cartica.Encryptions .NET Framework 4.7.1 暗号化、復号化関連。
Cartica.Core.Tests .NET Core 2.1 .NET Standard 用のテストプロジェクト。
Cartica.Tests .NET Framework 4.7.1 .NET Framework 用のテストプロジェクト。
Tests.Core .NET Standard 2.0 テストコードの汎用機能。

なお、今回移行対象に考えているのは"Cartica.App"プロジェクトです。

.NET Coreへの移行手順

まず、今回移行に伴い参考にした資料はこちらです。

docs.microsoft.com

下準備

  1. プロジェクトが.NET Core へ移行可能か検証する。 検証には.NET Portability Analyzer を使用します。 docs.microsoft.com
  2. .NET Core 3.0 Preview をインストールする。 .NET Core 3.0 Preview のインストールは以下から。 dotnet.microsoft.com
  3. Visual Studio 2019 をインストールする。 初期設定ではVS 2019 で.NET Core 3.0 Preview を使えないので、以下のページの「RC 版で .NET Core 3.0」にある通りに設定しましょう。 ufcpp.net

移行手順

  1. dotnet new wpfコマンドを使って.NET Core のWPF プロジェクトを作成する。
  2. 作成した.csproj ファイルの内容を.NET Framework の.csproj にコピペする。
  3. NuGet パッケージを参照しているのであれば、.csproj に記載する。packages.config ファイルとタグが若干違うので目Grep で書き換える。(ここめんどい)
  4. Properties/AssemblyInfo.csが未変更なら不要なので削除する。私の場合はInternalsVisibleTo使ってたので、そのコードだけ残して削除しました。
  5. NU1701の警告がめっちゃ出てくるので、.NET Framework 互換モード で警告を非表示にする。(ここはOSS の対応待ち or .NET Core 向けあるならそっち使う)

さて、ここまではよくブログなどに載せられている手順ですが、私のプロジェクト上では更に以下の手順を実施しました。 プロダクトによっては以下の手順は不要だと思います。

追加した移行手順

  1. ユニットテスト プロジェクトの参照を.NET Framework 用プロジェクトから.NET Core 側に移行した。
  2. System.Windows.Interactivity.dllを参照していたので、XamlBehaviors for WPF のNuGet パッケージを追加した。
    XAML に使用している場合、namespace はxmlns:interactions="http://schemas.microsoft.com/xaml/behaviors"に変更しておきます。xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"こっちはいらないので削除しておきましょう。
  3. 複数プロジェクトあったので、下位のプロジェクトから順にクリーン + リビルドを実施する。

これでビルドが成功し、実行すると動くようになりました。

移行後の.csproj

.NET Core 3.0 への移行で若干迷ったのが.csproj ファイルの編集なんですが、その理由がMS 公式リファレンスや個人ブログでは.csproj の中身が見えないのでどこに追記すればいいかわかんないんですよね。 なので、今回私が作成した.csproj ファイルはここに載せておきます。

タグの意味とかは移行手順の参考資料に記載しているのでそちらを御覧ください。

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <UseWPF>true</UseWPF>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <AssemblyName>Cartica.App</AssemblyName>
    <RootNamespace>Cartica.App</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="CommonServiceLocator" Version="2.0.4" />
    <PackageReference Include="LiveCharts" Version="0.9.7" NoWarn="NU1701" />
    <PackageReference Include="LiveCharts.Wpf" Version="0.9.7" NoWarn="NU1701" />
    <PackageReference Include="MaterialDesignColors" Version="1.1.1" NoWarn="NU1701" />
    <PackageReference Include="MaterialDesignThemes" Version="2.5.0.1205" NoWarn="NU1701" />
    <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.0.1" NoWarn="NU1701" />
    <PackageReference Include="Prism.Core" Version="7.1.0.431" />
    <PackageReference Include="Prism.Unity" Version="7.1.0.431" NoWarn="NU1701" />
    <PackageReference Include="Prism.Wpf" Version="7.1.0.431" NoWarn="NU1701" />
    <PackageReference Include="Unity.Abstractions" Version="3.3.1" />
    <PackageReference Include="Unity.Container" Version="5.8.11" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Cartica.Controls\Cartica.Controls.csproj" />
    <ProjectReference Include="..\Cartica.Core\Cartica.Core.csproj" />
    <ProjectReference Include="..\Cartica.Domain.Net\Cartica.Domain.Net.csproj" />
    <ProjectReference Include="..\Cartica.Domain\Cartica.Domain.csproj" />
    <ProjectReference Include="..\Cartica.Encryptions\Cartica.Encryptions.csproj" />
  </ItemGroup>

</Project>

できないこと

まだプレビュー版だからなのか、以下は対応できませんでした。

  1. .NET FrameworkWPF コントロールライブラリの.NET Core 3.0 対応

2. Azure Pipelines でVS 2019 Hosted で自動ビルド

2019年4月22日 追記

Azure Pipelines で.NET Core 3.0 Preview の自動ビルドは可能でした。 その手順を以下にまとめましたのでご確認ください。

iyemon018.hatenablog.com

ここまで追記

この辺は正式版がリリースされてからの話だと思うので楽しみに待ってましょう。

移行の感想

ぶっちゃけブログなどでは移行が簡単そうに書いていますが、それはWPF プロジェクトが1プロジェクトしかないときと考えたほうがいいでしょう。 WPF コントロールライブラリは.NET Core への移行が現時点では不可能なので使用している場合は無理に.NET Core へ移行する必要もないでしょう。

あと、Azure Pipelines もビルドできないので使用している方はご注意ください。

結論、 .NET Core 3.0 リリース早く来てくれ!!

ErgoDox EZ のキーキャップを変えてみた(TALP KEYBOARD)

以前、ErgoDox EZ のキーキャップを変えたのですが、そのときはDCS プロファイルだったたのでカラー バリエーションが少ない、海外でしか購入できないといった問題点がありました。 なので日本でキーキャップを購入できるところはないかなーと探していたところ、TALP KEYBAROD というサイトを見つけました。

talpkeyboard.stores.jp

カスタマイズした結果

先に購入したキーキャップを差し替えた私のErgoDox EZ をお見せしましょう。

f:id:iyemon018:20190420160152j:plain

自然界的には間違いなく毒持ちな配色となりました( ・`ω・´)+

(まぁ、変えたのは3ヶ月近く前のことなんですが…)

TALP KEYBOARDについて

主にメカニカルキーボードのキーキャップや自作キーボードパーツを提供されています。 DCS プロファイルのキーキャップはないのですが、DSA プロファイルであればカラーバリエーションが大変豊富です。 また、1.5u, 1.25u サイズやキーキャップのセット販売もあり見ているだけでポチってしまいそうなほどです。 Twitter もやっているそうなので、売り切れた場合でも再販の情報をいつでも見れます。

twitter.com

購入したキーキャプ

今回購入したキーキャップはこんな感じ。

f:id:iyemon018:20190420162020p:plain

全体的に写真で見るよりも実物のほうが若干明るい色のように見えます。 (モニタのせいかも?)

やっぱりパソコンを長時間使う職業柄、持ち物にはこだわりが強くなっていくのでちょっと気分を変えたいと言うときにお手軽な方法としてキーキャップを変えるというのはなかなかいい手段かと思います。 これを見たあなたもキーキャップ沼に入ってみてはいかがでしょうか?