Quantcast
Channel: かずきのBlog@hatena
Viewing all 1388 articles
Browse latest View live

Desktop Bridge のアプリの提出方法が変わったみたいですね

$
0
0

何処にも公式アナウンスが無さそうなのですが…。ドキュメントを総合的に見ると変わってるというのがわかるという。

まず、アプリケーションの機能のところに Restricted capabilities があります。

docs.microsoft.com

その中にこんな一文が

Restricted capability approval process
Previously, we required you to contact support to get approval to use a capability. We now allow you to provide this info in your Dev Center dashboard as part of the submission process.

前はサポートに問い合わせが必要だったけど ダッシュボードに特別な権限が必要な場合は入力できるようになったという感じですね。 実際に特別な権限を追加したパッケージをアップロードすると、申請の申請オプションに制限付き機能の項目がぽこっと現れます。

f:id:okazuki:20180521170833p:plain

スクリーンショットにもある通り、特別な権限の中の1つとして runFullTrust という Desktop Bridge を使用したアプリにくっついてくる権限も入ってるということなので、ダッシュボードから普通に提出できるようになりましたということですね。

う~ん、わかりにくい。


de:code 2018 で登壇してきました

$
0
0

de:code 2018 無事終わりました!!


最新 Windows 10 のデスクトップアプリ開発手法のセッションを担当させていただきました!!

世の中がクラウド!!AI!!Mixed Reality!!SPA!!とかしてるご時世にデスクトップアプリ!?しかもWindowsの!?というタイトルですが

速報値では NSAT が 170 個くらいあるブレイクアウトセッションの中で 26 番でした!ありがとうございます!!


因みに NSAT はアンケート結果から求められるセッションのスコアのつけかたの一つで 150 で普通くらいで 180 超えてすると凄い!!みたいな感じで 190 を超えてくるとヤバイくらい凄くて 200 点になると全員が最高の評価をしたということになる感じです。

セッション内容は Windows 10 のネイティブアプリ開発プラットフォームになる UWP を使うとメリットが出やすい機能ってなんだろう?そもそも例えセキュアでも不自由なプラットフォーム使うのって嫌だよな…というのを考えた結果 Project Rome を軸にした複数のデバイスが連携するタイプのアプリケーション開発において、WebでもなくWPFやWinFormsでもなくUWPが一番強い!!と思ったので、それをメインに伝えれたらなと思いました。

 

アンケートのコメントなどは、まだ見れない状態なのですがアンケートを集計した NSAT の速報が届いて良さそうな感じだったので安心しました。

 

本当にありがとうございました!れ

 

因みにセッションで使ったプログラムコードとかは GitHub に置いてあります。(DemoApp プロジェクトがデモで使用したものです。Android アプリは、rome フォルダの java のプロジェクトになります。(書いてる言語は kotlin です)

 

https://github.com/runceel/decode2018

de:code 2018 の「最新 Windows 10 に最適なデスクトップアプリ開発手法ご紹介」で伝えたかったこと

$
0
0

参加していただいた方ありがとうございました! セッション動画やスライドは順次公開されていくと思います。私はセッション中で使ったプログラムなどは GitHub に置いてありますのでご興味がおありでしたらご確認ください。

github.com

伝えたかったこと

一応セッションをするにあたって考えたことは Windows 10 のデスクトップアプリとは別のプラットフォームでやったほうが楽なことを無理やり UWP で!!というのは無理があると思うし、自分でも大いなる力が働かない限りは選択しないと思う…という考えがあって、じゃぁなんでデスクトップアプリなの?そして、その上で UWP を選ぶの??というのを考えていました。

マスターメンテナンスをしたいという要望に対してデスクトップアプリでやりましょう!!というのは配布とか考えると、ちょっとめんどくさいし、デスクトップアプリだとしても別にWPFで作った方が Windows 7 でも動くし Electron で作ったら macOS や Linux の人も使えるよ?となります。

そこに UWP をねじ込むのは誰も幸せにならない。せめて Windows 7 と 8 のサポートが完全に切れるまで UWP を選択するということは、メーカーはサポートしてるけど、このアプリは動かすことが出来ませんという OS が出来るということですよね。

じゃぁ、UWP まだ使うメリットないのでは?と思ったりしました。でもストアという配布の仕組みにのっかれるなら、UWP にした方がいいかもねって感じかなぁ…と。

そんなこんなで API 眺めてたら Project Rome という懐かしい文字をみつけました。 しかも SDK が preview とはいえ Android, iOS, MSGraph がある!出来ることは別マシンのアプリの起動や、自前サーバーとか用意しなくても別マシンのアプリとの通信ができるというもの。

これを使えば最近の Android や iOS にある「PCで続行」の機能が自分でも作れる! アプリのリモートでの起動はプロトコルでの起動だし、通信部分は AppService を使うということで UWP を想定してるっぽい。

色んなデバイスにまたがってシームレスに作業できるようなアプリを作るなら UWP が一番良さそうだなと思ったので、それを推すことに決めました。

ということで 1 つのデバイスに閉じた状態で完結するようなアプリであれば得意なもので作ればいいけど、もし複数のデバイスのアプリが連携して 1 つのことをやっていくようなアプリなら、それの Windows 上での役割を担うのは UWP が一番いいね!ってことを伝えたかったです。

そして幸いにも de:code のキーノートでも割とクロスデバイスに力入れてますというメッセージで次の Windows の大型アップデートで、こんな便利な機能が追加されます!!という感じだったので、実はそれと同じようなものは、すでに作ろうと思えば作れるよ!!ということを言えたのはラッキーでした。

まとめ

だらだらと書いてみましたが、Windows 10 になって追加される新しい機能の結構なものが UWP を想定しているので苦労をせずに新しい機能に対応できるというメリットが、既存の環境に縛られてるという呪縛を上回るときが早く来て欲しいなぁと思います。

因みに、WPFとかからでも Windows 10 API は叩けるのでやってやれないことはないです。.NET Core 3 や .NET Framework 4.8 からは、もっと Windows 10 API 叩きやすくなるらしいので、そうすると、もしかしたら UWP でやる必要無くなるかもしれませんが、モノが出てないので出たらまた見てみようという今日この頃でした。

ハッカソンで使い勝手の良さそうな Microsoft のサービス

$
0
0

ハッカソンではすごいスピードですごいものを作らないといけないので、結構既存サービスをうまく使って独自部分の実装に注力できるようにしておかないといけないというのがありますよね。

 

ということで、ハッカソンでパッと使えて割とすごいサービスをいくつか紹介したいと思います。

 

# QnA Maker

 

トップを飾るのは先日プレビューから一般公開になった QnA Maker です。

これは質問と回答の組みを登録しておくと、質問に対して回答を返してくれる API を提供してくれるものになります。

 

質問は完全一致してなくても大丈夫で、なんとなくそれっぽいものを返してくれるところがポイントです。

 

https://www.qnamaker.ai

 

なんとなく AI チックにやり取りしてくれる人や QnA 対応を自動化するときにとても強いです。

 

# Custom Vision API

こちらは画像をいい感じに判別してくれる API を作れます。

しかも、画像は自分で登録してタグづけしておくと学習させて API として公開できるので写真が何なのかというのを判別させる機能をさくっと作れるところが強いです。

 

しかも、最近は CoreML のようなモバイルアプリで使える学習済みモデルの出力とかにも対応してるので、クラウドで学習させてエクスポートしてローカルで学習結果を使うということもできます。強い。

 

そして、最近 preview で公開された Object Detection という機能は最高に強いです。

今までは1枚の画像を渡して1つの認識結果を返してくれるというものでした。Object Detection は、1枚の画像のどの部分に何があるのかということを返してくれます。

 

画像の左に猫がいて画像の右に納豆が置いてある!とかいうことが判別できるような API を作ることができます。

 

強い。

 

https://www.customvision.ai

 

# Face API

 

これは写真を食べて顔を検出してくれたりするやつです。前の2つが自分たちで学習させないといけないものでしたが、こちらはサービスをポチっと作った段階でほぼ使える感じです。(人の顔が誰のものか判別する API を使う場合は学習させないといけません)

 

ということで顔認証とかみたいなのがサクッとできますね。

過去に来た人を覚えておくようなシナリオなんかに使ったり、人が喜んでるのか?悲しんでるのか?といった感情に応じて対応を変えるようなものにも使えます。

 

https://azure.microsoft.com/ja-jp/services/cognitive-services/face/?v=18.05

 

# Bing Image Search

 

キーワードから画像を返してくれる API です。イメージ画像をさくっと返してくれるのでテキスト情報をなんとなく画像でわかりやすく示したいとかいうのに使えます。

 

私は英語レストランメニューを OCR して結果をこの API に投げ込んで英語のレストランのメニュー画像をとってきてメニューがどんな食べ物なのかというのを知るために使ったりしました。

 

使いようによっては面白いことに使えるのかなと思います。

 

https://azure.microsoft.com/ja-jp/services/cognitive-services/bing-image-search-api/

 

# Text Analytics

 

これはテキストをインプットとして解析結果を返してくれるものです。

テキストからキーワードを抽出したり、感情を返してくれたり、何語で書かれてるのか?とかも返してくれます。

 

たとえば入力された文章を食わせてキーワードを検出して、先ほど紹介した Bing Image Search に渡すと文章のイメージにあった画像を出してくれるといったこととかも実現できますね。

 

https://azure.microsoft.com/ja-jp/services/cognitive-services/text-analytics/

 

# まとめ

 

ということで、今回紹介したサービスは基本的に全部 Microsoft Cognitive Services という簡単に利用できる AI を使った Web API を簡単につくれるサービスの中のものです。

 

もし、ちょっとでも面白そうだな?って思ったら以下の URL から Cognitive Services のサイトに行けますので一度目を通しておくと何か作るときの引き出しを増やすという意味でいいかもしれません。

 

https://azure.microsoft.com/ja-jp/services/cognitive-services/

 

あと、Web API を作ることって凄く多いと思うのですが Azure Functions を使うと凄く簡単に Web API 作ったりできるので、まだ手に馴染む Serverless のプラットフォームをお持ちでないかたは見てみるといいかもしれません。

 

https://azure.microsoft.com/ja-jp/services/functions/

 

node.js, や C# で簡単にかけるようになってます。ちょっとしたものなら Web ブラウザだけで完結して作れます。本格的なものは Visual Studio Code + CLI ツール や Visual Studio を使っての開発になります。

 

私は、パッと何かやるときは Azure Functions で API を作って、そこから各種 Cognitive Services の API を叩いて結果をいい感じに組み合わせて返すものを作ってクライアントのアプリから呼ぶという形をとったりします。

 

ということで良いハッカソンライフを!!

 

 

 

 

 

 

 

 

 

 

2018/06/17 に Insider Dev Tour が品川で開催されます

$
0
0

結構力の入ってるっぽいイベントが 6/17 に品川で開催されます。

insiderdevtour.com

Windows 10 アプリ、Progressive Web Apps、Office 365、Microsoft Graph、機械学習、Mixed Reality、あと何かといったラインナップです。 とりあえずマイクロソフト関係テクノロジーで最近力入ってそうなものを全部突っ込んでみた感があります。

時間は 11:00-18:00 なので、ほぼ1日使ってがっつりやる感じですね。 マイクロソフト本社から人が来てキーノートをしゃべるみたいなので、キーノートは英語っぽいですがその他の部分は Microsoft MVP の人たちがしゃべるので日本語で安心して聞けます。

これだけ広い範囲のテクノロジーを1日で情報をキャッチアップ出来る機会というのは、あんまり無い気がするので、もしこの分野について興味があるかたは足を運んでみてください!

今風の開発環境を整えるぞ!!github に CircleCI に Jira だ!?→それ VSTS でも出来るよ!

$
0
0

タイトルのような組み合わせを構築して運用していい感じに回してる話しをよく聞きます。Jira のところが Redmine のケースや他のサービスを使ってるっていうパターンもありますね。Circle CI のところは自前 Jenkins とかみたいなケースもありますね! 私は Jenkins は太古のバージョン(Hudson から名前が変わった直後くらい)と Redmine を一時期使ったことがあるくらいなので、これから書く、これらのツール類についてのことは正しいことを書いてない可能性が高いです。間違えてたらコメントなどで是非最近の〇〇はこういうところが凄くいい!!って教えてください。

とりあえず言いたいのは「それ Visual Studio Team Services(VSTS) でも出来るよ!?」ということです。 別に今時点で運用がうまく回ってるものを無理に VSTS にしてほしいわけではなくて、これからこういう環境整えたいなという人が VSTS ってのもあるのか~って思ってもらえたら目的達成です!

Visual Studio Team Services

以下の機能を提供する SaaS です。

  • プライベート git リポジトリ
  • 自動ビルド
  • 自動でデプロイ
  • Wiki
  • カスタマイズ可能なタスク管理
  • 各種レポート機能
  • テスト

ということで、VSTS を使うとこれらの環境が全部使える状態が整います。強いのは開発者 5 人まで無料。開発しない人でタスクとか見れたらいいっていう人は、ここにカウントされないということです。 純粋にデベロッパーが 5 人まで無料です。

料金面の詳細については下記ページをご確認ください。

azure.microsoft.com

プライベート git リポジトリ

VSTS は 1 つのプロジェクトに対して複数個の git のリポジトリを持たせることが出来ます。

f:id:okazuki:20180601084605p:plain

このスクリーンショットでは、UWP book と Sources という 2 つのリポジトリを作ってます。 これ、地味に便利だと思うのですがどうでしょうか?

1 つの VSTS のアカウントに N 個のプロジェクトが作れて、プロジェクトごとに N 個のリポジトリが作れます。例えば共通機能とかを実装する人たちのリポジトリは別途用意しておいて適切なタイミングでリリース。各種個別機能を作る人達はリリースされたライブラリを参照して別リポジトリで開発とかいうことも出来ます。

リポジトリのブランチごとに色々なポリシーが設定できて、直接 push することを禁止して必ず pull request 経由で更新することとかというのが設定できます。pull request をマージするには最低何人のレビューが必要とか、必ず〇〇さんの承認が必要なこととか、特定のビルドが走ってエラーが無いこととか、どのタスクのための pull request なのかをきちんと設定しないとダメとか色々設定できます。これらを駆使することで例えば master ブランチには変なコードが入り込む可能性を減らすことが出来ます。

プライベートなライブラリ公開場所

VSTS には Package Management という機能があってライブラリを世界中には公開したくないけどパッケージマネージャー使ってインストールしたい!といった要望にこたえることが出来るようになっています。

docs.microsoft.com

nuget(.NET 向け)、maven(Java 系向け)、npm(言わずと知れた node.js)に対応しています。 先ほど書いたように、ある程度の大きなチーム単位でリポジトリをわけた場合にはビルドした結果のライブラリを参照して使うという形になると思うのですが、このときに、この Package Management を使うと世間のオープンな場所に置かずに自分たちだけのライブラリ置き場が出来て nuget、maven、npm を使ってインストールすることが出来るようになります。

VSTS には後で説明する自動ビルド機能とかもあるので、それと組み合わせて master ブランチに変更があったらビルドしてライブラリを更新するっていうことも出来ます。

自動ビルド・自動でデプロイ

VSTS には自動ビルドしてくれる機能があります。 これは VSTS のリポジトリに対してのビルド以外にも GitHub や SVN や GitHub Enterprise などの外部リポジトリに対してもビルドをすることが出来ます。

組み込みで .NET、Java(maven、Gradle、Ant)、Python、node.js(Grunt、Gulp)、Xcode(オンプレにビルドエージェントが必要、要はビルドを実行するマシンは自分たちで用意して VSTS からビルド時に使うように設定する) 、Go(Preview) などに対応しています。Docker にも対応してるみたい。

f:id:okazuki:20180601085904p:plain

ビルドの定義は、1 つ 1 つのタスクを組み合わせて定義できるので Ant でビルドしたあとに Visual Studio のビルドを走らせるとかいったことも出来るようになっています。

f:id:okazuki:20180601090400p:plain

やろうと思えば自分たちでタスク自体を作ることもできるので、頑張れば結構なことが出来ます。 まぁタスクを作る前に、任意のシェルスクリプトやバッチファイルを走らせるタスクがあるので、それでかりっとやると割と何でもできちゃいそうな雰囲気はあります。

このビルドの定義の中で、各種クラウドサービスにデプロイまでやることも出来ますが、リリースは偉い人の承認が必要だとかステージング環境にデプロイしたのちに問題がなかったら手動で本番環境に持っていくといった凝ったリリース方法をやるためにリリースは別機能としても提供されています。

f:id:okazuki:20180601090931p:plain

Wiki

普通に markdown で書ける Wiki もあります。 Wiki は git で clone してローカルで編集して push とかも出来ます。メモやドキュメント置き場として

カスタマイズ可能なタスク管理・レポート

Scrum、Agile などのいくつかの組み込みのタスク管理のテンプレートが提供されています。 イテレーションを作って、人を割り当てて、各々のキャパシティを割り当てて、フィーチャーを定義してフィーチャーをイテレーションに割り当てて、それぞれにタスクを割り当ててカンバン形式で見たり、タスクに対して任意のクエリを定義して自分たちが見たい方法で見たりとか色々できます。

そして、バーンダウンチャートを見たりダッシュボードに色々ぺたぺたはりつけてレポートちっくに仕立てたりといったことが出来ます。ここらへんは前にチーム開発じゃないけど個人用タスク管理として使ってみた!という記事書いたので見てみてください。

blog.okazuki.jp

テスト

これ使ったことないんです。 マニュアルテストとかロードテストとかに使えるみたいなんですがユニットテストで自動ビルドで回すくらいまでしかしたことがないのですが、これを使うとマニュアルテストとかロードテストとかいけるみたい。

docs.microsoft.com

まとめ

ということで VSTS の認知度が少しでも上がるとうれしいな!ということでした。

ちなみに、VSTS は全機能使わないといけないというわけではなく、一部機能だけ使って他は外部サービス使うとかもできます。リポジトリは GitHub だけどタスク管理とかは VSTS みたいなのも OK です。

ReactiveProperty v5.0.0 をリリースしました

$
0
0

一週間くらい前に公開された System.Reactive 4.0.0 に対応しました。 System.Reactive 4.0.0 が .NET Standard 2.0 になったので、それに合わせて ReactveProperty も .NET Standard 1.3 から 2.0 になりました。なので、.NET Framework だと 4.6.1 以降、UWP だと Fall Creators Update 以降への対応になります。

まぁ新しめのプラットフォームを使っていれば恐らく問題にはなりませんが PCL とか .NET Standard 1.x 系を使っている場合は引き続き ReactiveProperty 4.x 以下をご利用ください。

インストールはいつも通り nuget から!

www.nuget.org

Power Point で書式のコピペをしたい

$
0
0

Power Point で資料を作っていて「あそこと同じ書式に変更したい!!」と思うことってありますよね?

テキストの書式しかり、図形の書式しかり。

そんなときは書式のコピー元で Ctrl + Shift + C で書式をコピーできます。 そして書式のコピー先で Ctrl + Shift + V で貼付けできます。

とっても便利。

f:id:okazuki:20180604163156g:plain


nuget から依存関係を含めたライブラリを取ってくる方法

Windows 8.1 アプリから UWP へのアップグレード時の ApplicationData.Current.LocalFolder の中身

$
0
0

前準備

アプリ名を予約しておきます。 同じアプリに紐づけた Windows 8.1 アプリと UWP アプリを準備します。

試したこと

ローカルデータの保存場所

UWP やストアアプリでローカルデータを保存しておくための ApplicationData.Current.LocalFolder のパスが同じか確認します。 Windows 8.1 アプリを起動してパスを表示しました。

Windows 8.1 アプリの ApplicationData.Current.LocalFolder.Path の値
C:\Users\UserName\AppData\Local\Packages\45014okazuki.Win8ToUWPSample_r82gs1ecy8g7c\LocalState

次に同じコードを UWP でも動かしてみました。

UWP アプリの ApplicationData.Current.LocalFolder.Path の値
C:\Users\UserName\AppData\Local\Packages\45014okazuki.Win8ToUWPSample_r82gs1ecy8g7c\LocalState

同じですね!!

アップデート時の動作

上記フォルダは、アプリのアンインストールで消えた気がするので Win 8.1 アプリから UWP アプリに変わるタイミングでアンインストールされたら悲しいですよね。 ということでパッケージを作ってサイドローディングで試してみました。

  1. Windows 8.1 アプリをインストール
  2. Windows 8.1 アプリで LocalFolder にファイルを書き込み
  3. UWP アプリをインストール
  4. UWP アプリで LocalFolder のファイルを読み込み

結果はサイドローディングではファイルは消えずに引き継がれました。 やったね!

ストアも多分一緒でしょう。ちょちょっと試すには審査通過しないといけないからそこらへんがちょっと辛いですね。

まとめ

Windows 8.1 アプリから UWP にしてもローカルのファイルは消えないし、同じ場所を参照するのでデータ引継ぎは OK っぽい。

ReactiveProperty v5.1.1 をリリースしました

$
0
0

v5.1.0 は nuspec の定義間違えたので取り下げました。 機能としては、初期状態でバリデーションロジックが必ず実行されて INotifyDataErrorInfo インターフェースに対応している人たちから見るとエラーがある!っていう状態になっていたので、最初はバリデーションロジックを実行しないようにするフラグを追加しました。

具体的には ReactiveProperty 生成時に mode に IgnoreInitialValidationError を追加する感じです。こんな風に。

// new する場合new ReactiveProperty<string>(mode: ReactivePropertyMode.Default | ReactivePropertyMode.IgnoreInitialValidationError);

// ToReactiveProperty する場合
xxx.ToReactiveProperty(mode: ReactivePropertyMode.Default | ReactivePropertyMode.IgnoreInitialValidationError);

アップデートやインストールはいつも通り nuget からよろしくお願いします!

www.nuget.org

App.config に秘密の情報を入れたいときはどうする?

$
0
0

入れないのがいいんですけどね。ローカルで実行するときに、開発用のキー情報を入れることもあるでしょう。 でもリポジトリには入れたくないという感じ。

App.config を分割する

App.config を作って、こっちには当たり障りない情報を書きます。そして、appSettings タグに file 属性があるのでこいつに Secret.config とかって書いておきます。

<?xml version="1.0" encoding="utf-8"?><configuration><appSettings file="Secret.config"><add key="a"value="a"/></appSettings></configuration>

そして Secret.config ファイルを作ってこんな感じにします。プロパティでビルドアクションはコンテンツで常にコピーするようにしておきましょう。

<?xml version="1.0" encoding="utf-8"?><appSettings><add key="b"value="b" /></appSettings>

今回は b の値が秘密って感じですね。あとは Secret.config あたりを .gitignore あたりに追加して完成です。

このときに、ConfigurationManager.AppSettings["a"] も ConfigurationManager.AppSettings["b"] もマージされてるので、どっちの値も取れます。

めでたしめでたし。

まとめ

でもまぁ exe にまとめちゃったら何もしないとプレーンテキストだから残念な感じになりますね。 Azure WebJobs みたいにクラウドで動くプロセスでユーザーのもとに配られないものならありですかね。WebJobs ならポータル側でアプリケーション設定できるので完璧ですね。

App.config / Web.config に秘密の情報を入れたいときはどうする? その 1

$
0
0

入れないのがいいんですけどね。ローカルで実行するときに、開発用のキー情報を入れることもあるでしょう。 でもリポジトリには入れたくないという感じ。

App.config を分割する

App.config を作って、こっちには当たり障りない情報を書きます。そして、appSettings タグに file 属性があるのでこいつに Secret.config とかって書いておきます。

<?xml version="1.0" encoding="utf-8"?><configuration><appSettings file="Secret.config"><add key="a"value="a"/></appSettings></configuration>

そして Secret.config ファイルを作ってこんな感じにします。プロパティでビルドアクションはコンテンツで常にコピーするようにしておきましょう。

<?xml version="1.0" encoding="utf-8"?><appSettings><add key="b"value="b" /></appSettings>

今回は b の値が秘密って感じですね。あとは Secret.config あたりを .gitignore あたりに追加して完成です。

このときに、ConfigurationManager.AppSettings["a"] も ConfigurationManager.AppSettings["b"] もマージされてるので、どっちの値も取れます。

めでたしめでたし。

まとめ

でもまぁ exe にまとめちゃったら何もしないとプレーンテキストだから残念な感じになりますね。 Azure WebJobs みたいにクラウドで動くプロセスでユーザーのもとに配られないものならありですかね。WebJobs ならポータル側でアプリケーション設定できるので完璧ですね。

Google アシスタントアプリを開発する時に Fulfillment の先を C# で開発する方法(スマートスピーカーを遊びたおす会での LT 内容)

$
0
0

別に C# じゃなくても開発できるんですが個人的に一番好きな言語なので。 Fulfillment は決まった形の JSON でやり取りするだけの、ただの webhook なので POST を受け取る webhook が使えれば何でもいいです。

Azure のアカウントを作る

とりあえずそこそこの金額を無料で使えるので作りましょう。

azure.microsoft.com

あとは、このほかにもハンズオン系イベントとかでもバウチャーとか配られてるケースもあったり Visual Studio Subscription を持ってたりする人は特典として Microsoft Azure を開発目的で毎月数千円使える権利がついてたりします。https://my.visualstudio.comあたりから有効化してしまいましょう。

ちなみに無料で使えると書いてある製品の中の Azure Functions を今回使います。

f:id:okazuki:20180627181504p:plain

1 月 1000000 回のリクエストってことは 30 日で割ると 1 日あたり 33,333 回のリクエストが OK ってことみたいです。 33,333 回も Google Home と 1 日に対話するか?と言われるとしないと思うので無料の範囲でお試しが出来そうな感じですね。

因みに開発ツールの Visual Studio 2017 は Community Edition が個人利用や小規模企業や学習目的では無料で使えたりします。

visualstudio.microsoft.com

あと、IDE みたいな重いのは好きじゃない人は Visual Studio Code でも普通に開発できます。

Azure Functions を作ろう

Dialogflow で Fulfillment に設定するための Azure Functions を作りましょう。 Azure ポータル上で右上の + ボタンを押して新しいリソース(Azure 上に作るものは全部リソースって言います)を作りましょう。 Functions で検索すると Functions App というのが出てくるので選択します。

f:id:okazuki:20180627182538p:plain

Functions App を選択すると必要事項の入力になります。アプリ名が世界で一意になる必要がある点が注意点なくらいです。大体以下のような意味になります。

  • アプリ名:URL に使われる
  • リソースグループ:フォルダみたいなものの名前。同じリソースグループに入れてるリソースはまとめて削除とかできる。
  • ホスティングプラン:従量課金プランがサーバーレスっぽく動いてる時間に対して課金される。AppService Planは自分でコンピューターを確保するイメージ。従量課金でよさそう。
  • 場所:日本もある
  • Storage:Function App が裏で使ってるストレージの名前。名前はかぶらないように自動生成されてるのでそのままで問題なし
  • Application Insights:90日間アプリログを保存してくれるサービス。あると便利だけど日本で提供されてないので最寄の Southeast Asia あたりが無難

作成を開始すると各リソースのデプロイが始まります。画面上部のベルのマークを押すと通知で進捗を確認できます。作ったリソースへは画面左のリソースグループを選択して、自分が作ったときに入力したリソースグループ名を選択すると行けます。

f:id:okazuki:20180628100856p:plain

そうすると雷マークのアイコンがあるはずなので、それが Functions App の本体です。

f:id:okazuki:20180628101451p:plain

一応簡単に説明すると、ここにできてるものは以下のようなものです

  • ストレージアカウント:Function App が裏で使ってるストレージ
  • Application Insights:ログ保管所。ログの検索やアラートの設定なんかもできる。
  • App Service:これが Function App。App Service には Function App の他にも Web App, Logic App, API App なんかがある
  • App Service プラン:App Service をホストしてるサーバーのイメージ。今回作ったのは従量課金のタイプのサーバーで使った時間で課金。他にも一定の性能を確保するタイプのものもある。

では、ここに Function App を作っていきましょう。LT ではブラウザでぽちぽちと作りましたが個人的には本格的に開発するのに、この画面で開発するのはつらいと思ってるので ローカルでやります。

Visual Studio 2017 でも Visual Studio Code + CLI ツール でも出来ます。Azure Functions には 1.x 系と 2.x 系があるのですが 2.x はプレビューなので現時点では触らない方がいいと思います。バグ踏んでつまったりするとメンドクサイので入門には向かない。

とりあえず今回は Visual Studio Code でしてみたいと思います。

ここを見て 1.x の Azure Functions Core Tools を入れます。(Windows限定なので Mac とかでやる場合は必然的に 2.x になってしまいます)

docs.microsoft.com

Node がいるので入れたら npm でインストールです。

npm install -g azure-functions-core-tools

そして、Visual Studio Code の Azure Functions の拡張機能を入れます。

marketplace.visualstudio.com

入れたら以下の場所をクリックしてプロジェクトを作ります。

f:id:okazuki:20180628102707p:plain

ウィザードがはじまるので、フォルダと言語(C#)を選びます。テンプレートのインストールを求められたら 1.x を選びます。

作成が終わったら、またAzureアイコンをクリックしてFUNCTIONSのところにある雷マークを選択します。これで関数(今回は HTTP に対応して呼び出される関数)を作ります。

f:id:okazuki:20180628103516p:plain

HTTP Trigger を選んで関数名を入れます。とりあえず名前は DialofflowWebhook とかにしておきました。次に名前空間です。これは適当でいいですけど仕事でやるときは「会社名.プロダクト名」(例:Microsoft.Hogehoge)とかにしたりします。Authorization level は認証です。デフォルトの Function でいいでしょう。Function にしてると関数の URL のパラメーターに指定したキーを渡さないと呼べない状態になります。

インターネットに無防備でさらすわけじゃないので少し安心。 これでコードが出来上がります。

あとは、以下のドキュメントにあるような JSON をやり取りすれば OK っぽいです。

Dialogflow Webhook Format  |  Actions on Google  |  Google Developers

C# で JSON をデシリアライズしたらシリアライズする一般的な方法は JSON.NET (Newtonsorf.Json)というライブラリを使ってやることです。このライブラリは Microsoft の各種プロダクトでも使われてるのと、そもそも Functions App のプロジェクトを作ったら最初から入ってたりします。

その際にスクリプト言語みたいに、型は指定しないでカジュアルに解析する方法と、JSON を格納するためのクラスをあらかじめ定義しておいて、そこに流し込んだり、それを元に JSON を吐くといったことが出来ます。 コード補間の恩恵を受けたいので今回はクラスを定義しておこうと思います。

クラスの定義は、JSONがあればさくっとできます。私のおすすめは https://quicktype.ioを使うことです。

このページを開いて右上のボタンから実際の画面に行くと JSON を張り付けることができる場所が出てきます。ここに Dialogflow のドキュメントのサンプルの JSON を張り付けます。

f:id:okazuki:20180628105010p:plain

張り付けるとコードが生成されるので名前空間とかクラス名を適切なものに変更してからコピーしておきます。私はリクエストの名前空間を DialogflowWebhook.Requests にしてクラス名を DialogflowRequest にしました。レスポンスは名前空間を DialogflowWebhook.Responses にしてクラス名を DialogflowResponse にしました。

リクエストとレスポンスに対してC#のコードが生成できたらプロジェクトフォルダに拡張子 cs のファイルをリクエスト用とレスポンス用に作成して、そこに張り付けます。

あとは関数本体を作っていきます。

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using DialogflowWebhook.Requests;
using DialogflowWebhook.Responses;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

using ResponsePayload = DialogflowWebhook.Responses.Payload;

namespace DialogflowSample.Functions
{
    publicstaticclass DialogflowWebhook
    {
        [FunctionName("DialogflowWebhook")]
        publicstatic async Task<DialogflowResponse> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]DialogflowRequest req,
            TraceWriter log)
        {
            log.Info(req.QueryResult.Intent.DisplayName);
            if (req.QueryResult.Intent.DisplayName == "now")
            {
                var tst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
                var now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tst);
                return CreateResponse($"こんにちは!今は{now.Hour}時だよ!");
            }
            
            return CreateResponse("こんにちは!よくわからなかったよ!");
        }

        privatestatic DialogflowResponse CreateResponse(string text)
        {
            returnnew DialogflowResponse
            {
                Payload = new ResponsePayload
                {
                    Google = new Google
                    {
                        ExpectUserResponse = true,
                        RichResponse = new RichResponse
                        {
                            Items = new[]
                            {
                                new Item
                                {
                                    SimpleResponse = new SimpleResponse
                                    {
                                        TextToSpeech = text,
                                    }
                                }
                            }
                        }
                    }
                },
            };
        }
    }
}

今の時間を返しているだけです。 HttpTrigger の関数の特徴として引数に特定のクラスを指定していると自動的に body のリクエストの JSON をデシリアライズして入れてくれたり、レスポンスは関数の戻り値を自動で返してくれたりします。便利。

もっと細かく制御したいときは HttpRequestMessage や HttpResponseMessage クラスを使うことで色々設定できます。今回は規定の動作でいいのでこんな感じで。

発行して動作確認

クラウドに発行しましょう。Visual Studio Code の左側の Azure のアイコンを選択してさっき作った Azure Functions を右クリックして Deploy Function App を選択すると配備対象プロジェクトを選ぶように言われるので選んだらデプロイが始まります。

f:id:okazuki:20180628134051p:plain

デプロイが終わると Azure ポータル上で以下のように関数が表示されます。関数の URL の取得を押すと関数を呼ぶ駄目の URL が表示されるのでコピーしておきます。

f:id:okazuki:20180628134246p:plain

Dialogflow での作業

Dialogflow で適当にアプリを作って Fulfillment の先の URL に先ほど入手した Azure Functions で作成した関数の URL を入れます。

f:id:okazuki:20180628134757p:plain

あとは適当に Dialogflow でインテントを作りましょう。今回は Fulfillment に設定した webhook の中でインテントの now があることを期待してるので now インテントを作りました。

f:id:okazuki:20180628134529p:plain

このインテントでは Fulfillment を呼ぶように指定します。

f:id:okazuki:20180628134618p:plain

保存してテストしてみましょう。こんな感じで動いてくれるはずです。

f:id:okazuki:20180628140029p:plain

ローカルテストの方法

因みにクラウドにあげなくてもローカルでもテストできます。

Visual Studio Code で F5 を押すとローカルで実行します。あとは ngrok を使ってインターネット越しにアクセスできるようにして、その URL を Dialogflow の Fulfillment の URL に設定するだけです。

注意点は Azure Functions のエミュレーターがローカルからのアクセスしか認めてないので ngrok で起動するときに以下のように -host-header オプションを指定する必要がある点です。(下の例はポート番号 7071 ですが、実際には自分が起動した Azure Functions のエミュレーターのポート番号にあわせてください)

ngrok http 7071 -host-header="localhost:7071"

クラウドでのデバッグ

Visual Studio 2017 を使ってるとクラウドエクスプローラーというビューから Functions App のリストが見れるのですが右クリックしてデバッガをアタッチってやるとクラウドで動いてるものに対してデバッガがアタッチできます。これは結構強いと思う。 デバッグビルドでアップロードしてないとダメだったかな?

Application Insights

ログですね。Function App 作るときに一緒に作られた Application Insights を開くと色々見れます。 Application Insights を開いてとりあえず検索を選択して出てきた画面で検索するのが一番とっつきやすいと思います。関数の引数にわたって来てる TraceWriter に対して Info とかのメソッドでログをはいてると、ここに表示されます。

f:id:okazuki:20180628141128p:plain

その他にはライブメトリックスストリームとかも面白いです。リアルタイムでアクセスがあるかとか出力されてるログが確認できるので。

f:id:okazuki:20180628141304p:plain

App.config / Web.config に秘密の情報を入れたいときはどうする? その 2

$
0
0

blog.okazuki.jp

さて、時代はクラウドですね。 ということでクラウド使う場合はどうなの?っていうケースです。

ASP.NET MVC では Web.config に設定を書きます。 開発中はローカルにあるエミュレーターとかを使うという感じにしておけば Web.config にはとりあえず開発ローカルエミュレーターとかに繋ぐために情報などを入れておけばいいでしょう。

こんな感じで。

<?xml version="1.0" encoding="utf-8"?><configuration><appSettings><add key="webpages:Version"value="3.0.0.0"/><add key="webpages:Enabled"value="false"/><add key="ClientValidationEnabled"value="true"/><add key="UnobtrusiveJavaScriptEnabled"value="true"/><add key="Secret"value="ローカルの秘密情報だよ!"/></appSettings><!-- 省略 -->

もし、この情報すらリポジトリに入れたくない場合は、その1で紹介した方法で入れないようにすればいいでしょう。 読み取り方はいつも通り ConfigurationManager になります。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SecretSample.Controllers
{
    publicclass HomeController : Controller
    {
        // GET: Homepublic ActionResult Index()
        {
            ViewBag.Secret = ConfigurationManager.AppSettings["Secret"];
            return View();
        }
    }
}

本筋とは関係ないですが、cshtml 側で以下のように表示するようにしました。

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2><p>@ViewBag.Secret</p>

実行すると以下のような感じです。

f:id:okazuki:20180629170635p:plain

ここまでは問題ないでしょう。

本番環境ではどうする?

クラウドにデプロイしたらどうなるか?というところですが Microsoft Azure の App Service 系のサービスには「アプリケーション設定」という項目があって、そこに Web.config で設定している AppSettings や ConnectionStrings が指定可能です。

f:id:okazuki:20180629171838p:plain

おそらくちゃんとやるなら、どこかの自動ビルドの仕組みからデプロイしてると思うので .gitignore とかに指定してれば変なファイルがもぐりこむこともありません。

完璧!しかも config ファイルに書くよりもこっちのほうが優先されます。

f:id:okazuki:20180629172149p:plain

つづく

次はもっと秘密にしたい情報についてどうするかということを書きたいと思います。


Reactive Extensions とか知らない人向けの ReactiveProperty のはじめかた その 2

$
0
0

blog.okazuki.jp

はじめに

最初の記事を受けて使い始めてきた人向けのちょっと Rx っぽい使い方を紹介します。

ReactiveProperty 値を加工して代入しているケース

ReactiveProperty に値を代入するケースがあると思います。例えば以下のような感じですね。

public ReactiveProperty<string> A { get; } = new ReactiveProperty<string>();

public ReactiveProperty<string> B { get; } = new ReactiveProperty<string>();


publicコンストラクタ()
{
   A.Subscribe(x => B.Value = $"Value is {x}");
}

プロパティ A の値が変わったら値を加工してプロパティ B に代入するという流れです。上記のようなコードでも動きますが以下のように書くと Rx っぽくなります。

// using System.Reactive.Linq;public ReactiveProperty<string> A { get; } = new ReactiveProperty<string>();
public ReactiveProperty<string> B { get; } // B はコンストラクタで初期化するpublicコンストラクタ()
{
  B = A.Select(x => $"Value is {x}") // 加工して
    .ToReactiveProperty(); // 流れてきた値を保持するための ReactiveProperty にする
}

これで同じ意味になります。

読み取り専用?

因みに上記のケースでは B は A の値が変わったら自動的に更新されることが期待されてるので、大体はそれ以外のケースで書き換わると嫌なことが多いと思います。 そういうときは ToReadOnlyReactiveProperty か ToReadOnlyReactivePropertySlim が使えます。最初のが自動的に UI スレッドで PropertyChanged イベントを発行してくれるもので後者は、そういったお世話はしてくれないものになります。

早いのは Slim のほうです。

ということでこんな感じになります。

// using System.Reactive.Linq;public ReactiveProperty<string> A { get; } = new ReactiveProperty<string>();
public ReadOnlyReactivePropertySlim<string> B { get; } // B はコンストラクタで初期化するpublicコンストラクタ()
{
  B = A.Select(x => $"Value is {x}") // 加工して
    .ToReadOnlyReactivePropertySlim(); // 流れてきた値を保持するための ReadOnlyReactivePropertySlim にする
}

フィルタリングして値を変更

いやいや、単純に値を加工して代入するんじゃなくてフィルタリングしたりするんですよというケース。例えば以下のような感じ。

public ReactiveProperty<string> A { get; } = new ReactiveProperty<string>();

public ReactiveProperty<string> B { get; } = new ReactiveProperty<string>();


publicコンストラクタ()
{
   A.Subscribe(x => 
  {
    if (x == null) { return; }
    return B.Value = $"Value is {x}"
  });
}

まさにそれ LINQ で出来るよ!案件です。

// using System.Reactive.Linq;public ReactiveProperty<string> A { get; } = new ReactiveProperty<string>();

public ReadOnlyReactivePropertySlim<string> B { get; } 

publicコンストラクタ()
{
  B = A.Where(x => x != null)
    .Select(x => $"Value is {x}")
    .ToReadOnlyReactivePropertySlim();
}

ばっちりですね。

複数のプロパティを見てる

いやいや、単一プロパティの値を加工してるんじゃなくて複数プロパティの値を見てやってるんですよ!というケース。

public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReactiveProperty<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();
    FullName = new ReactiveProperty<string>();

    FirstName.Subscribe(_ => SetFullName());
    LastName.Subscribe(_ => SetFullName());
}

publicvoid SetFullName()
{
  FullName.Value = $"{FirstName.Value} {LastName.Value}";
}

これは前記事で案内した CombineLatest の出番ですね。

// using System.Reactive.Linq;public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReadOnlyReactivePropertySlim<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();

    FullName = Observable.CombineLatest(
        FirstName,
        LastName,
        (firstName, lastName) => $"{firstName} {lastName}")
        .ToReadOnlyReactivePropertySlim();
}

いやいや、フィルタリングとかもしてるんですよ?とかもありますね。例えば

public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReactiveProperty<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();
    FullName = new ReactiveProperty<string>();

    FirstName.Subscribe(_ => SetFullName());
    LastName.Subscribe(_ => SetFullName());
}

publicvoid SetFullName()
{
  if (string.IsNullOrWhiteSpace(FirstName.Value) || string.IsNullOrWhiteSpace(LastName.Value)) 
  {
    return;
  }
  FullName.Value = $"{FirstName.Value} {LastName.Value}";
}

これはこんな感じ。

// using System.Reactive.Linq;public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReadOnlyReactivePropertySlim<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();

    FullName = Observable.CombineLatest(
        FirstName,
        LastName,
        (firstName, lastName) => (firstName: firstName, lastName: lastName))
        .Where(x => !string.IsNullOrWhiteSpace(x.firstName) && !string.IsNullOrWhiteSpace(x.lastName))
        .Select(x => $"{x.firstName} {x.lastName}")
        .ToReadOnlyReactivePropertySlim();
}

そもそもダメだったらダメって感じにしたいときのケース。

public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReactiveProperty<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();
    FullName = new ReactiveProperty<string>();

    FirstName.Subscribe(_ => SetFullName());
    LastName.Subscribe(_ => SetFullName());
}

publicvoid SetFullName()
{
  if (string.IsNullOrWhiteSpace(FirstName.Value) || string.IsNullOrWhiteSpace(LastName.Value)) 
  {
    FullName.Value = "Invalid";
    return;
  }
  FullName.Value = $"{FirstName.Value} {LastName.Value}";
}

これは、いろんなやり方がありますがダメな時の処理の流れと OK な時の処理の流れを別立てで考えると…

// using System.Reactive.Linq;public ReactiveProperty<string> FirstName { get; }
public ReactiveProperty<string> LastName { get; }

public ReadOnlyReactivePropertySlim<string> FullName { get; }

public MainWindowViewModel()
{
    FirstName = new ReactiveProperty<string>();
    LastName = new ReactiveProperty<string>();

    var nameChanged = Observable.CombineLatest(
        FirstName,
        LastName,
        (firstName, lastName) => (firstName: firstName, lastName: lastName));

    var valid = nameChanged.Where(x => !string.IsNullOrWhiteSpace(x.firstName) && !string.IsNullOrWhiteSpace(x.lastName))
        .Select(x => $"{x.firstName} {x.lastName}");

    var invalid = nameChanged.Where(x => string.IsNullOrWhiteSpace(x.firstName) || string.IsNullOrWhiteSpace(x.lastName))
        .Select(_ => "Invalid");

    FullName = Observable.Merge(valid, invalid)
        .ToReadOnlyReactivePropertySlim();
}

こんな感じかなぁ。ただ、入力にエラーがあるかどうかとかはバリデーションとかを使って書いた方がすっきりしますね。

// using System.Reactive.Linq;// using Reactive.Bindings.Extensions;
[Required(ErrorMessage = "required")]
public ReactiveProperty<string> FirstName { get; }
[Required(ErrorMessage = "required")]
public ReactiveProperty<string> LastName { get; }

public ReadOnlyReactivePropertySlim<string> FullName { get; }

publicコンストラクタ()
{
    FirstName = new ReactiveProperty<string>()
        .SetValidateAttribute(() => FirstName);
    LastName = new ReactiveProperty<string>()
        .SetValidateAttribute(() => LastName);

    var isValidInput = new[] 
        {
            // Inverse は Select(x => !x) と同じ// つまりエラーが無い時に true になる
            FirstName.ObserveHasErrors.Inverse(),
            LastName.ObserveHasErrors.Inverse()
        }
        // 全てが true なら true になる。 CombineLatest(x => x.All(y => y)) のショートカット
        .CombineLatestValuesAreAllTrue()
        // つまりエラーが無い時 true になる ReactiveProperty の出来上がり
        .ToReadOnlyReactivePropertySlim();

    // FirstName と LastName と エラーの有無を見て FullName の値を加工
    FullName = Observable.CombineLatest(
        FirstName,
        LastName,
        isValidInput,
        (firstName, lastName, valid) => valid ? $"{firstName} {lastName}" : "Invalid")
        .ToReadOnlyReactivePropertySlim();
}

なんか LINQ 書いてる気がしてきますね。

まとめ

途中から、これはちょっとわからん…ってなっても問題ありません。 わかる範囲で使えばおk。

でも、わかろうとする努力は惜しんではいけない気がします。理解の幅がひろがればひろがるほど表現の幅が広がりますしね。

あと、チームでやるときはわからない人合わせるか、わからない人に対してある程度教育コストを払ってある程度理解してもらうか、腹をくくってめっちゃ教育コストを払ってフル機能を使うかの判断が入ると思うのでバランス感覚大事です。

Azure Functions の Durable Functions を使って恋人を作ろう

$
0
0

Firebase って使うと色々な効能があるというのを見かけたんです。

じゃぁ Azure Functions を使ってこれらのメリットのどれか実現できないか!?と思ったので作ってみました。とりあえずモテるというやつを実現してみましょう!

恋人を作るには告白して返事をもらわないといけない

そういうワークフローを回せば OK ですね! Azure Functions の中でも特にイケてる機能に Durable Functions というのがあります。

docs.microsoft.com

この Durable Functions には人の承認が入るワークフローを処理するための機能があります。 外部イベントがそれです。

docs.microsoft.com

以下のようにコードを書くだけで、Approval という外部イベントが来るまで、そこで処理が止まったような動きになります。 実際には処理が止まるわけではなく、賢く何度も再実行されてイベントが来てなかったらそこで終わるみたいな動きになってるみたいなので、外部イベント待ってる間コンピューターを占有して課金対象になるということはありません。

// Approval というイベントが来るまで待つみたいな動きをする
var approved = await context.WaitForExternalEvent<bool>("Approval");

そして、別のところでこんな風にイベントを発火できます。

await client.RaiseEventAsync(instanceId, "Approval", approved);

ということで、チャットで告白したい相手のメールアドレスを伝えるとラブレターをメールで送信して相手から OK/NG の返事がきたら返答をくれるチャットボットを作ってみました。 告白のワークフローは Azure Functions の Durable Functions を使ってチャットボットは Azure Functions で Bot Builder SDK を使って作ってみました。

Slack に繋いで動かしてみるとこんな感じです。

f:id:okazuki:20180707001247p:plain

ここまでやると、入力したメールアドレスの先にこんなメールが飛びます。

f:id:okazuki:20180707001403p:plain

このメールのリンクをクリックすることで Azure Functions の関数が呼ばれて、その中で RaiseEventAsync が呼び出されて WaitForExternalEvent で待ってたところの処理が先に進むようにしています。

Slack 側にこんな風に通知が来ます!!

f:id:okazuki:20180707011358p:plain

f:id:okazuki:20180707012445p:plain

やったね!これで Slack や Skype とかのチャットからメアドを知ってる人相手にラブレターが送れますね!

まとめ

Azure Functions の Durable Functions を使うと人の承認が必要なワークフローのような処理を簡単に直感的に書くことが出来ますね!凄い。

コードはここにあげておきました。

github.com

Azure Functions v2 で MSDeploy 時にファイルがロックされてるエラーが出る

$
0
0

ぼちぼち Azure Functions v2 を使い始めてみよう(まだ preview だけど)と思ったら Visual Studio からの再デプロイに失敗しちゃう…。

DLL がロックされてるらしくて Function App を停止してもダメでした。回避方法はアプリケーション設定に以下の値を追加する。

MSDEPLOY_RENAME_LOCKED_FILES=1

ポータルでこんな感じで OK

f:id:okazuki:20180714061741p:plain

参考

stackoverflow.com

Prism.Forms 7.1 の新しい XAML でのナビゲーション定義

$
0
0

Xamarin.Forms 向けの Prism の 7.1 (2018/07/17 時点で preview)で便利な機能が追加されてたので紹介します。

ドキュメントページはこちら。

Xaml Navigation | Prism

これが無い時はどうしてた?

画面遷移するだけの DelegateCommand 型のプロパティを定義して CommandParameter で遷移先を指定したりするようなことをしてました。

こんな感じですね。

private DelegateCommand<string> _navigateCommand;

public DelegateCommand<string> NavigateCommand => _navigateCommand ?? (_navaigateCommand = new DelegateCommand<string>(NavigateExecute);

privatevoid NavigateExecute(string page)
{
  await _navigationService.NavigateAsync(page);
}

XAML 側でこんな感じに使います。

<Button Text="Nav"Command="{Binding NavigateCommand}"CommandParameter="NextPage" />

XAML でのナビゲーション定義を使うとどうなる?

これを使うと画面遷移するだけでよければ ViewModel にコマンドを定義しなくてもよくなります。 しかも、パラメーターも渡せるし画面遷移可能かどうかの条件も指定できるので結構なケースで XAML だけで完結しそうです。

使い方は以下のような感じです。

  • xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms"の名前空間を定義
  • {prism:NavigateTo '遷移先'}
  • 戻るときは {prism:GoBack}で OK
  • 以下はオプション
    • CommandParameter に渡したい情報を設定可能
      • prism:NavigationParametersタグを CommandParameter に指定することで複数個のパラメータも指定可能
    • prism:Navigation.CanNavigate添付プロパティに画面遷移の実行可否の条件を指定可能

使ってみよう

例えば以下のような MainPage.xaml を用意します。

<?xml version="1.0" encoding="utf-8"?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms"x:Class="NewNavLab.Views.MainPage"Title="{Binding Title}"><StackLayout HorizontalOptions="CenterAndExpand"VerticalOptions="CenterAndExpand"><Label Text="Welcome to Xamarin Forms and Prism!" /><Switch x:Name="canGoBack" /><Entry x:Name="param" /><Button Text="Navigate"prism:Navigation.CanNavigate="{Binding IsToggled, Source={x:Reference canGoBack}}"Command="{prism:NavigateTo 'NextPage'}"CommandParameter="{Binding Text, Source={x:Reference param}}" /></StackLayout></ContentPage>

Switch で画面遷移の可否、Entry で次のページに渡すパラメーターを指定しています。

NextPage は以下のような感じです。

<?xml version="1.0" encoding="utf-8"?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:prism="clr-namespace:Prism.Navigation.Xaml;assembly=Prism.Forms"Title="{Binding Title}"x:Class="NewNavLab.Views.NextPage"><StackLayout><Label Text="NextPage" /><Label Text="{Binding Text}" /><Button Text="Back"Command="{prism:GoBack}" /></StackLayout></ContentPage>
using Prism.Navigation;

namespace NewNavLab.ViewModels
{
    publicclass NextPageViewModel : ViewModelBase
    {
        privatestring _text;
        publicstring Text
        {
            get { return _text; }
            set { SetProperty(ref _text, value); }
        }

        public NextPageViewModel(INavigationService navigationService) : base(navigationService)
        {
        }

        publicoverridevoid OnNavigatedTo(INavigationParameters parameters)
        {
            if (parameters.TryGetValue(KnownNavigationParameters.XamlParam, outstring text))
            {
                Text = text;
            }
        }
    }
}

XAML で定義したナビゲーションのパラメーターはデフォルトで KnownNavigationParameters.XamlParamという名前で渡ってくるので、それで取得できます。

実行すると以下のような感じで動きます。

f:id:okazuki:20180717114106g:plain

コードは以下に置いてあります。

github.com

他の人のアカウントに提出する用に UWP アプリをビルドする方法

$
0
0

一番簡単なのは、ストアのダッシュボードから Azure AD を紐づけて、そこに開発者ロールで追加してもらえば、普通に Visual Studio からストア向けパッケージ作れるんですが、それが出来ないケースでの方法です。

アカウント ユーザーの管理 - UWP app developer | Microsoft Docs

他の人のアカウントに提出する appxupload の作り方

まず、アプリに関する情報をもらいます。ストアのダッシュボードの該当アプリのアプリ ID の項目に全部詰まってます。

f:id:okazuki:20180731132815p:plain

1. 証明書の作成

プロジェクトを Visual Studio で開いて Package.appxmanifest を開きます。 そしてパッケージ化タブで、発行者のところにある証明書の選択ボタンを押します。そして左下にあるドロップダウンからテスト証明書の作成を選択します。

f:id:okazuki:20180731134117p:plain

発行者共通名のところに、アプリの情報にある「パッケージ/ID/発行元」の「CN=XXXXXXXXXXXXXXXXXXXXXX」にある「XXXXXXXXXXXXXXXXXXXXXX」の値を入力します。CN=は入れないでください。

f:id:okazuki:20180731134155p:plain

2. パッケージ化タブの情報の変更

パッケージ化タブのパッケージ名、パッケージ表示名、発行者名をアプリの情報の「パッケージ/ID/名前」「ページの左上にあるアプリの名前」「パッケージ/プロパティ/発行元表示名」に変更します。 バージョン番号はリリースするバージョン番号に合わせて編集してください。

3. ストア用パッケージを生成するように設定を変更する

この後の手順でストア用パッケージを生成するように設定ファイルを手で編集します。

まず、Visual Studio でプロジェクトを右クリックしてアンロードします。 アンロードの仕方がわからない場合は Visual Studio 自体を閉じておくと安全です。

そして、ソリューションのフォルダに移動して プロジェクト名.csproj.user という名前のファイルをテキストエディタで開きます。 PropertyGroupタグの子要素として以下の値を追加してください。

<UapAppxPackageBuildMode>StoreUpload</UapAppxPackageBuildMode>

4. パッケージの作成

アプリパッケージの作成画面を開きます。

f:id:okazuki:20180731134935p:plain

そして、サイドロード用のパッケージを作成します。を選択して次へを選択します。

f:id:okazuki:20180731135242p:plain

ソリューション構成を Release にしたうえで作成ボタンを選択します。

f:id:okazuki:20180731135423p:plain

5. パッケージの確認

プロジェクトフォルダの下の AppPackages フォルダの中に appxupload という拡張しのファイルが作成されます。 これをストアのアカウントを持っている人に渡してアップロードすれば完了です。

Viewing all 1388 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>