Quantcast
Channel: 銀の光と碧い空
Viewing all 278 articles
Browse latest View live

ASP.NET MVC 5実践プログラミングを読みました

$
0
0

先日、ASP.NET MVC 5実践プログラミングをいただいたので(かなり時間はかかりましたが)読んでみました。

ASP.NET MVC 5実践プログラミング

ASP.NET MVC 5実践プログラミング

読もうと思ったきっかけ

会社で開発しているものはASP.NET MVC5 アプリでコードも見ていますが、実際自分の手を動かすことはあまりなく*1、なんとなくしかMVC5での開発をやったことがないので、一度整理する意味もこめて読みました。

全体的には非常にわかりやすい構成になっているのと、実際の開発にすぐ使えるような内容が書かれているなと感じました。

全体的な構成

導入・基本・応用の大きく3つに分かれていて、まず導入編で開発環境を作ってMVC 5でアプリを作ります。MVC5での開発の全体像をまず把握することができます。 その後、基本編でビュー・モデル・コントローラーの開発の詳細が説明されています。 最後の応用編では、ルーティングであったり、クライアントサイド開発(バンドル&ミニフィケーション・jQuery・AJAXなど)、認証、Azureの利用といったあたりに触れられています。

MVC の説明とEntity Framework

一般的にMVCとは、となると大上段に構えた説明になりがちですが、この本ではASP.NET MVCの本質はView-Controllerであると言ってもよい、ASP.NET MVC にモデルに相当する機能は含まれていない、書いてあります。これは、モデルが単なるデータクラスにとどまるものではないということを意味しています。このあたりまで踏み込んで説明しているのはわかりやすいと思います。

となるとモデルには、ビジネスロジックやデータアクセスを記述することになりますが、ビジネスロジックはアプリケーションによって異なるため、データアクセスについて説明しています。特にMicrosoft Recommendedなライブラリ「Entity Framework」についてもページを割いて説明しているので、はじめてデータベースを使ったWebアプリを MVC5 で開発する場合でも参考にできるのではないかと思います。*2

具体的な操作手順

C# による開発のメリットは、VisualStudioというIDEがもたらしている部分が大きいです。これは ASP.NET MVC の開発でも同じだと思っています。この本では開発手順として VisualStudio の操作手順も丁寧に説明してあります。 また、具体例を挙げると、 「Viewを作成するときには、先にControllerに

return View();

とあったら、この"View"の部分からVSを操作してViewを作成できます」 というように、実際の開発でもこういう手順で動かすだろうな、という手順が載せてあるのも非常にわかりやすかったです。

網羅的な説明とその先への指針

たとえば、Viewの開発ではビューヘルパーを使うことがありますが、あらかじめ用意されているヘルパーメソッドについての説明も書かれています。また、さらにその先として、独自ビューヘルパーの定義の仕方も説明されています。このあたり、なんとなく知っていて使っているという状態であると、いったん自分の知識を整理することができ、その先に進む方針もわかりやすいのではと思います。

周辺技術への入口となる応用編

最近のWeb技術は多様化していることもあり、MVC5のコア機能だけでは開発が追い付かないことがあります。この本に載っているところで言えば、

  • JavaScript/CSS のロード時間を削減するためのバンドル・ミニフィケーション
  • クライアントサイドの開発で利用するjQuery
  • 認証機能を実装するときに利用する ASP.NET Identity
  • Azure Web Sitesを利用した迅速なアプリの展開

といったところです。これらについても説明されているため、このようなライブラリ・サービスがあってこういうことに使える、といったことを理解することができます。

まとめ

全体を網羅的に説明しつつ、詳細な機能への入口となる説明を載せている、といったのがこの本を通しての感想です。ですので、

  • なんとなく ASP.NET を知っている
  • JavaやRuby on Rails といった他言語・フレームワークでWeb開発をしたことがあって、C# の基本的機能は知っている

といった方には向いていると思います。個人的には一度全体を通して読んで、自分の知識を整理し、あとは実際の開発をしながら分からないところを読みなおす、という使い方をしています。

逆に、ASP.NET を使いこんでいてコアな部分の辞書的に使いたい、という目的だと説明が長すぎると感じるかもしれません。

*1:MVCのバージョンあげたり、MVCとあまり関係ない部分を触ったりはありますが

*2:ただ、個人的には EntityFramework (のような重厚なORマッパー) は嫌いなので使わないのですが...


第7回中心会議で C# 6.0 を中心にお話ししてきました #devchu

$
0
0

で、話した資料になります。

20141129-dotNet2015

Visual Studio 2015 で強化されたリファクタリング機能について

$
0
0

Visual Studio 2015 の1日目です。

Visual Studio Advent Calendar 2014 - Qiita

一発目なので最新の機能の中からデバッグ関連の機能を軽く紹介したいと思います。

リネーム機能

変数名のリネーム機能が強化されました。変数名を変更したあとに、使用しているかしょをまとめて変更する機能はありましたが、今回はプレビュー機能もついて強化されました。 変数にフォーカスを置いて、Ctrl+R,Ctrl+R (CtrlとRの同時押しを2回)すると、この機能が呼びだされます。

f:id:tanaka733:20141130175956p:plain

f:id:tanaka733:20141130180006p:plain

強化された点は、変更対象がリアルタイムに変更に追随すること、文字列リテラルやコメント中の文字列もオプションで変更対象に含めることができる点です。

メソッドの抽出

抽出したいコードを選択して、 Ctrl+R,Ctrl+Mでメソッドが抽出されます。抽出後は上のリネーム機能状態になりメソッド名を入力できます。

f:id:tanaka733:20141130183719p:plain

f:id:tanaka733:20141130183728p:plain

クイックアクション

選択して、Ctrl+.を押すとクイックアクションと呼ばれる機能が呼びだせます。ReSharper の Alt+Enterに似た感じの機能です。

たとえばハードコーディングした内容を定数化できたり、

f:id:tanaka733:20141130185911p:plain

メソッドチェーンをローカル変数に抽出したり、

f:id:tanaka733:20141130185945p:plain

逆に複数のメソッドをインライン化したり

f:id:tanaka733:20141130185959p:plain

といったことができます。

Roslynによるコードリファクタツールの追加

拡張できる、という意味ではこれがある意味最強の機能追加かもしれません。Roslynが解析APIを公開したことで、自分でコードリファクタの機能を作成・展開し、利用することができます。詳細はのいえせんせーのブログがわかりやすいです。

neue cc - VS2015のRoslynでCode Analyzerを自作する(ついでにUnityコードも解析する)

といった感じで、あっさりですが、わりと便利な機能が追加されたのではないでしょうか。また、リファクタリング機能に限らず全体的にモーダルダイアログを表示する、ということが少なくなった印象があります。好き嫌いはありそうですが、個人的には好みな向きな変更です。

CloudWach (Windows版)に.NET アプリから独自のイベントログとパフォーマンスカウンタを送信する方法

$
0
0

このエントリは、AWS Advent Calendar 3日目の記事です

AWS Advent Calendar 2014 - Qiita

先日出た CloudWatch にWindows Serverからイベントログやパフォーマンスカウンタの値を送信できる機能ですが、これを使うことによって、アプリケーションから独自のイベントログやパフォーマンスカウンタを定義し送信することができます。ただ、若干面倒なところがあるのでブログにまとめてみました。

事前準備

Ec2Configは念の為最新の2.2.11 を使っています*1。Windows Serverは最新の Windows Server 2012 R2。アプリケーションはC# で書かれた.NET アプリを想定していますが、対応するWindowsのAPIを利用すれば他言語/Frameworkでも問題ないと思います。

イベントログを送る

独自のイベントログを定義する(理由編)

AWSのドキュメントの手順のところにあるのですが、Ec2Configが送信するイベントログは、イベントビューアー上で確認できる状態になっていないといけません。一方、Windows においてイベントビューアーに表示されるようなイベントログを定義するのは割と面倒です。というのも、最近のWindowsでは、イベントログとは別のETW(Event Tracing for Windows)という仕組みがが使われるようになっています。このETWは、.NET標準のAPIが用意されているため、C#/VBといった managed なコードから利用することが簡単になっている反面、標準の機能ではイベントビューアーに表示されません*2

ではどうするかというと、ETWについているChannel Supportという機能を使います。ChannelをサポートしたETWのログはイベントビューアーに表示されます。が、このChannelの機能、.NET標準のAPIではサポートされていません。その代わり、BCLチームが作成したMicrosoft.Diagnostics.Tracing.EventSourceライブラリを使うと、事前準備が必要ですが、ManagedコードからChannelサポートしたETWのログを書きこめるようになります。

独自のイベントログを定義する(手順編)

1: ログを送信したいアプリ(コンソールなりWPFなりASP.NETなり)に、Microsoftほげもげライブラリの参照を追加します。Nugetからどうぞ。ダウンロードすると、docx なファイルも一緒に追加されるのですが、使い方はこれが一番詳しいです。

Install-Package Microsoft.Diagnostics.Tracing.EventSource -Version 1.0.26

2: ログを送信するクラス・メソッドを定義します。もともと構造化ログをサポートする意味合いもあったためログのメソッドに意味合いをもたせるのですが、単純なサンプルとしてはこうなります。

using Microsoft.Diagnostics.Tracing;

namespace MyEventSource
{
    [EventSource(Name = "Sample-EventLog")]
    publicsealedclass MyEventSource : EventSource
    {
        publicstatic MyEventSource Log = new MyEventSource();

        [Event(1, Message = "{0}", Channel = EventChannel.Admin)]
        publicvoid Debug(string message)
        {
            WriteEvent(1, message);
        }
    }
}

3: ビルドします。すると *.etwManifest.dllとか *.etwManifest.manとかいう見慣れないファイルが生成されているはずです。これが Microsoft.Diagnostics.Tracing.EventSourceライブラリの便利なところで、ChannelをサポートしたETWはOSに登録しないといけないのですが、そのために必要なファイルを生成してくれます。

f:id:tanaka733:20141201232051p:plain

4: OSに登録します。実際にログを送信するEC2インスタンス上に3で生成された2つのファイルを持ってきて、以下のコマンドを管理者権限で実行します。なお、rf と mfの後にしているdllはフルパスが必要です。

> wevtutil im "D:\Documents\visual studio 2013\Projects\MyEventSource\MyEventSource\bin\Debug\MyEventSource.Sample-EventLog.etwManifest.man"  rf:"D:\Documents\visual studio 2013\Projects\MyEventSource\MyEventSource\bin\Debug\MyEventSource.Sample-EventLog.etwManifest.dll" /mf:"D:\Documents\visual studio 2013\Projects\MyEventSource\MyEventSource\bin\Debug\MyEventSource.Sample-EventLog.etwManifest.dll"

5: 念のためイベントビューアーで確認してみましょう

f:id:tanaka733:20141201232401p:plain

6: Ec2Configの設定ファイルに追加してみます。PrametersのLogName は下記のように EventSourceの名前/Channelの名前で指定します。

{"Id": "SampleEventLog",
    "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
    "Parameters": {"LogName": "Sample-EventLog/Admin",
        "Levels": "7"}},

7: Ec2Config サービスを再起動後、ログのAPIを呼びだすメソッドを実行すると、CloudWatchLogs に送信されているはずです。

パフォーマンスカウンタの値を送る

1: カスタムパフォーマンスカウンタを定義する。

MSDNに説明が載っています。ただ、複数サーバーに展開するときなどを考えるとC#で書いてビルドしたexeを実行する、というのは若干面倒なこともあるので、PowerShell版のサンプルコードを載せておきます*3

# Perfmon Name and Help
$categoryName = "MyAppPerformance"
$categoryHelp = "MyApp"
$categoryType = [System.Diagnostics.PerformanceCounterCategoryType]::MultiInstance

# Fix it by Index
$counterName = "Count", "Time"
$counterType = "NumberOfItems32", "NumberOfItems32"
$counterHelp = "Count", "Time"

# Delete Existing Category
$categoryCount = ([System.Diagnostics.PerformanceCounterCategory]::GetCategories() | where CategoryName -eq $categoryName).Count
If ($categoryCount -ne 0){ [System.Diagnostics.PerformanceCounterCategory]::Delete($categoryName) }

# Create Collection
$objCCDC = New-Object System.Diagnostics.CounterCreationDataCollection
0..($counterName.count -1) `
| %{
    $objCCD = New-Object System.Diagnostics.CounterCreationData
    $objCCD.CounterName = $counterName[$_]
    $objCCD.CounterType = $counterType[$_]
    $objCCD.CounterHelp = $counterHelp[$_]
    $objCCDC.Add($objCCD) > $null
}
$objCCDC | Format-Table -AutoSize | Out-String | %{[Console]::WriteLine($_)}

# Perfmon Execute
[System.Diagnostics.PerformanceCounterCategory]::Create($categoryName, $categoryHelp, $categoryType, $objCCDC) | Out-String | %{[Console]::WriteLine($_)}

2: アプリでカスタムパフォーマンスカウンタに送信する処理を書く

こちらも最低限のサンプルを載せておきます。

privatestaticreadonlystring categoryName = "MyAppPerformance";
privatestaticreadonlystring countCounterName = "Count";
privatestaticreadonlystring timeCounterName = "Time";


publicvoid Write(PerformanceData data)
{
    var retryCounter = new PerformanceCounter(categoryName, countCounterName, data.EventName, false);
    var elaspedCounter = new PerformanceCounter(categoryName, timeCounterName, data.EventName, false);
    retryCounter.RawValue = data.Count;
    elaspedCounter.RawValue = data.Time;
}

3: 設定用のjsonに追記する。

{"Id": "PerformanceCounterMyAppCount",
    "FullName": "AWS.EC2.Windows.CloudWatch.PerformanceCounterComponent.PerformanceCounterInputComponent,AWS.EC2.Windows.CloudWatch",
    "Parameters": {"CategoryName": "MyAppPerformance",
        "CounterName": "Count",
        "InstanceName": "instance1",
        "MetricName": "MyAppPerformanceCount",
        "Unit": "Count",
        "DimensionName": "Host",
        "DimensionValue": "{hostname}"}},
{"Id": "PerformanceCounterMyAppTime",
    "FullName": "AWS.EC2.Windows.CloudWatch.PerformanceCounterComponent.PerformanceCounterInputComponent,AWS.EC2.Windows.CloudWatch",
    "Parameters": {"CategoryName": "MyAppPerformance",
        "CounterName": "Time",
        "InstanceName": "instance1",
        "MetricName": "MyAppPerformanceTime",
        "Unit": "Count",
        "DimensionName": "Host",
        "DimensionValue": "{hostname}"}},

MetricNameはCloudWatch から見てわかりやすい名前にしましょう。またUnitもCloudWatchで使える値の中から適したものを選んでおきます。 また、Dimensionが1組だけ指定できます*4。1つだけなので厳選する必要がありますが、複数台スケーリングさせているWebサーバー上のパフォーマンスカウンタであれば、ホスト名でDimensionを作っておくのがいいかと思います*5

4: アプリを実行して、CloudWatchに送信されていることを確認する。

まとめ

というわけで、AWS といいつつ、ほぼC# とPowerShellな内容になってしまいました。が、内容はC# と PowerShell でも、これを使うことによってシステムから出力されるイベントログやパフォーマンスカウンタだけでなく、自前のアプリのログやパフォーマンスカウンタをCloudWatchとCloudWatchLogsで管理できるようになりました。

この機能の一番のメリットは、CloudWatchとCloudWatchLogsというAWSのパワフルなツールを活用していますが、ログやパフォーマンスカウンタを送信するアプリ側はAWSのことを一切知らない点です。アプリだけであれば、オンプレミスでもAzuer上でも動きます。そして、ETWもしくはEventLogおよびパフォーマンスカウンタという標準的なツールでそのログやカウンタの監視もできます。Ec2Configサービスがその間の橋渡しをしてくれているのです。

なお、弊社ではアプリは別の監視サービスで監視していて、このCloudWatchとCloudWatchLogsはそのサービスでは監視しづらい、Webサーバーの常駐させる自前のWindowsサービスの監視に利用しています。

と持ち上げたところでちょっと下げておくと、まだこなれていない部分もあります。パフォーマンスカウンタのデータを取る頻度をもっと多くしてほしかったり、 設定用のjsonで {ip_address} という置換変数だけ置換されなかったり、Dimensionが1つしか指定できなかったりします。このあたりは、今後のアップデートに期待しています。

PS

Windows パフォーマンスカウンタをCloudWatch に送信しようとすると、設定用の json ファイルがかなり肥大化してきて、手書きではなかなかつらいです。

というわけで、弊社ではExcel VSTO を使って、Excel上で必要なパフォーマンスカウンタ一覧や、イベントログなどを指定すると、設定用のjsonを吐き出すツールを私が作っています。

この辺はきっとAWS側でのなにかしらの対応してくれるとは思っていたりします...

*1:バージョンの確認とサイレントインストールがめんどいです

*2:なので、ETWのログを見るためには別のツールを利用する

*3:PowerShellという名のC#コードという噂もある

*4:本来のPutCustomMetrics なら10組までいけるはずですが...

*5:ip_address は現バージョンでは動きません

PowerShell Cmdlet の中でRxを使いたい

$
0
0

PowerShell Advent Calendarの4日目の記事です。

PowerShell Advent Calendar 2014 : ATND

去年もPowerShell Advent Calendarなのに C# な話だったんですが、今年も性懲りもなくC# コード満載のCmdletネタになります。

PowerShell を C# から実行する - 銀の光と碧い空

最近、マルチプラットフォーム対応のポータブルクラスライブラリが話題ですが、PowerShell Cmdlet として実装するC# プロジェクトでも中身のロジックをポータブルにしておくといろいろ便利です。といっても、AndroidとかiOSに対応するところまでいかなくとも、ロジックのクラスをクラスライブラリとして分離して Cmdlet のクラスから参照してPowerShell から呼び出すほかに、たとえばそのクラスライブラリをWPFツールから参照してGUIから実行する、といったことができます。

さて、そんな状況で、わりと長い(数分くらい)の処理を実行する Cmdlet とその中身のロジックを作ることになりました。また、この処理はWPFのツールからも実行したいので、上に書いたようにクラスライブラリとして分離させることにしました。当然数分かかるため、進捗状況を知りたいので、処理の途中経過でメッセージで表示することにしました。単純に処理の結果だけ取得するなら、Taskな返り値でいいのですが、進捗状況を知りたいとなると。。。と悩んだ結果、Rxを使って IObservableで進捗状況を返すことにしました(Tは独自定義の進捗状況を表すクラス)。で、IObservableなAPIをCmdletクラスで呼びだそうとして、問題はここで起きたのです。

問題を再現するためのコードを紹介します。まず、IObservableなクラスライブラリのメソッドはこんなものです*1

で、これを Cmdlet で呼ぶために、まずこんな書き方をしてみました。

Select メソッド内で飛んできた進捗を Write-Objectしつつ、処理の完了を待つために、 FirstAsyncしたものを Waitしています。 これを実行するとこんなことになります。

Invoke-BadHelloRx : WriteObject メソッドと WriteError メソッドは、BeginProcessing メソッド、ProcessRecord メソッド、
および EndProcessing メソッドの上書きの外側から呼び出すことはできず、同じスレッド内からだけ呼び出すことができます。
コマンドレットで呼び出しが正しく作成されていることを確認するか、または Microsoft カスタマー サポート サービスにお問い合わせください。
発生場所 行:3 文字:1
+ Invoke-BadHelloRx
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Invoke-BadHelloRx]、PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,ObservableCmdletSample.BadRxCmdlet

ぐぬぬ... Write-Objectは呼びだされたスレッドの中から実行しないといけないのですね...((ちなみに、async voidにして、Waitメソッドの代わりにawaitすると、PowerShellが強制終了し、ほとんど情報のないイベントログがイベントID:1000 として記録され、さらに訳が分からなくなります)) では、ということで、SynchronizationContext.Currentを取得して、 ObserveOnしてみましょう。

実行すると...

Invoke-BadHelloRx : 値を Null にすることはできません。
パラメーター名:context
発生場所 行:3 文字:1
+ Invoke-BadHelloRx
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Invoke-BadHelloRx], ArgumentNullException
    + FullyQualifiedErrorId : System.ArgumentNullException,ObservableCmdletSample.BadRxCmdlet

おお、ぬるぽ!!!111 Cmdletの中は SynchronizationContext.Currentが null でした。

対処法を検索したところ*2*3、このCmdletが呼ばれる環境(コマンドプロンプトの中なのか、WPFの中なのか...など)がわかれば、それに対応した SynchronizationContextを作ればいいようなんですが、そもそもいろんな環境で再利用したいので、そういうこともしたくない...

と悩んでいたところ、CTOに教えてもらったのがこの方法です。

BlockingCollection<Action>を使って、RxのSubscribeの中でQueueに処理を追加し、後から逐次実行していくイメージです。

実行してみると...

f:id:tanaka733:20141201115100p:plain

無事に実行できました。この書き方がベストかどうかはわからないのですが、PowerShell Cmdlet から RxなAPIを叩くときに困ったときの助けになれば幸いです。

*1:この程度なら、Subject使わずに Observable クラスのメソッドチェーンで書けそうですが、実際は様々な非同期処理をawaitしている処理になっています。

*2:c# - Powershell custom cmdlet Calling WriteVerbose outside of implementation of standard methods - Stack Overflow

*3:powershell-for-developers/WPFJob.cs at 437aab5821e8de698168f245413d3ad725b40f7f · dfinke/powershell-for-developers · GitHub

.NET アプリから BigQuery に Streaming Insert する方法

$
0
0

このブログは Google Cloud Platform Advent Calendar 2014 の7日目のエントリです。

Google Cloud Platform Advent Calendar 2014 - Qiita

さて、以前テーブルをAPIから生成する方法は紹介したのですが、データをStreaming Insertする方法について書いていなかったので、そこを説明したいと思います。また、すでに本番運用して、WebサーバーからデータをBigQueryに送信しているのですが、どのような点に注意しているかも紹介したいと思います。

C# から Streaming Insertする方法

まずはサンプルコードをのせます。

StreamingInsert.cs

CreateTable メソッドは前回の記事を参考にしてください。LoadRowsメソッドは実際に送信するデータですが、でたらめな値を入れるのであればこんな感じになります。特徴としては、テーブル定義に対応した列名とその値を Dictionary<string,object>で指定することです。

private IList<TableDataInsertAllRequest.RowsData> LoadRows()
{
    return Enumerable.Range(0, 450)
        .Select(_ => new TableDataInsertAllRequest.RowsData
        {
            InsertId = Guid.NewGuid().ToString(), //リクエストの一意なIdなのでGuidで代用
            Json = new Dictionary<string, object>
            {
                { "date", DateTime.Now },
                { "source", "hoge" }
            }
        }).ToList();
}

長くなっていますが、基本的には

var req = new TableDataInsertAllRequest
{
    Rows = LoadRows()
};

var response = await bigquery.Tabledata.InsertAll(req,
                    "testprj", "testdataset", "testtbl").ExecuteAsync();

でInsertできます。面倒なことをしているのは、

  • Insert先のテーブルがないときにテーブルを生成する処理
  • 失敗時にリトライする処理

を入れているからです。

テーブルの自動生成処理を入れるかどうかはInsertの要件次第でしょう。たとえば期間ごとにテーブルを分けて格納する場合*1に、新しいテーブルを作るたタイミングで別のツールから生成するのではなく、このコードの中で生成することを想定しています*2

また、後者の失敗時のリトライですが、これは割と必須の処理です。BigQuery のStreaming InsertはバックエンドのエラーでInsertが失敗することがあり、その場合にはリトライすることが推奨されています。リトライも単純に一定時間おきに繰り返すのではなく、指数関数的な伸び+ランダムに追加した時間だけ待機する Google.Apis.Util.ExponentialBackOffを利用しています。なお、所定の最高試行回数(ExponentialBackOff の初期値だと10)を超えると、Insertをあきらめデータは破棄することになります。

本番運用で考慮していること

というわけで上のような Streaming Insert なコードを本番環境で動かして BigQuery にデータを送信しています*3

さて、そもそもどうやってこのコードを動かしているかですが、 上のコードを SLABのSinkとして実装し、 Out-of-Process Serviceとして動かしています。送信するイベントを送信するのはIIS上のASP.NETアプリになります。

テーブルの自動生成と失敗時のリトライは上のコードのように考慮していますが、ほかに次のようなことを考慮して動かしています。

  • Insert先のDataSet名、Table名、テーブル定義などは EventSource のメタ情報として定義しています。 DataSet名 は EventKeyword、Table名は EventTask、テーブル定義は Paylowd 経由で取得、という感じです。
  • 1回のリクエストあたり500行というハードリミットがあるので、450行ずつバッファリングして送信
  • SLABのSinkでは BufferedEventPublisher<EventEntry>でイベントをバッファリングしてまとめて送信できるが、バッファが溜まった時に発火するeventPublisher*4の中でリトライを繰り返すと、後続のログもたまり続けるため、1回失敗した場合は、別の BufferedEventPublisher にためていくようにしている
  • Insertしている Out-of-Process Service の健全性は、Windows EventLogおよびパフォーマンスカウンタを通して確認している。*5

といった点です。

というわけで、意外な組み合わせかもしれませんが、.NET アプリからもBigQueryにデータを送信して活用しています、というお話でした。

*1:test_20141201, test_20141202 ... みたいなテーブル名を想定

*2:その場合、テーブル名は日時に応じて動的に判断することになり、テーブル構造を指定する必要もある

*3:動いているコードそのものをお見せしていないのは、テーブル名やテーブル定義の生成部分に弊社固有のロジックが入ってコードの見通しが悪いためです...

*4:CreateAndStartメソッドの第2引数で指定

*5:実際はそれらを AWS CloudWatch で集約してアラートをしかけている

ASP.NET/IIS 上で X509Certificate2 をバイト配列指定で生成するときは、 Application Pool の実行ユーザーのプロファイルを読みこませないといけません

$
0
0

C# Advent Calendar と ASP.NET Advent Calendar の9日目のエントリです。

もともと別の内容を書くつもりだったのですが、仕事であまりにはまったことがあったので、それを書こうと思います。

背景

Google API をたたきたい状況で、APIサーバー側(つまりGoogle側)で発行される証明書を使って、 X509Certificates2クラスのインスタンスを生成して認証する必要があります。

X509Certificate2 クラス (System.Security.Cryptography.X509Certificates)

証明書ファイルのパスを指定してインスタンスを生成することもできますが、

X509Certificate2 コンストラクター (String, String, X509KeyStorageFlags) (System.Security.Cryptography.X509Certificates)

証明書ファイルのコンテンツを byte配列として渡すこともできます。

X509Certificate2 コンストラクター (Byte[], String, X509KeyStorageFlags) (System.Security.Cryptography.X509Certificates)

どういうときにbyte配列を指定したいかというと、複数のWebサーバーで同じ証明書を使うときなどにネットワーク上のストレージに証明書を置いて管理したいときになります*1

ネットワーク越しに証明を取得するコード

AWS SDK を使って、S3から証明書を取得してX509Certificates2クラスのインスタンスを生成するコードはこんな感じになります。

var s3 = AWSClientFactory.CreateAmazonS3Client(s3Key, s3Secret, RegionEndpoint.APNortheast1);
var s3Obj = s3.GetObject(certficateBucket, certificateKey);

byte[] bytes = null;
using (var responseStream = s3Obj.ResponseStream)
{
    bytes = responseStream.ReadFully();
}

var certificate = new X509Certificate2(bytes, certificatePassword, X509KeyStorageFlags.Exportable);

//以下の拡張メソッドを用意publicstaticclass StreamExtension
{
    publicstaticbyte[] ReadFully(this Stream input)
    {
        var buffer = newbyte[16 * 1024];
        using (var ms = new MemoryStream())
        {
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            return ms.ToArray();
        }
    }
}

このようなコードを Global.asax.csApplication_Startメソッドの中から呼び出していました。

起きたこと

で、このコードを載せたアプリをIISで動かすとエラーが発生しました。(以下のエラーはエラーの詳細を表示する設定を Web.config に指定している場合にブラウザ上に表示されるメッセージの一部)

[CryptographicException: 指定されたファイルが見つかりません。]
   System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) +41
   System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx) +0
   System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags) +313
   System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password, X509KeyStorageFlags keyStorageFlags) +98

このエラー、ブラウザ上に表示しないようにしていると、イベントログにこんな感じに表示されるだけで、さらに謎になります*2

(一部抜粋)

障害が発生しているアプリケーション名: w3wp.exe、バージョン: 8.0.9200.16384
障害が発生しているモジュール名: ntdll.dll、バージョン: 6.2.9200.16579
例外コード: 0xc0000374
障害オフセット: 0x00000000000ebd59

障害が発生しているアプリケーション パス: c:\windows\system32\inetsrv\w3wp.exe
障害が発生しているモジュール パス: C:\Windows\SYSTEM32\ntdll.dll

障害が発生しているパッケージの完全な名前: 
障害が発生しているパッケージに関連するアプリケーション ID: 

なぜ、 byte配列を指定しているのにファイルが見つからないといわれるのか...

原因と対策

いろいろぐぐっていたら似たようなことにはまった人がStackOverflowにいて自己解決していました。

どうやら、X509Certificate2を byte配列を指定してインスタンス化しようとすると内部でユーザープロファイルに書きこみ処理を行っているようで、IIS でApplication Poolの実行ユーザーに対してユーザープロファイルの読みこみを指定していないと書きこむことができなくてエラーになるようです。 というわけで、ユーザープロファイルを読みこむようにしてみましょう。以下のサイトがわかりやすいです。

ApplicationHost.config で次のように設定すればOKです(他のIdentityType でもいけるはず)。

<system.applicationHost><applicationPools><add name="MyAppPool"><processModel identityType="SpecificUser"userName="MyAppPoolUser"password="password" /></add></applicationPools><!--省略--></system.applicationHost>

この設定をすると無事最初のコードで X509Certificates2をインスタンス化して、認証に使うことができました。めでたし、めでたし。 なお、ユーザープロファイルのディレクトリを見ても、この証明書ファイルとして保存しているわけではないようです。

なお、もともとC# Advent Calendarで書く予定だった社内ライブライのビルド・デプロイ戦略については改めて書きたいと思っています。

*1:S3に証明書を置いて、その証明書を取得できる権限を IAM Role で制御するなど

*2:例外コードでぐぐったり、VSでプロセスにアタッチしたりすると「ハンドルされない例外が 0x000007FD14B4BD59 (ntdll.dll) で発生しました(w3wp.exe 内): 0xC0000374: ヒープは壊れています。 (パラメーター: 0x000007FD14BA05F0)。」とかいうメッセージが出るのもさらに謎を深める

【読み始めました】 「Pro Unity Game Development with C#」

$
0
0

Unity Advent Calendar の10日目のエントリ...だったのですが、いろいろ体調不良が重なり当初書評を書く予定で読んでいた本が読み切れませんでした...というわけなので、なぜこの本を読もうとしたのかと、読んだところまでの感想を書きたいと思います。

今回読んだ本は「Pro Unity Game Development with C#」です。シアトルのMS本社内のMicrosoft Storeに行った際に割引していたこともあり紙の本で購入しました。

読もうとしたきっかけ

Unity なんですが、会社としては Unity による開発プロジェクトが進行しており、Unity以外のプロジェクトに携わるエンジニアも含めて全員がUnityの勉強を定期的にしています。勉強会ではテーマを設けて丸一日そのテーマについて勉強するので、そのテーマの周辺の理解を深めることはできるのですが、そもそもゲーム全体をUnityでどうやってつくるのか?という全貌はなかなか見えてきません。そこでUnityによる全体像を学ぶために本で勉強しようと思いました。

本の概要

この本は章に沿って、Unityプロジェクトを開発していき、最終的に1つのゲームを作る形式になっています。途中まで読んだ感想としては、丁寧に解説していると思います。Unity そのものの操作もそうですし、途中で記述する C# コードについてもそうです。また、コードをダウンロードできるので、ちょっと書いていってこれであっているかな?と思ったときに答え合わせすることもできます。

という感じで非常に短くて申し訳ないのですが、いったんこれで本日分のエントリにします。読破して、プロジェクトを作った時に改めて書評を書きたいと思います。


CLR/H in Tokyo 第7回で ETWとカスタムパフォーマンスカウンタについて話しました #clrhtky7

$
0
0

CLR/H in Tokyo 第7回 で話してきました。

資料はこちらになります。

資料中にリンクはあるのですが、ETWとは?とか今までのイベントログとの違いとは?についてはこちらのエントリがわかりやすいです。

EventSource をHttpModuleのデバッグ用ロギングに使った話はこちら。

今回は、ETWとカスタムパフォーマンスカウンタという視点からのお話でしたが、AWS Cloudwatch での統合という視点からはこちらのエントリで書いています。

Visual Studio Online のビルドテンプレートとしてのXAMLをさわってみよう

$
0
0

XAML Advent Calendar 23日目です。

昨日は id:karnoroidさんのStore向けMVVMライブラリ「Skylight」のお話でした。

さて、ここまでの XAML Advent CalendarはUIテクノロジとしてXAMLが中心でしたが、ここらで Workflow Foundation としてのXAMLを見てみたいと思います。単にWFというと、どこか遠いようなわークフローな気がしますが、UIとしてのXAMLを扱うエンジニアでも気軽に使える Visual Studio Online でのお話です。

Visual Studio Online

もともとTeam Foundation Service として、Team Foundation Service のSaaS版という位置づけから開始したサービスを、TFSに限らずGitなどさまざまな開発者向けサービスを統合したSaaSとして展開しているものです。

Visual Studio Online とは

TFSの機能は強力なんですが、GitHubを中心とした開発者向けサービスがいろいろ出ている現状を見るに、TFSに限定しない開発者向けサービスを出してきたのは、昨今変わり身の速いMicrosoftっぽいと思っています。

そして、先日行われたConnect(); というイベントの中で Visual Studio Online の展望も話され、Gitとの強力な連携や、リリース管理機能の搭載などが発表されました。

Connect(); Microsoft Visual Studio vNext & Azure | Channel 9

Visual Studio Online と XAML

というVisual Studio Onlineなんですが、ビルドをクラウドサービスとして行うことができます。AppVeyorもMS系テクノロジと親和性の高いビルドサービスなんですが、 Visual Studio Online の特徴はTFSをベースにしているため、Workflow Foundation でビルド定義を記述することです。そうです、XAMLなんです。ということで、ようやくXAML アドベントカレンダーの記事らしくなってきましたが、このビルドテンプレートをいじってみたいと思います。

詳細な手順はこちらを参考にしてください。

ビルド プロセス テンプレートのカスタマイズ

今回は、Visual Studio 2013 Update4 を使い、Gitでやっています。

さて、元から用意されているGit用のテンプレートに手を入れる前にちょっとXAMLを覗いてみましょう。普通に開くとデザイナが立ち上がります。

f:id:tanaka733:20141223172926p:plain

f:id:tanaka733:20141223172936p:plain

直列な処理なので、わかりやすいと思います。ビルドエージェントのなかで Pull sources from Git repoとかRun MSBuildとかあって、Gitからコードを取得してMSBuildしている様子が確認できます。

次に、「コードの表示」でXAMLを直接見てみましょう。適当に折り畳んでいます。

f:id:tanaka733:20141223172710p:plain

ActivityというRoot要素の下にいろいろ作られています。この中の、Sequenceという要素がデザイナで見たビルド処理を定義しています。

f:id:tanaka733:20141223172722p:plain

基本的には、デザイナでポトペタした処理が追加され、処理ごとの引数とかを設定できるようになっています。

ビルドテンプレートへの追加と編集

実際に紹介したリンク先にあるように、デザイナ上で WriteBuildMessageというアクティビティをフローの最後に追加してみました。

f:id:tanaka733:20141223173812p:plain

これを選択すると、WPFのXAMLのようにプロパティエディタで編集できます。

f:id:tanaka733:20141223173842p:plain

プロパティに値を編集するダイアログを開くと、Intelisense も効きます。

f:id:tanaka733:20141223174050p:plain

Messageプロパティを編集しようとダイアログを開いて入力したところです。わかりづらいのですが、右側の i マークはコンパイルエラーを表しています*1

f:id:tanaka733:20141223175417p:plain

文字列リテラルを指定するには、引用符が必要でした。

f:id:tanaka733:20141223175515p:plain

ここまで編集してビルドを実行したあとで「ログを表示」で表示すると、追加したアクティビティが動作していることがわかります。

f:id:tanaka733:20141223175612p:plain

引数の追加とアクティビティへの指定

ここまでが引用先のリンクにあったカスタマイズなのですが、せっかくなのでメッセージをべた書きではなく、ビルド時の編集で指定できるようにしてみましょう。

ビルドテンプレートのデザイナを開いて、引数タブを選択して開きます。ここで引数を追加して、名前 OutputMessage、方向 入力、引数の型 Stringを指定します*2

f:id:tanaka733:20141223175835p:plain

で、WriteBuildMessageアクティビティのMessageプロパティを編集します。Intelisenceに先ほど定義したOutputMessageという変数が表示されます*3

f:id:tanaka733:20141223180001p:plain

ここまでできたら、いったんビルドテンプレートをコミットしてプッシュまでしたのちに、最新版を適用しておきます。すると、ビルド定義の編集時のビルドプロセスパラメーターに先ほど追加したOutputMessageという変数が表示され、メッセージを指定できます。

f:id:tanaka733:20141223175844p:plain

あとは、ビルドするとここで指定したメッセージが最後に表示されます。

なぜ Visual Studio Onlineなのか

というわけで、Visual Studio Onlineのビルド定義のXAMLをさわってみました。ちょっとさわってみる分にはXAMLでビルド定義というのは、敷居が高いとは思っています。しかし、個人的には今後ビルド・リリースの自動化ではVisual Studio Onlineに注目しています。

理由は、最初の方にも書きましたが Workflow Foundationだからです。ビルドだけでもそうですが、リリース作業まで自動化することを考慮すると、その処理はかなり複雑なものになります。本番にリリースしたら、リリースしっぱなしではなく、何かしらの値を監視して正常なリリースだったかを確認する必要があります。なにか異常が見られたらロールバックなどの対応を行う必要もあります。このような処理を記述するのにWorkflow Foundationはかなり適していると考えています。(Workflow Foundationに限らず)ワークフローエンジン上で動くビルド・リリース自動化基盤として、Visual Studio Onlineを今後も調査しく予定です。

*1:水色がエラーとか

*2:C# プロジェクトとして開いていても、既定値はVBの式として入力するんですねー

*3:つまり、さきほど文字列引用符が必要だったのは、引用符がないと変数として認識されるため

パイザオンラインハッカソン4 の C# での解答を晒してみる

$
0
0

パイザオンラインハッカソン4 というのが行われているのですが*1

なんかTwitterで@numa08氏を煽ってしまったようなので、せめて自分の解答くらいは晒しておこうと思います。 最速を狙ったわけではなくて、とにかくストーリーを進めたくて100点の出せるコードを書いてみたという感じです。

ミッション1

ケース実行時間
Test case 1 0.03 秒
Test case 2 0.03 秒
Test case 3 0.03 秒

ミッション2

ケース実行時間
Test case 1 0.04 秒
Test case 2 0.03 秒
Test case 3 0.03 秒

ミッション3

ケース実行時間
Test case 1 0.03 秒
Test case 2 0.03 秒
Test case 3 0.03 秒
Test case 4 0.10 秒
Test case 5 0.10 秒

*1:メガネスキーな方は読まないことを強く推奨します

リモート接続先で接続元の情報を C# で取得する

$
0
0

リモート接続先で起動するアプリで、接続元の情報を取得したい事案が発生しました。 そんなときはこの関数を使えばよさそうです*1

WTSQuerySessionInformation 関数

DllImportすれば C# でも書けますね、ということで書いてみました。sessionId は WTS_CURRENT_SESSION を指定すれば自分自身のセッション情報を取得できるのですが、これは uint.MaxValueのようです。

Retrieve Terminal Server session information.

若干面倒なのは、WTSInfoClassで指定した値に応じて ppBuffer が示す変数の構造が変わることです。そのため、サンプルでは WTSClientAddressWTSClientNameの時のパターンを書いています。WTSClientAddressの時の構造体はここに情報があります。

WTS_CLIENT_ADDRESS structure (Windows)

また、自分自身以外のすべてのセッション情報を取得したい場合のサンプルも書いています。これはこの関数を使います。

WTSEnumerateSessions 関数

というやや面倒な処理が初めての DllImport 体験でした。

*1:アプリをUAC昇格して起動することで権限的な問題もなさそう

AWS Management Console でクロスアカウントアクセスするための IAM Role をPowerShellで生成する

$
0
0

複数のAWSアカウントを管理している人には待望の機能が来ました。

さて、この機能を作るためには、Switch Roleする先のAWSアカウントで、クロスアカウントを許可するIAM Roleが必要です。Management Consoleでぽちぽち作ってもいいですが、PowerShellで一発で*1作ってみました。

$assumeRolePolicyDocumentの Principalですが、今回は指定したAWSアカウントの指定したユーザーに対して許可するようにしました。AWSアカウント全体に対して許可する場合は、user/<IAM_USER_NAME>のところを ROOTにすればOKです。また、ここユーザーだと個別指定になってめんどいよね...というのでGroupとかで指定したいところですが、それはできない仕様になっています。

また、付与する権限そのものはすべて許可するようにしていますが、$policyを編集すれば付与する権限を設定することも可能です。

*1:正確にはコマンド2回

PowerShell Cmdlet バイナリモジュールのプラクティスまとめ (1) スレッド・Rx編

$
0
0

今まで何度か、PowerShell Cmdlet バイナリモジュール(C#でdllを記述し、Import-Moduleで利用するCmdlet)について書いてきました。実際、Cmdletを実戦投入して運用していますが、実際に運用してみるとなかなかはまりどころが多いこともわかりました。何回かにわけて、実際にこうやって解決したという(ベストとは言えないけど)プラクティスを紹介したいと思います。

連載目次

  • スレッド・Rx
  • ロギング
  • 例外処理
  • 設定(Configファイル)

スレッド・Rx

いきなりスレッドなわけですが、これは以前下記の記事で紹介したものを修正したいからです。

このエントリでも触れましたが、PowerShell Cmdletは WriteObjectメソッドと WriteErrorメソッドは、呼ばれたメソッド(たとえば、ProcessRecordメソッド)と同じスレッドから実行する必要があります。という観点でみると、実は一つ漏れがあって例外処理時にエラーが発生するのです。

以前載せていたものでは、Rxの SubscribeメソッドのonError の中で例外処理をしていましたが、このActionの中で直接ThrowTerminatingErrorを実行していました。ThrowTerminatingErrorは内部で WriteErrorメソッドを実行しているのですが、これが呼び出し元スレッドとは別のスレッドで実行されてしまい、Cmdletが強制終了してしまいます。

というわけで例外処理も含めて、すべての WriteObjectメソッドと WriteErrorメソッドをメソッドの呼び出しスレッドと同じスレッドで実行するように修正したのが以下のコードになります。

今回はRxを使ったサンプルになりましたが、 async/awaitを使った場合やそのほかの別スレッドでの実行を行う処理も同様です。WriteObjectメソッドと WriteErrorメソッドはメソッドの呼び出しスレッドと同じスレッドから呼びだすようにしないといけません。そして、SynchronizationContext.CurrentがCmdletクラス内では null になっていることにも注意する必要があります。

PowerShell Cmdlet のデバッグを楽にする、 OpenForPSCmdlet VS拡張

$
0
0

PowerShell Cmdlet のバイナリモジュールを作ったことがある方はわかるとおもうのですが、バイナリモジュールを実際にPowerShellで実行して動作を確認するためには、ビルドしたdllをImport-Moduleで読みこむ必要があります*1。さらに、一度 Import-Moduleすると、そのPowerShell ConsoleなりISEのプロセスが dll をファイルロックするため、一度 Consoleを閉じないと、リビルドできません*2

そのため、バイナリモジュールをデバッグするときは、ビルドする、PowerShell Console開く、Import-Moduleする、デバッグする。Console閉じる、という流れを繰り返す必要があります。これはめんどい!っていうのを前から思っていたのですが、ようやくVisual Studio拡張として作成しました。

作成したCmdletを継承した自分のクラスを開いたエディタを右クリックすると、「Open for PSCmdlet」というメニューが出るのでクリックします。

f:id:tanaka733:20150203010609p:plain

すると、そのクラスが含まれるプロジェクトをアクティブなビルド構成でビルドした後で、PowerShell Consoleを開き、プロジェクトのビルド成果物である dllをImport-Moduleしてくれます(Import-Moduleしたコマンドは表示されませんが、実際にImportされています)。こんな風に、デフォルトとは異なるアセンブリ名や出力先フォルダを指定していても、

f:id:tanaka733:20150203011012p:plain

f:id:tanaka733:20150203011015p:plain

この設定を読み取って、dll を Importしてくれます。

f:id:tanaka733:20150203011143p:plain

現在リリースしている最新のバージョンはこの機能だけになります。

コードはGitHubで公開しているので、バグ報告や機能要望もこちらにお願いします。

処理は、OpenForPSCmdletPackage.csで完結しているのでここを読んでもらえると、Visual Studio拡張の中でビルドする方法や、csproj の設定を読む方法などがわかると思います。

*1:所定のフォルダに配置すればImport-Moduleは必要ないですが、開発中はプロジェクトディレクトリのbin以下に出力することが多いでしょう

*2:閉じずにリビルドやクリーンすると、dllを削除できないためエラーになる


#めとべや東京 #7 で MSCCで開発したAzure WebSites でうごくASP.NET MVC のサイトについて発表しました

Kindle Voyage と Kindle PaperWhite を比較して PaperWhiteを選びました

$
0
0

そろそろ電子書籍端末ほしいなあと思っていたとこと、30日間全額返金キャンペーンというのがあったので、お言葉に甘えてVoyageとPaperWhiteの両方を購入して比較することにしました。

Kindle Voyage Wi-Fi、キャンペーン情報つきモデル

Kindle Voyage Wi-Fi、キャンペーン情報つきモデル

Kindle Wi-Fi、キャンペーン情報つきモデル

Kindle Wi-Fi、キャンペーン情報つきモデル

端末の想定利用シーン

  • 技術書メイン。今のところ英語のDRMフリーなものが多い。mobi形式で配布されているのでそのまま読み込み。
  • 日本語の技術書も、電子書籍化が進んで来たら購入したい。
  • 漫画はほとんど読まない
  • 通勤電車の中で読むことがほとんど。座って読めるときと立って読むときが半々くらい。
  • 寝転がってよむことはあまりない

Voyage を使ってみた感想

  • 背景が白くてきれい & 解像度高い

これも比べると顕著。WhitePaperが汚いとかではないけど、断然Voyageの方がきれい。 解像度も高いので小さい文字でもよみやすい。 漫画がメインだとこちらの方が読みやすいかも。

  • 薄くて軽い

これは比べてみると確かにわかる軽さ。寝転がって読むとかいうシーンだとこの軽さを求めたたいのもわかるかも。 ただケースとかつけると、メリット薄くなるかも。

  • 電源ボタンの配置とページめくりボタン

電源ボタンが裏側についていて、両手でホールドして読む体勢になったときに自然に右手の指先に電源ボタンの位置がある感じ。PaperWhiteは下側にあるのでちょっと手を伸ばさないといけない。 また、画面タップのほかに指をかざすだけでページめくりできる(感圧)ボタンがあって、手袋とかしてるときは便利。

  • PCやiPhoneと比べると動作はもっさり

これは、この価格帯の専用端末では現状どうしようもないのかもしれないけど、普段PCやiPhoneでタッチ操作しているものと比べると動作はややもっさり。 ただ、PaperWhiteと比べると、体感的にはこちらの方が動作はよくなっています。

PaperWhite を選んだ理由

スペック的には全部PaperWhiteの方が上です。そして両者の差額が1万円なので、1万円出していいスペックを選択するかどうかなのですが...私は選択しませんでした。 理由は

  • 技術書メインだと、そこまで解像度の高さや綺麗さは必要なかった。(PaperWhiteで十分に快適に読めた)
  • Voysage でももっさり感を感じたので、それならPaperWhiteでもいいやという感覚
    • PaperWhite は表面がややざらざらしているが、むしろざらざらしている方が操作しやすい

といったところです。

ちなみに、今回両方ともキャンペーン付きモデルを選びました。電源を入れたときに1回広告画面を挟んで画面遷移するのと、ライブラリの下部に広告が表示されます。本を読むときの画面には出ませんし、個人的にはストレス感じないレベルでした。

というわけで、完全にその人の使い方というか、好み次第という結論になってしまいますが、4月まで30日間全額返金キャンペーンをやっているようですので、両方を比較してみるのもいいのではないでしょうか。

Open for PowerShell Cmdlet v1.1 をリリースしました

$
0
0

visualstudiogallery.msdn.microsoft.com

すでにインストールしている方はアップデートがかかるはずです。

v1.0ではモジュールをImportした状態でPowerShell Consoleが開きましたが、v1.1ではこのConsoleのプロセスにアタッチしてデバッグ可能になりました。

f:id:tanaka733:20150320010433p:plain

ちなみにコードとしてはこんな感じで数行でかけてしまいました。

//PowerShell Consoleのプロセスを起動
var p = new System.Diagnostics.Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = @"C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe",
        WorkingDirectory = dir,
        Arguments = $"-NoExit -Command \"& {{Import-Module '{outputPath}'}}\""
    }
};
p.Start();

//デバッガーがアタッチできるローカルのプロセス一覧の中から、起動したPowerShell ConsoleのプロセスIdと一致するものを取得
var dteProcess = DTE.Debugger.LocalProcesses.Cast<EnvDTE.Process>().FirstOrDefault(prop => prop.ProcessID == p.Id);

if (dteProcess != null)
{
    //該当のプロセスにアタッチ
    dteProcess.Attach();
    DTE.Debugger.CurrentProcess = dteProcess;
}

引き続き機能要望などお待ちしております。

github.com

Visual Studio 拡張(VSIX)用のプライベートリポジトリを作ろう

$
0
0

最近 Visual Studio拡張ツールの開発にはまっているのですが、パブリックに公開したいものであれば Products and Extensions for Visual Studioで公開するのがお手軽ですし、ダウンロードもしてもらえます。しかし、時には社内にのみ配布したい拡張もあるでしょう。特に、Visual Studio 2015 と C# 6.0 Roslyn で、Code Analyzer や Code Refactoring が作れることによって、よりVS拡張を作る機会が増え、社内向けプライベート VSIXリポジトリの需要が増えるかもしれません。

というわけで、今回はさくっと社内向けプライベートVSIXリポジトリを作ってみました。

内容としては、以下のMSDNやMSDNブログで紹介されている内容です。

blogs.msdn.com

https://msdn.microsoft.com/en-us/library/hh266746.aspxmsdn.microsoft.com

共有フォルダや、Sharepoint のサイトによる公開もできるのですが、ダウンロードできるVSIXの一覧を作成する必要があるので、普通のASP.NET MVC なWebアプリとして作るみることにしましょう。VSIX自体も別のStorageに置くのではなく、Webサイトが動くサーバー上のファイルシステムに直置きすることにします。

まず、VSIXの一覧をAtomフィードで作成する必要があるのですが、フィードの作成に必要な情報を別途管理するのではなく、直置きされたVSIXファイルを読みこんで作成することにしました。

gist.github.com

コードはC# 6.0で書いてます。 説明はコメントに書いてある通りです。面倒な点としてフィードに記述する情報はすべてがVSIXが読み取れるわけではなく、カテゴリやVSIXの作成・更新日時は別途リポジトリで管理しないといけません。今回、カテゴリは決め打ち、作成・更新日時はファイルの更新日時で代用しています。

途中でてくる、 PackageManifest や feed・feedEntry といったクラスはXMLをC#のクラスに対応させたもので、サンプルのXMLを Visual Studio に「Paste XML as Classes」で張り付けて作成したものになります。gist のリンクだけを貼っておきますが、面倒なのでクラス名が小文字で始まっているままになっています。

Models.cs

最低限これだけがあれば、Visual Studioにフィードを登録できます*1。Webサイトに PackagesBin というフォルダを作り、そこにVSIXを入れておけばフィードが作成されます*2

f:id:tanaka733:20150404224901p:plain

ちなみにDL処理ですが、ファイルが存在しているのであれば(最低限PackageBinというフォルダがあれば) ~/PackageBin/hogemoge というリクエストに対しIIS側で静的ファイルを返すように処理してくれます。ただ、 vsix という拡張子がMIMEになくてエラーになるので、以下の記述を Web.config のConfiguration要素の子として追加しておきましょう。

<system.webServer><staticContent><remove fileExtension=".vsix" /><mimeMap fileExtension=".vsix"mimeType="application/octet-stream" /></staticContent></system.webServer>

これだけでも、VSIXを追加するたびにサーバー上のフォルダに配置すれば動くんですが、まああれなのでアップロード機能もさくっと追加してみましょう。

gist.github.com

gist.github.com

これで、 ~/Packages にアクセスするとフォームが表示され、VSIXを選択して送信すると PackageBin 以下に保存してくれます。

もうちょっと真面目にやるなら、アップロード側の認証だったり*3、リポジトリの削除機能だったり、バックアップ機能があったりしてもいいかもしれません。

ちなみに、 Nuget だと Nuget.Server というNugetライブラリがあって、これをASP.NET MVCなWebアプリに追加するとすぐに使えるようになっています。

www.nuget.org

*1:登録の仕方は最初のMSDNブログにあります

*2:例外処理とかしてないので、不正なVSIXがあると落ちる

*3:クライアント側はVSの機能で制限される

#5joffice で VSTO について話してきました

$
0
0

html5j 番外編 Microsoft Officeセミナー その1 で、「Introduction to VSTO」というタイトルでVSTOについて話してきました。

5joffice.doorkeeper.jp

資料はこちらになります。

www.slideshare.net

資料中にもありますが、デモしたアプリは一部改変して以下のリポジトリに置いています。

github.com

VSTOの情報って少ないしセッションする機会もあまりないので、今後も何かの機会に出していければいいなと思っています。特にVSTOの画面をWPFで作るとか。

Viewing all 278 articles
Browse latest View live




Latest Images