Windows - 1 [Programming]
以前は、Windows ネイティブの開発が主だったのだけれど、最近は .NET Framework や Web アプリケーションのような(直接)Windows に関わらないような業務が増えてきている。開発環境としては Eclipse を使うようにもなってきたんだけど、やっぱり Visual Studio が馴染む感じがある。最近の Visual Studio は .NET Framework 以外の環境にも対応するようになってきているので、提供される全ての機能を把握するのは難しい(無理?)というのが率直な意見だったりもする。
休日に何の気もなしに Visual Studio を弄っていたら、 MFC(Microsoft Foundation Classes) のアプリケーションのサポートが続いていることが確認できた。MFC を現役で扱っていたのが Windows XP 全盛の頃(西暦 2000 年前後)なので相当の年月が経過しているのを実感した。
実業務とはちょっと離れ、あくまでも趣味のプログラミングということでネイティブな Windows プログラムを作ってみようと思う。素材はデスクトップに置くマスコット。ただの癒しではなく、ちょっとしたユーティリティとしての機能を盛り込んだものにするつもり。
以前、Windows XP 環境で使用する個人用のユーティリティとして作ったアプリケーションのリメイク版だったりする。当時の実行ファイルは現環境(Windows 10)でも動作可能であることは確認できているのだけれど、多くの外部ライブラリに依存してしまっている関係で再ビルドができなくなってしまっていて機能追加ができない。そこで、外部の依存関係を排除し作り直してみようと思う。
久しぶりに MFC アプリケーションのスケルトンを見た感じは、「懐かしい」の一言。.NET Framework のようなライブラリに比べると設計が古い感じは否めないし、提供される機能は少ない。多くのことを自分で構築しなければならないので、作業効率を考えたら今更感が先行してしまう。
現役だった頃は把握していたつもりのノウハウや制限に関して、年月の経過とともに忘却の彼方となってしまったことも含め、新しいモノに触れたような感触が楽しかったりする。
仕事から帰った後の趣味のプログラミング、サンデープログラマをしばらく楽しんでみようと思う。
SharePoint 開発 [SharePoint]
SharePoint の開発に携わるようになって数か月、なんとなく見えてきた現実がある。それは、、、まともな情報が見つからない。
SharePoint 2013 .NET サーバー API リファレンス
SharePoint 2013 .NET クライアント API リファレンス
開発を進めるためにはほぼ必須ともいえるリファレンス。残念なことに、ここから辿れる情報はメソッドの名称とサンプルだけ。サンプルがあれば「使い方」はなんとなくわかるけど、「何」をするためのメソッドなのかはは全く解らない。翻訳精度が悪いせいで情報が抜け落ちてしまったのかと考え、英語版の情報を見てみたけど、大差ない模様。
Collaborative Application Markup Language のコア スキーマ
Collaborative Application Markup Language (CAML) Structure
SharePoint に関わろうとすると、どうしても避けられないのがこの CAML。SharePoint の動作原理が解らないと読みこなすのに一苦労する。
その他、非公式(Microsoft 以外)の HP やブログの情報も大して役に立たない。公式サイトで得られる情報以上のものはまず見つからない。基本的には公式 HP と同じで基本的な情報を持ち得ていることが前提となっているようで、初心者がちょっと覗いた程度だと理解できない。まあ、ココも同類だとは思う。
唯一使えそうなのが stackoverflow をはじめとする掲示板(質問サイト)。とは言っても、欲しい情報が 100% 得られるわけではなくヒントがもらえる程度。残念なことに、迷宮入りしてしまう案件も少なくなく、日本語のサイトは使い物にならないことが多い。
そして最後に至ったのは 、「情報が見つからなければ、検証して突き止めるしかない」ということ。幸いにも SharePoint は PowerShell との相性がいいようだ。アセンブリさえ見つけられればある程度は使える .NET Framework の特性が結構生かせる。
Microsoft SharePoint のネームスペースさえ取り込んでしまえば(GUI は使えないけれど) ある程度の機能の検証が可能になる。そのために必要になるのが以下の 2 行。
[void] [Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint");
$sp= New-Object Microsoft.SharePoint.SPSite("https://localhost/");
あとは、ハッカーにでもなったつもりで探っていくのが手っ取り早い。SharePoint Server のインストールしてあるサーバーにログオンして、PowerShell を起動する。そして、上記のコードを実行すれば、(多くの)Server Side の機能を検証することができる。
IDisposable [Programming]
.NET Framework の環境で開発をしていると結構な割合で出てくるこのインターフェース。公式な文書以外にも Tips として情報が公開されていることからも分かる通り、結構ややっこしいインターフェースだったりする。IDisposable インターフェースの定義そのものは下記の通り。
Namespace System
'
' 概要:
' アンマネージ リソースを解放するためのメカニズムを提供します。
Public Interface IDisposable
'
' 概要:
' アンマネージ リソースの解放およびリセットに関連付けられているアプリケーション定義のタスクを実行します。
Sub Dispose()
End Interface
End Namespace
IDisposable が解りづらい最大の要因は、これがインターフェースだということにある。インターフェースは見かけを指定することはできるけど、実装を強制することができないから。単に IDisposable インターフェースの要件を満たす実装をするだけならコレでもいい。
Class Test
Implements IDisposable
Public Sub Dispose() Implements IDisposable.Dispose
End Sub
End Class
ただ、コレではなんの意味もないということは考えないでも解るだろう。IDisposable の使用目的(アンマネージ リソースを解放するためのメカニズムを提供します)に合わせた実装にするには多少手を加える必要があるのだけれど、ここでは先人の知恵を拝借するのが間違いない。Visual Studio の吐くコードはこんな感じになる。
Class Test
Implements IDisposable
Private disposedValue As Boolean ' 重複する呼び出しを検出するには
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
End If
' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
' TODO: 大きなフィールドを null に設定します。
End If
disposedValue = True
End Sub
' TODO: 上の Dispose(disposing As Boolean) にアンマネージ リソースを解放するコードが含まれる場合にのみ Finalize() をオーバーライドします。
'Protected Overrides Sub Finalize()
' ' このコードを変更しないでください。クリーンアップ コードを上の Dispose(disposing As Boolean) に記述します。
' Dispose(False)
' MyBase.Finalize()
'End Sub
' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
Public Sub Dispose() Implements IDisposable.Dispose
' このコードを変更しないでください。クリーンアップ コードを上の Dispose(disposing As Boolean) に記述します。
Dispose(True)
' TODO: 上の Finalize() がオーバーライドされている場合は、次の行のコメントを解除してください。
' GC.SuppressFinalize(Me)
End Sub
End Class
Visual Basic では、IDisposable インターフェースを実装を定義(Implements IDisposable と記述し Enter キーを押下)した瞬間に必要なフィールド及びメソッドがすべて展開されるので、あとは TODO に必要な処理を追加してやればいい。コメントに今一つ意味不明な単語があるけど、とりあえず横に置いておいて、多くの場合ハイライトした部分だけが必須で、それ以外はほぼ不要ということで問題ないはず。
.NET Framework においては、ガベージコレクションの対象とならないオブジェクトをアンマネージド リソースと呼ぶ。メモリ以外のオブジェクトを指すと考えて問題ない。ファイルを扱う際のファイルハンドルやデータベースのコネクションなどがこれに含まれる。
注意しなければならないのは、上記のソースコードに含まれる、マネージ オブジェクトやアンマネージ オブジェクトという単語はコレとは少し違うということ。
例えば、System.IO.FileStream というクラスがある。このクラスはファイル ハンドルをカプセル化し、ファイルに対する各種のオペレーションを提供するもの。System.IO.FileStream の実装としては、OS の提供するファイルハンドルを管理する必要があるので、直接これを操作しているものと想像できる。上述の通り、ファイル ハンドルはアンマネージド リソースなのだけれど、アンマネージド リソースを管理する System.IO.FileStream というクラス(のオブジェクト)はマネージ オブジェクトという扱いになる。
なので、アンマネージ オブジェクトを意識することはあまり(絶対ではない)ないと考えられる。
さて、ここで上記の Test の派生クラスを定義する場合のことを考える。そこでも IDisposable の機能を定義したいとしたらどうしようか?この時に基本クラスの実装には手を付けないのが前提。
解答だけを示すならこうなる。
- 派生クラスでは IDisposable インターフェースの再実装をしない。
- 派生クラスで Dispose(disposing As Boolean) メソッドをオーバーライドする。
処理は上記と一緒だけれど、以下の変更を施す必要がある。- Overridable を Overrides に変更する。
- メソッドの最後で基本クラスの Dispose(disposing As Boolean) メソッドを呼び出す。
- disposedValue フィールドは、基本クラスで定義されているものを流用しちゃいけない。
もともと Private になっているので問題ないだろうけど、これを書き換えて無理やりアクセスしないこと。
要は、既に実装されている Dispose( ) メソッドから、独自の実装を施した Dispose(disposing As Boolean) を呼び出してもらえるようにするだけ。
これだけなら、単に仮想メソッドによる機能の追加になるのだけれど、よくよく見ると大きな問題が隠れている。
IDisposable インターフェースによって仕様が決められているのは、Dispose( ) メソッドだけであって、独自に定義し、派生クラスでオーバーライドした Dispose(disposing As Boolean) に関する仕様はどこにも明示されていない。
今回は基本クラスも派生クラスも自作しているので、Dispose(disposing As Boolean) の仕様はわかるけれど、前提が変わってしまった場合には上記の実装は結構危ういものになってしまことがわかる。Visual Studio のような開発環境を使用していると、メソッドのシグネチャ等の情報も提供してくれるけれど、実装については正確にわからない可能性もある。
上記は Microsoft が定めるガイドラインに沿った記述であり、Microsoft 謹製のツールが吐くコードなので問題になることは多くはないと思うけど、基本クラスを他者が作成している場合等も考えると絶対安全とも言えないところがある。
今更ながらではあるけど、今回のサンプルコードは Visual Basic のものを採用している。C# を使っても同様のコードを記述することも可能だし、Visual Studio がスニペットの挿入をサポートしているのでその機能を利用することも可能。ただ、その時にいくつかの選択肢が提示される。「Dispose パターンを使って(明示的に)インターフェースを実装します」を選択してやらないとなんの機能も実装していない Dispose( ) メソッドが構築されてしまう。Visual Basic ではなんの選択肢も提示されずにガイドライン通りのコードが生成される。紛れがなくていいのか、なんでもできるのがいいのか、好みの別れるところであるとは思うけど、、、。
Provider hosted SharePoint Add-in - 3 [SharePoint]
単純にプロバイダー ホスト型の SharePoint アドインを構築すると独自の書式を持ってしまうため、統一感のない画面になってしまう。今回は、アドインの書式を SharePoint に合わせる方法。
今回の元記事はコレ。 ただし、オリジナルは Web フォームを使用しているので、MVC のプロジェクトで同様のことができるように変更している。
- MicrosoftAjax
[ツール] - [NuGet パッケージマネージャ] - [ソリューションの NuGet パッケージの管理] を実行し、MicrosoftAjax を Web アプリケーションプロジェクトに追加する。 - ChromeLoader
左記の元記事にある ChromeLoader.js をファイルとして保存し Web アプリケーション プロジェクトに追加する。ここでは、Scripts フォルダに配置しています。
参考
こちらに英語版の記事のアーカイブが公開されているようです。当該ファイルをダウンロードして利用できます。- 26 行目付近で、appIconUrl の設定を行っているのですが、単純なファイル名("siteicon.png")ではなく絶対パス表記("/siteicon.png")に変更した方がよさそうですね。
- _layouts.cshtml
以下のように書き換えます。ハイライトが修正箇所、取り消し線は削除します。<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - マイ ASP.NET アプリケーション</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
<script type="text/javascript" src="~/Scripts/MicrosoftAjax.js"></script>
<script type="text/javascript" src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="~/Scripts/ChromeLoader.js"></script>
</head>
<body>
<div id="chrome_ctrl_placeholder"></div>
:
略
:
</body>
</html> - アイコン
Web アプリケーション プロジェクトのルートにサイトのアイコンをsiteicon.png という名称で配置します。 - 実行
サイトのデザインを変更すると、、、適用される。
ASP.NET MVC のサンプルコードにあったスタイルシートを外してしまっているので、書式が崩れてしまっているのだけれど、代わりに SharePoint の書式が適用されている。なお、この段階では Account Settings、Contact us および Help のリンクは機能しませんので注意。
ちなみに、アドイン プロジェクトの AppManifest.xml のクエリ文字列に、&SPHostTitle={HostTitle} を追加してやると、ウィンドウ左上にある Back to Site となっているところがサイト名に変化するようになります。
Provider hosted SharePoint Add-in - 2 [SharePoint]
プロバイダーホスト型の SharePoint アドインを、Web パーツとして表示する手順。前回に引き続き、コードの編集は含まれていない。
Visual Studio 2015 を使用して SharePoint アドインを作成する手順は大して難しいものじゃない。ただ、出来上がったアドインを実行させてみると別窓で表示されてしまうので、なんとなくガッカリ感が拭えない。
アドインを Web パーツとして取り込むことで、それらしく見えるようになるので、手順を紹介する。
- Web パーツ
SharePoint アドインを作成するためのプロジェクトを作成すると、実際には 2 つのプロジェクトからなるソリューションが構築される。1 つは ASP.NET Web アプリケーションで、もう 1 つが Web パーツのアプリケーション。ASP.NET Web アプリケーションのほうは、SharePoint アドインの本体を実装するプロジェクトで、テンプレートに従ってある程度のアプリケーションの体をなすようになっているのに対して、Web パーツのほうは殆ど空の状態(単純にASP.NET Web アプリケーションをキックする設定になっている)のものしか提供されない。今日の手順では、ここに手を入れる。
ソリューション エクスプローラー上で当該プロジェクトのコンテキスト メニューから [追加] - [新しい項目] と辿り、[新しい項目の追加] ダイアログで、[Visual C# アイテム] - [Web] - [Office/SharePoint] と辿って [クライアント Web パーツ(ホスト Web)] を選択する。 - Web パーツ コンテンツ
[クライアント Web パーツのコンテンツのために、既存の Web ページの URL を選択するか入力します] を選択して、エディットボックスには ~remoteAppUrl/?{StandardTokens} と入力する。
これが Web パーツ内に表示する ASP.NET Web アプリケーションのリンク情報になる。 - AppManifest.xml
ソリューション エクスプローラー上で AppManifest.xml をダブルクリックして開く。そして、スタートページに サイトの URL を指定する。 - 起動
これで準備はできた。デバッグ実行すれば 3. で指定したサイトが表示されるようになるはず。あとは、当該ページに Web パーツを埋め込んでやれば完了。
環境によってはセキュリティの設定を変更する必要があるかも。
Provider hosted SharePoint Add-in - 1 [SharePoint]
Visual Studio 2015 を使用して、プロバイダーホスト型の SharePoint アドインを作成する手順。
アドインは ASP.NET MVC を使用して作成するものとします。今回の手順では、ウィザードが生成するアプリケーションをそのままアドインとして表示するだけで、 処理のカスタマイズは含まない。
環境
オンプレミスに SharePoint Server 2013 を展開していて動作可能な状態になっている。既に開発者向けサイトも構築済み。
Visual Studio 2015 は、SharePoint Server 2013 とは異なるホストにインストールしてあり、Office Developer Tools for Visual Studio 2015 もインストールしてある。
- 開始
[ファイル] - [新規作成] - [プロジェクト] と辿り、プロジェクトを作成する。環境によっては多少異なるかもしれない。 - SharePoint アドインを選択
[テンプレート] - [Visual C#] - [Office/SharePoint] - [Web アドイン] と辿り、目的のテンプレートを選ぶ。
- SharePoint の開発者向けサイトを選択
- オンプレミスの SharePoint 2013 を選択
- ASP.NET MVC Web アプリケーションを選択
ASP.NET Web フォーム アプリケーションでも特に問題はない。 - アドインの認証方法
開発用に自己署名入り証明書(オレオレ証明書)を作成、エクスポートして、2. で作成したソリューションの下にコピーしてきて利用する。パスワード、発行者 ID は適当、、、いい加減。
ここで、[完了] をクリックすれば作業は終わり。このあと ビルドして、デバッグ実行すれば、作成されたアドインが実行される。 - 実行
初回実行時にはこんなメッセージが表示される。とりあえず、[信頼する] を選択しないと先に進めないから受け入れる。
ここで表示されるのが SharePoint の開発者向けサイト。ちなみに、ウィンドウ右上に表示されているアカウントを確認しておこう。 - 処理中
- アドイン
素の状態のアドインが起動される。ASP.NET Web アプリケーションの見た目によく似ているけれど、よく見ると SharePoint のアカウントが表示されるようにカスタマイズされている。
アドレスバーを見ると、SharePoint の開発者向けサイトとは異なるサーバー(IIS Express)でホストされているのがわかる。
Eclipse [Programming]
Apache, MySQL, PHP で構築する AMP ソリューションに喧嘩を売っているような IIS, SQL Server, PHP の環境が組みあがった。
ただ、このままだと Hello World (に毛の生えた程度) くらいしかできそうもないので、開発環境を導入しようと思う。
よく聞く Eclipse を日本語化したパッケージを公開しているので、それを利用させていただこうと思う。よくわからないので、最新版 (Neon) のフルセット (Ultimate - x64 Full Edition) をダウンロードしてきてインストール(zipを展開するだけ)してみた。
PHP のバージョンが 5.6.21 となっているようなので、これを新しいものに差し替える。Hello World にブレークポイントを仕掛けてデバッグすると、停止できるところまでは意外にすんなり通った。
PHP 再び [Network]
http://windows.php.net/ のサイトを覗いてみたら、PHP のランタイムがバージョンアップしていた。以前、ここで取り上げた時には 5.5 だったのが 7.0 まで進化してしまっていて、殆ど浦島太郎になった気分...と思ったら、なんか 6.x はスキップしているようなので、ちょっと安心。
古いままでも特に困るようなこともないのだけれど、見つけてしまったからにはインストールくらいはしてみようと思う。PHP のランタイムは、システムの設定(レジストリ等)を書き換えるわけでもないようなので、異なるバージョンを共存させることは可能みたいだけど、一応サラの状態に構築してみる。
ザックリとした手順は以下の通り。
- IIS (Internet Information Services)
IIS の上で PHP を稼働させたいのでコレは必須。サーバーマネージャーの役割と機能の追加(サーバー)あるいはコンパネのプログラムと機能(クライアント)がら Web サーバー (IIS) を追加する。必要なオプションとして、[Web サーバー] - [アプリケーション開発] 以下にある CGI を追加してやればいい。 - SQL Server
これも上記と同じ理由で必須。取り合えず、細かいこと考えずにフルインストールしちゃった。 - PHP 7.0
http://windows.php.net/download/ のなかで一番新しそうなパッケージのうち Non Thread Safe となっているものをダウンロードしてきてインストール。インストールとは言ってもインストーラーパッケージは提供されていないため、zip を解凍して配置後、設定ファイルを自分で書き換える必要がある。
書き換えが必要な情報は、PHP on Windows ガイドライン の 4 章の情報で大体大丈夫。 - SQL Server driver for PHP
PHP から SQL Server を使用するためのドライバーはここにある。製品候補という事なので、正式版が公開されたら差し替えたいと思っている。このバージョンから(?) x64 と x86 の両方が公開されるようになったみたい。一応、両方とも試してみたけど(サンプル程度の動作では)問題なかった。 - ODB Driver
SQL Server driver for PHP が使用するらしい。検証時点で ODBC Driver 13 は Preview 版のみの公開だったので、ちょっと古い ODBC Driver 11 で動作を確認してみた。
半壊 [Network]
SharePoint Server を LAN に導入しようと準備をしていたのだけど、チョットした災難に見舞われて作業が滞っている。検証用に使用している自宅の LAN 環境では、(外部に公開はしていないものの)色々とサーバーを稼働させている。ホストの数がかなり多いので Active Directory も勉強を兼ねて展開している。Microsoft のサーバー群は Active Directory が前提となっているものも結構あるので(Exchange Server や SharePoint Server がそう)結構重宝していた。
今回、Active Directory を担うサーバーを含む数台(仮想環境で構築していたのだけど、ホストがコケるとゲストは全滅しちゃう)のサーバーがお釈迦になってしまったことで、ネットワークが半壊状態に陥ってしまった。
障害状況は下記の通り。
- Domain Controller(Active Directory Domain Services)
Active Directory 自体の恩恵なんて普段はあまり実感しなかったんだけど、使えなくなってみるとその効果がよくわかる。というか、これがないとなにもできなくなってしまう。さらに悪いことに、今回は FSMO の 5 要素を一手に引き受けていたホストが被害にあってしまったために「役割の強制」を実施することになってしまった。MCP を受けるときに一応は勉強したけど、実施したのは初めて。結構ドキドキものだった。 - Windows Deployment Services
今回、改めて気づいたんだけど、ウチのネットワーク環境には常時稼働状態にある DVD/BD というのが存在しない。殆どのソフトは ISO 形式で保存しているし、OS は常に WDS を使用したネットワークブートで賄っている。WDS を Domain Controller で動作させていたため、一緒に使えなくなってしまった。仮想マシンは ISO から直接インストール可能なんだけど、物理マシンはそうもいかない。 - Hyper-V
物理マシンは全て Hyper-V を稼働するサーバーになっている。1 台コケると 10 台近いサーバー群が一気に利用できなくなるのは結構イタい。とはいっても、仮想環境を利用せずに今の環境に近いものを構築するのはちょっと無理。チョットした教訓にはなるかも。運用を生業にする気はないけど。 - Active Directory Certification Services
Active Directory の環境で、かなり過保護に育てられるのがこの子。一度構築してしまうと、転身することができなくなる証明書サービス。業務用として利用しているわけではないので、壊れてしまったら別の証明書サービスを建てたらすむのだけど、結構な手間がかかることを実感した。 - Windows Server Update Services
Windows Update を中継するだけの割にディスクをバカ食いするこのサービス。常時 2TB のディスクを割り当てるようにしていたのだけど、無くなってみるとネットワーク負荷削減には結構効果があったのだと感じる。新規インストールする環境が多くなると覿面に現れる。 - Dynamic Host Configuration Services
ブロードバンドルーターが DHCP をサポートしていることが多いのだけど、上記の WDS が必要としていたために導入していた。一応 2 系統展開していた(スコープは異なる)ので、IP を求めることはできていたのだけど、デフォルトゲートウェイに死んだサーバーを指定していたため、結局はネットワークが麻痺してしまった。
なんだかんだ言っても、Active Directory が逝ってしまったのが痛い。軒並み名前解決ができなくなり、RDS(Remote Desktop Services) が通らないし、Hyper-V マネージャも繋がらない。ホストにキーボードとマウスを繋げるなんて何年ぶりだったろうか。
一応、仮想マシンのバックアップはとってあったので、バックアップからの復旧は可能な状態ではある。ただし、復旧するか、新たに構築するか、ちょっと考えようと思う。復旧しなければならないような情報がないということが解ったので、この際、新しいバージョンにしてしまおうかと思案中。
return [PowerShell]
他のプログラミング言語と同様に PowerShell にも Return ステートメントは存在する。PowerShell では明示的に Return ステートメントを使用しなくても(複数の)値を返すことができるために、無くても困らないかもしれない。
ただ、PowerShell の Return ステートメントはかなり癖がある。PowerShell を使い始めた頃から気になってしようがなかったのだけど、誰も指摘しない、、、あまり気にしないのかなあ。なんか、こんなシチュエーション多いなぁ。
下記のスクリプトを動作させたときの結果を正確に予想できますか?
0..9 | %{
foreach ($i in 10..19) {
return $i;
}
}
---
0..9 | %{
10..19 | %{
return $_;
}
}
---
foreach ($i in 0..9) {
10..19 | %{
return $_;
}
}
---
foreach ($i in 0..9) {
foreach ($j in 10..19) {
return $j;
}
}
私は未だに迷うことがある。