redwarrior’s diary

C#, ASP.NET, WEB, G*などの雑多な情報

TFSの新しいビルドを試す

前回からあっという間に2か月以上たってしまった。細く長くがんばろう。
2015以降のTFSではXAMLビルドは推奨されない*1方式になるので、新しいビルドを試した。

環境:Team Foundation Server 2015 Update 4、Windows Server 2012SQL Server 2012

目次

プールの追加

画面上から歯車アイコンを押して、コントロール パネル画面に遷移する。

f:id:redwarrior:20180808111646p:plain

コレクション管理ページの表示をクリックして、コレクションのプロファイル画面に移動する。

f:id:redwarrior:20180808114633p:plain

エージェントキュータブをクリックする。新しいプールとキューを作成するために、新しいキューリンクをクリックする。

f:id:redwarrior:20180808115714p:plain

ダイアログで「新しいプールの作成」ラジオボタンを選択し、プール名に名前(今回は「VSPool」とする)を設定する。(上記画像は既に作成済)

f:id:redwarrior:20180808115644p:plain

プールの作成に失敗した場合は、権限が不足しているので、Team Foundation 管理者ユーザにプールを作成してもらう。

権限の設定

ビルド等に必要な権限を設定するため、プールの管理リンクをクリックするか、コントロールパネルをクリックしてサーバーの管理画面に遷移して、エージェントプールタブをクリックする。

f:id:redwarrior:20180808120359p:plain

すべてのプールに新規作成したプールが表示されるので選択する。エージェントにはまだ何も表示されていない。役割をクリックすると、役割として「エージェントプール管理者」、「エージェントプールサービスアカウント」が表示される。両方にビルドエージェントを起動するユーザを追加する。

f:id:redwarrior:20180808120449p:plain

次にコレクションのプロファイル画面のエージェントキューに戻って、新規作成したプールを選択して、役割をクリックする。役割として「エージェントキュー管理者」、「エージェントキューユーザー」が表示される。エージェントキューユーザーにビルド定義を作成するユーザを追加する。「エージェントキュー管理者」は変更しなくて良い。

f:id:redwarrior:20180808120827p:plain

エージェントのインストール

今回はお試しという事で、開発で使用しているPCにエージェントをインストールして、手動でビルドを試す。 エージェントのダウンロードをクリックして、ビルドエージェントをダウンロードする。

f:id:redwarrior:20180808133433p:plain

ダウンロードした圧縮ファイルを解凍する。するとAgentフォルダとConfigureAgent.cmdファイル、RunAgent.cmdファイルが作成される。

f:id:redwarrior:20180808133608p:plain

初期設定のために「ConfigureAgent.cmd」を管理者として実行する。 コマンドプロンプトに表示された内容に従って、値を設定すると「settings.json」ファイルが作成される。

f:id:redwarrior:20180808134311p:plain

表示内容と設定値は以下の通り。

表示内容 設定値
ローカルエージェントの設定が更新されます 設定を更新したいので「Y」を入力
エージェント名 エージェント一覧に表示したい名前を入力する。PC名を含めると実行場所がわかりやすい
Team Foundation ServerのURL http://xxx:8080/tfsといったURL
どのエージェントプールに対して構成しますか? 作成したプールの名前(「VSPool」)を入力
エージェントの作業フォルダのパス 既定のまま
エージェントをWindowsサービスとしてインストールしますか? 今回は手動ビルドを試したいだけであり、エージェントも手動で起動・終了したいので「N」を入力

設定が完了すると、コントロールパネルのエージェントプールタブか、コレクションのプロファイル画面のエージェントキューにエージェントが表示される。

f:id:redwarrior:20180808134626p:plain

エージェントの起動

「RunAgent.cmd」を管理者として実行すると、コマンドプロンプトが開き、ビルドエージェントが起動する。

f:id:redwarrior:20180808135057p:plain

画面のエージェントの名の左端が緑色になる。

f:id:redwarrior:20180808135301p:plain

緑色になった状態でコマンドプロンプトを閉じると、画面のエージェントの名の左端が赤色になる。

ビルド定義の作成

ビルド定義の作成は簡単。+アイコンをクリックする。

f:id:redwarrior:20180808135652p:plain

画面上からVisual Studioを選択する。

f:id:redwarrior:20180808135814p:plain

リポジトリとブランチ、エージェントキューを選択する。作成したビルド定義は保存しないと残らないので注意する。

f:id:redwarrior:20180808135830p:plain

テンプレートに従って作成すると、最初にNuGetの復元を行うためにNuGetインストーラーが設定されている。必要なパッケージはリポジトリに登録済で、NuGetの復元は不要なのでビルドステップから削除する。

f:id:redwarrior:20180808140140p:plain

XAMLビルドでは、NuGetの復元をやめるためにビルドプロセステンプレートをカスタマイズしなければならなかったのでここは楽になった。

Visual Studioのビルドの設定にも「NuGet パッケージの復元」があるため、チェックされていないことを確認する。ちなみにNuGetの復元は別のステップになったので、ここのチェックボックスはチェックされることは基本的に無さそう。

f:id:redwarrior:20180808140338p:plain

ビルド以外にも様々な設定があり、ビルドステップも色々あるけど、上記以外は特に変更はしていない。保存アイコンをクリックしてビルド定義名を入れて保存する。

ビルドの実行

ビルドエージェントを起動した状態で、「ビルドをキューに挿入」をクリックする。

f:id:redwarrior:20180808140711p:plain

画面ではそのままOKを押す。

f:id:redwarrior:20180808140923p:plain

画面が変わりビルドが始まって、そのままビルドが成功した。ビルドが終了しても、エージェントを起動したコマンドプロンプトは開いたままなので、そのまま次のビルドを実行することも出来るし、終了する場合は、Ctrl+Cでコマンドプロンプトを閉じれば良さそう。

f:id:redwarrior:20180808141436p:plain

f:id:redwarrior:20180808141450p:plain

感想

エージェントプールの設定や、ビルドエージェントのインストールが多少手間がかかるけど、ビルドの実行自体はあっさりと成功した。

余談だが、画面コピーを取ってモザイク編集するのに、Monosnap というソフトを使ったら意外と便利だった。

参考資料

www.slideshare.net

*1:TFS 2018 Update 2では復活したみたいだが

Windows Server 2016 で WCF Data Services

Windows Server 2008 で動いていた WCF Data ServicesアプリケーションをWindows Server 2016に載せ替えたので、メモを残しておく。

WCF Data Servicesアプリケーションを発行し、アクセスすると404エラーが発生する

WCF Data Servicesの拡張子「.svc」がIISに認識されていないという事が以下のブログでわかった。

Publishing a WCF service on IIS 8gyorgybalassy.wordpress.com


直接設定すれば動きそうだけど、画面から設定できるのではないかと思って調査を続けたところ、Windows Serve 2012での設定内容を書いたブログがあった。WCF Data ServicesはHTTPで通信するので良さそう。

blog.livedoor.jp


検索キーワード(HTTPアクティブ化)がわかったので、Windows Server 2016の設定を探したところ、以下の複数のサイトが見つかったので書かれていた設定を行うことで、404エラーを無くすことが出来た。

qiita.com

.NET Framework 4.7が入っているケース。

WCF サービスで HTTP 404.17 エラー

一つ上のサイトからリンクされているページ。設定した結果がもう少し詳しくのっている。

symfoware.blog.fc2.com

タイトルにWCFの文字はないが、画面の画像付きで丁寧に説明されている。ASP.NETMVCではない)が動作する環境ではWCF Data Servicesも動作するようだ。

「現在のセキュリティ コンテキストでは、NT AUTHORITY\IUSR はデータベース にアクセスできません。」というエラーメッセージが表示される

WCF Data Servicesのトップ画面は表示されたが、個別のエンティティセットを表示しようとすると上記エラーメッセージが表示されてしまう。IUSR について調べてみると、以下のサイトに情報があった。

IIS のアクセス許可 - クリエイティブWeb

関連個所を引用すると

Windows Vista 以降、IUSR ユーザーアカウントをビルトインアカウントとして用意し、これを匿名認証のときに用いるようになりました。

そして

IIS マネージャーを使って、「IIS」の「認証」の「匿名認証」の編集で、匿名ユーザー ID をアプリケーションプール ID に設定すれば既定のIUSR を使用せずに、アプリケーションプール ID のみでアクセス許可の設定ができるようになります。

とあるため、 IIS マネージャーを開いて匿名認証の設定を確認すると、既定のユーザー(IUSR)になっていたので、アプリケーションプール IDに設定することでデータを表示することが出来た。

以上

おまけ

アプリケーションプール IDでデータベースにアクセスする設定は、過去記事参照。

redwarrior.hateblo.jp

ASP.NET MVC でチェックボックスのカスタマイズをCSSのみで行う。

ググると以下のようなサイトがヒットするが、そのままでは、ASP.NET MVC で動作しない。

cultureacademia.jp

なぜかと言うと、Form要素を作成するときは、HTMLタグを直接入力することはあまりせず、ビューヘルパー(@Html.***For)を使用することが多く、チェックボックスのビューヘルパーはinputタグを2つ作成するからだ。

その解決方法を調べたら、以下のサイトに載っていた。

stackoverflow.com

最初のサイトで使用していた隣接セレクタを使用する代わりに、間接セレクタを使用すれば良いということだった。奥が深い。

ちなみに、labelタグで囲む場合と、labelタグのfor属性を使用する場合があるが、labelタグで囲まない(labelタグのfor属性を使用する)場合は、HTML上はinputタグ、labelタグの順番で書く必要がある。

これは隣接セレクタ、間接セレクタ共に、○○の前という指定が出来ないからである。CSS4では出来るようになるらしい。

これだとデザイン上困ったことになりそうだが、inputタグによるフォーム(チェックボックス)は非表示にされるので特に困らない。

やはりASP.NET MVCの情報を探すには、stackoverflow(英語版)は必須だな。

以上

(小ネタ)IISのApplicationPoolIdentityでデータベースへのアクセス許可を設定する

以前にメモしていたのに、忘れていて余分な時間を費やしてしまったので、忘れないようにブログに残しておく。

以下のサイトを参考にWebアプリケーションを作成し、リモートのIIS上にデプロイする。

www.nuits.jp

Webサイトを追加した場合に設定を変更しなければ、アプリケーションプールのユーザーにはApplicationPoolIdentityが使用される。

WebアプリケーションからDBに接続するには、ApplicationPoolIdentityのユーザーでデータベースへのアクセス許可を設定する必要がある。

以下の2サイトを押さえておけば大体OK。

ASP.NET で MSSQL に Windows 認証で接続 - クリエイティブWeb

How to add the ApplicationPoolIdentity to a SQL Server Login – Eric Parvin(英語だけど、調べたことが全て書いてある)

以上。(ほとんどリンクだけど、リンク先が十分わかりやすいので、備忘録ということで一つ)

(小ネタ)SQL Server Management Studio (SSMS) のSQLフォーマットには、ApexSQL Refactor が良さげ

SQL Server Management StudioのSQLの書式をフォーマットするのに、SQL Server 2012の時は、「Poor Man's T-Sql Formatter SSMS & Visual Studio AddIn」を使っていました。

SQL Server 2014にも対応していたのですが、SQL Server 2016にはその時点では対応しておらず*1、代わりのソフトを探していて「ApexSQL Refactor」を使い始めました。

ApexSQL Refactor もインストールした時点では、あまり使いやすくなかったのですが、最近のアップデートでフォーマットの設定画面がわかりやすくなっており、細かい設定も可能になってだいぶ使いやすくなりました。

なので、SQL Server Management Studio (SSMS) のSQLフォーマットには、ApexSQL Refactor が良さそうです。

ちなみに、どちらもフリーです。

www.apexsql.com

architectshack.com

以上です。

*1:今回調べたら Poor Man's T-Sql Formatter SSMS & Visual Studio AddIn もいつの間にか最新のSQL Serverに対応していました。

NLogを使用して、開発環境と本番環境でログの出力先を切り替える設定について

問題

Webアプリケーション開発でNLogを使ってログ出力をしていて、本番環境に乗せることになった時に、開発環境と同じパスにログを出力できない事ってありますよね。

例えば、開発時はソリューション内のフォルダに出力していたけど、本番ではWebから参照できない場所に出力したりとか、他のソフトやシステムの連携のためにログの出力先が決められていたりとかです。開発環境、テスト環境、本番環境でログ出力先が異なるというケースもありそうです。
そういった場合にどうすれば良いのか?調べました。

調査

とりあえず、以下の公式ドキュメントを見てみたり、検索エンジンで調べてみましたが、NLog.configにはそういった設定はなさそうでした。(調べたのは少し前なので最新の情報では変わっているかもしれません)

github.com

対処方法

NLog.config→Web.configへの設定の移動

では、どうするか。今回使用した方法は、NLog.configを使わないという方法です。実は、NLog.configの設定は、Web.configに書くことが出来ます。

まず、先頭で、nlogセクションを使用する事を宣言します。

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- ↓この行を追加 -->
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
  </configSections>

次に、ファイルの最後にnlogセクションを追加します。(追加する場所はどこでも良いと思いますが、わかりやすいので最後にしました)

    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <!-- 以下の一連の行を追加 -->
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
      <target xsi:type="File" name="f" fileName="${basedir}/logs/current.log"
              layout="${longdate} ${uppercase:${level}} ${message}"
              archiveEvery="Day"
              archiveFileName="${basedir}/logs/archive_{#}.log"
              archiveNumbering="Date"
              archiveDateFormat="yyyyMMdd"
              maxArchiveFiles="3"/>
    </targets>
    <rules>
      <logger name="*" minlevel="Trace" writeTo="f" />
    </rules>
  </nlog>
</configuration>

ちなみに上記の設定は、以下の過去記事からコピーした内容です。

redwarrior.hateblo.jp

そして、設定が重複してしまうのでNLog.configを削除します。

この状態でアプリケーションを起動して、ログが出力されていることを確認します。

Web.config変換を使用した切り替え

いよいよ、開発環境と本番環境で切り替える設定ですが、Web.configに設定が書けるという事は、Web.config変換を使用することが出来るということです。
以下のサイトを参考にして、発行先ごとのWeb.config作成することで、発行時にNLogによるログの出力先を切り替えることが出来ます。

kkamegawa.hatenablog.jp

最後に、発行先ごとのWeb.config(Web.発行先プロファイル名.config)の内容をのせておきます。

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true">
    <targets>
      <target name="f" fileName="D:/WepApplicationLogs/current.log"
              archiveFileName="D:/WepApplicationLogs/archive_{#}.log"
              xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </targets>
  </nlog>
</configuration>

ログ出力パスとアーカイブ用のパスを変更しています。それ以外の設定は元のWeb.configの内容をそのまま引き継ぎます。(Web.config変換の機能)
発行先が複数ある場合でも、各ファイルの設定を変えることで対応できるのでなかなか便利です。
以上です。

(小ネタ)ASP.NET MVC でテキストボックスに小数を入力する時に日本語入力をオフにする方法

今回も以下に関連した話題。

redwarrior.hateblo.jp

二つ前の記事でも書きましたが、上記ではinputタグのtype属性が「text」になってしまうため、フォーカスが当たった時に日本語入力モードになってしまいます。

これだと数字を入力した後にいちいち確定しなければならないため、小数を入力するフォームが続いたりするとかなり面倒くさいです。これを解決する方法を調べました。

全てのケースで対応できる解決策ではないのですが、スタイルシートで制御できます。
以下のように、style属性にime-mode: disabledを設定します。

@* EditorForの場合 *@
@Html.EditorFor(model => model.Published, new { htmlAttributes = new { style = "ime-mode: disabled" } })


@* TextBox,TextBoxForの場合 *@
@Html.TextBox("Published", null, new { style = "ime-mode: disabled" })

テキストボックスにフォーカスが移ると、IMEが無効になるためtype=textのテキストボックスでも直接入力モードになります。

注意点1

IMEが無効にされた状態で、他の日本語入力が必要なテキストボックスがある場合、そのテキストボックスにフォーカスが移っても、そのままでは日本語入力が出来るようにはなりません。

日本語入力を可能にするためには、そのテキストボックスのstyle属性にime-mode: activeを設定する必要があります。(設定の仕方は上と同じです)

注意点2

全てのケースで対応できる解決策ではない理由は、これはリンク先で書かれているように、ChromeOperaSafariではサポートおらず、廃止予定のプロパティだからです。

developer.mozilla.org

今回の目的は小数の入力作業の効率化であり、Chrome等を使用することは想定していないため、この方法を取りました。
以上です。