2011年12月29日木曜日

GData API を利用して Google カレンダーに予定を登録する

前回は Google ドキュメントのスプレッドシートに対して操作してみたので、次はカレンダーに予定を登録してみます。

GCal1

2011年12月26日月曜日

GData API を利用してスプレッドシートの値を取得する

Google Document では多くの API が提供されており、それを用いる事で Google が提供しているサービスへのアクセスを比較的簡易に行う事ができるようになっています。今回は色々理由があったのもあり、スプレッドシートに書かれている値を取得する、というのを行ってみました。

2011年12月23日金曜日

Powershell 3.0 と Workflow Foundation

※これは PowerShell Advent Calendar 2011 用の投稿です

PowerShell の最新版 3.0 では多くの機能強化が行われています。あまり深くチェックしていなかったのですが、@mutaguchi さんのツイートから興味を持って調べてみると、WF の機能を PowerShell から利用したり、逆に PowerShell の機能を WF で利用することができるようになっていました。 3.0 では多くのクラスが追加されており、半分ほどは WF で PowerShell を利用できるようにしたアクティビティクラスです。内部的に PowerShell のコマンドレットを Invoke で呼び出しているとの事で、これを利用することにより既存 PowerShell スクリプトのワークフロー化というのも可能になっています。

2011年12月21日水曜日

VB6 でもクラスは役に立つ

※これは VB Advent Calendat 2011 用の投稿です

元々私は VB2 からの VisualBasic プログラマだったりします。お仕事としても VB を利用していますが、まだまだ VB6 は廃れないなー、というのが率直なところです。

VB6 を利用されている場合、言語上の仕様もありあまりクラスを利用するメリットが見いだせないかと思われます。特定のケースに限り利用するだけで、結構使われていない。または使った事のない方も多いのではないでしょうか。ですが、VB6 でもクラスを利用する事で役立つことは多くあるのです。

CLR/H 第 65 回勉強会レポート

PC170640

12/17 に行われた CLR/H 勉強会のレポートです。今回は昨年のカソウ化デイで好評?だったかもしれないことがなきにしもあらず、という事があり、ハイパーカソウ化デイとして「仮想化の話題を扱う」予定だったものが、フタをあけてみると仮想化の話ほとんどないよ!という楽しい勉強会になりました。

2011年12月19日月曜日

CLR/H 第 65 回勉強会で利用した LT スライド

今回の勉強会にて利用した LT のスライドをアップしておきます。

今回の内容は WMI + WF で運用管理作ろうよ、という内容でした。今後登場する PowerShell 3.0 によってその流れはますます加速すると思います。

2011年12月16日金曜日

文字列で指定した VB ソースを実行する

※これは VB Advent Calendat 2011 用の投稿です

Workflow Foundation では Assign アクティビティに代表されるように色々なアクティビティにて VisualBasic 構文を用いた記述が利用できます。この仕組みを利用すると、テキストファイル等に保存した VisualBasic ソースをそのまま解析し実行させることが可能です。

2011年12月9日金曜日

VB の xaml と C# の xaml

※これは VB Advent Calendat 2011 用の投稿です

ネット上で調べ物をしていると C# で書かれている記事に出会う事が多々あると思います。基本的なロジックは、コード変換を行っているサービスを利用するなど C# を知らない人でもどうにかする方法が用意されています。ですがコードだけではなくxaml 上でも C# と VB では違いがあります。

2011年12月5日月曜日

MethodInfo からのインテリセンス用ヒント文字列の生成

現在 α 版としてですが、インテリセンスにある程度対応した状態にて WF Designer Express をアップさせてもらっています。インテリセンス自体もまだまだ改良中ですが、その際に表示するツールチップヒントの文字列生成というのが、なかなかよく分かっていなかったのでまとめてみました。

2011年11月23日水曜日

CLR/H 第 64 回勉強会レポート

11/19 に行われた CLR/H 勉強会のレポートです。今回も前回に続き Deep Dive! な回ということもあり、深い話が多い回となりました。

PB190586

2011年11月22日火曜日

IExpressionEditorService と IEXpressionEditorInstance でインテリセンスの導入

ある程度 WF の ExpressionTextBox で式や値の入力中にインテリセンスを利用するように実装できてきたので、その利用方法や注意点をまとめてみます。

まず WF での ExpressionTextBox におけるインテリセンスサポートですが、Visual Studio 上でワークフローを触られている場合は Visual Studio が提供するインテリセンスが自動で利用されています。しかし再ホストを行っているケースでは、自前でインテリセンス部分を用意しなくてはいけません。海外 MSDN だと VIsual Studio のアドイン Dll をそのまま利用してしまえという豪快な方法を目にすることがありますが、配布が出来ませんので自分一人の環境で利用する場合のみ許される方式です。

2011年11月19日土曜日

CLR/H 第 64 回勉強会での LT スライド

本日 11/19 に行われている CLR/H 第 64 回勉強会にて発表した LT スライドを公開します。今回は WF を利用して WPF アプリを作ってみよう、という題材です。もう少しあれこれできれば、ノベルゲーなら十分作れるんじゃないかな、と思いますw

2011年11月15日火曜日

ワークフロー上のアクティビティを非同期に複数動作させるには

原則として Workflow Foundation は非同期にて動作しますが、俗に言うマルチスレッドにタスクを分配して動作するような挙動は行いません。Parallel アクティビティというのもありますが、これも内部ではシングルスレッドで動作しており、待ち状態が発生した際に制御を切り替えるというものになっています。

このあたりで色々考える人は多いのですが、海外の Blog ですばらしいサンプルを見つけたので VB に移植してみました。

2011年11月9日水曜日

属性指定から IRegisterMetadata.Register へ

前回の LocBAML を利用した記事にあるように、現在拙作の WFDesignerExpress を多言語対応(といっても機械翻訳での対応ですが……)を行っています。その際に非常に感じたのは、クラスやプロパティに対して属性を設定するのではなく、IRegisterMetadata.Register メソッドにて属性の設定を行うようにするのが、WPF や WF でのプログラミングを行う際に適している、というところです。

2011年11月7日月曜日

.NET 4 における LocBAML を利用した多言語対応

アプリケーションの多言語化対応というのは、人によっては必要な作業だと思います。MSDN でもローカライズ関係の資料が色々と掲載されており、その中の一つの方法として LocBaml ツールを利用したローカライズがあります。

2011年11月6日日曜日

InArgument(T) から String への変換

アクティビティを色々作成している中で、次のようなケースがありました。

  • デザイナ上で指定した画像のイメージをデザイナ上にプレビュー表示する

アクティビティのプロパティとしてファイル名を受け取るとして、そのファイル名で指定された画像をデザイナ上でプレビュー表示をする、というものです。その際にプロパティが String で指定されているのであればまだ簡単なのですが、アクティビティの場合ほとんどのプロパティは InArgument(T) を指定することもあり、値の変換には少し方法を変える必要があります。

2011年11月4日金曜日

Zip 圧縮を外部ライブラリ無しで行うアクティビティ

WF でファイルやフォルダ操作を行う上で必要性を非常に感じているのが Zip 圧縮。バッチスクリプト等での定型処理でも結構使われているのではないでしょうか。

これを実際に .NET で行おうとすると何種類かの選択肢から方式を選ぶことになると思います。

  1. J# ライブラリを利用する
  2. DotNetZip 等の外部ライブラリを利用する
  3. Windows 標準機能を利用する

自分が今まで利用していたのは(1)の方法で、これだと MS 純正コンポーネントのみで済み、かつ結構楽な手段でサンプルもごろごろ転がっていたと思います。ところが、.NET 4 から J# を利用するというのが結構面倒でそのままでは利用できないため WF から利用するのは躊躇していました。
そうなると(2)か(3)なのですが、(2)のように外部ライブラリを利用するのは最も楽で安定するのですが、気持ちとして参照 Dll がどんどん増えていく事が嫌いというのもあり却下。必然的に(3)の方法となってしまいます。

2011年11月2日水曜日

MessageBoxIcon の値を IValueConverter で変換

メッセージボックスを表示するアクティビティを作っていて、デザイナ上でアイコンやボタンの設定をラジオボタンにて選択させようとした時、MessageBoxIcon 列挙値を変換するような IValueConverter を用意してあげれば、ラジオボタンにバインドができて非常に楽になります。ただし、その際に少しだけ注意する点がありました。

2011年11月1日火曜日

アクティビティの検証(2)

前回は属性による指定と CacheMetadata メソッド内部での検証ロジック実行という方法を利用しましたが、今回は制約(Constraint)による検証を行ってみます。制約とは MSDN にも記載されている通り「検証ロジックを含むアクティビティ」となっています。そのためコードだけでなく XAML によっての作成も可能です。

2011年10月31日月曜日

アクティビティの検証(1)

WF ではアクティビティの検証を行う方法が複数用意されています。単純に必須項目とするだけであれば、RequiredArgument 属性を利用する事だけで可能ですし、OverloadGroup 属性と組み合わせて必須項目グループを形成する事も可能です。

2011年10月27日木曜日

WF4 と WF4.5 における XAML 出力の違い

WF4 と WF4.5 では出力される xaml ファイルの中身がかなり異なっています。それに伴い、WF4 での一部問題も解決されています。

例えば Sequence アクティビティの中に WriteLine アクティビティを置いただけのワークフローにインポートの設定を行ったものを xaml に出力した場合、WF4 と WF4.5 ではこのように出力の違いがあります。まずは WF4 の場合です。

2011年10月25日火曜日

SourceLocationProvider.CollectMapping メソッドは WorkflowDesigner.Load(ファイル名) が必要

最近自作ツールのデザイナーをちまちまやっているのですが、その中で微妙な気持ちながらも未だに対応策が見えていない点が一つ。

ビジュアルデバッグトレースという感じに、ワークフローの実行状況をデザイナ上で表示するために色々やる必要があるのですが、その中に SourceLocationProvider.CollectMapping メソッドを用いてワークフローファイルの内容と実際のアクティビティの内容とをマッピングする必要があります。

2011年10月24日月曜日

VB6 でコンソールアプリを作る

今までずっとできないできないと思っていたところ、@rinta100 さんに教えてもらいました。まずはリンクを。

How to create a VB6 console program

詳しいことはリンク先を見てもらうとわかると思いますが、コンパイル時に明示的にライブラリのリンクを行う( LINK.exe /EDIT /SUBSYSTEM:CONSOLE ~)ことで、コンソールアプリを作成できるようです。

これは正直驚きました・・・!

2011年10月21日金曜日

アイコン等のリソースと IRegisterMetadata

前回の記事で、外部ライブラリを動的に読み込みそのリソースを登録する際に、IRegisterMetadata.Register メソッドを呼ぶ、というものを書きました。この方法は現時点で Microsoft としても推奨している方法です。アイコンやアクティビティデザイナ等、今までは属性を利用して設定していたのですが、この方法であれば別 Dll に分離することができるようになります。WPF ではよく見かける形ですが、WF においても同様の方法を用います。

なお、ここで言う IRegisterMetadata インターフェースは System.Activities.Presentation.Metadata 名前空間に属するもので、WPF で利用する Microsoft.Windows.Design.Metadata 名前空間に属する同一名称のインターフェースとは別になります。

2011年10月19日水曜日

外部ライブラリの動的読み込み(仮)

Visual Studio 上で行っている分には自動で参照設定を行った Dll からアクティビティをツールボックスに追加、リソースの読み込み等を行ってくれているので、特に心配する事はないのですが、リホスティングデザイナにてこれを行う場合、少し気を付ける必要があります。

2011年10月16日日曜日

CLR/H 第 63 回勉強会レポート

10/15 に行われた第 63 回勉強会のレポートです。今回は一部 Ust、Tweet 禁止な話題が含まれていたりということもあり、現場だからこその楽しさを感じられた回だと思います。

PA150533

2011年10月13日木曜日

10/15 第 63 回 CLR/H 勉強会で利用するスライド

第 63 回勉強会で利用するスライドをアップしておきます。当日までにもう少し追加・調整するかもしれませんが、とりあえずという事で。

今回は WF4.5 の新機能についてさらっと説明するショートセッションです。
時間の都合によっては懇親会中、アイスブレーク的にやるかもしれませんw

2011年9月30日金曜日

WF 4.5 用の SQL Server (Azure) 永続化構成

WF では SQL Server で永続化するための設定用スクリプトがあらかじめ用意されています。今回 WF 4.5 となるにあたり、ワークフローインスタンスのバージョン管理機能が追加されたこともあり、その構成に追加が行われていました。

2011年9月29日木曜日

起動時にワークフローの引数を設定する

CodePlex にて開発中のデザイナ、細かいところをアップデートしてみました。
今回はコンソール実行用モジュールにて引数をコマンドラインオプションで渡せるようにしてみまして、このあたりをやってみて気付いた点があったので記載しておきます。

2011年9月27日火曜日

WF4.5 でリホスティングデザイナの Load ができない

Windows 8 とともに .NET Framework 4.5 も開発者向けプレビュー版が用意されているので、これも暇をみて触っている最近ですが、リホスティングデザイナが全くどうして動いてくれません。

よく分からないのは、TargetPlatform を .NET 4.5 にしたから発生しているのではなく、.NET Framework 4.5 DP をインストールしている環境であれば、TargetPlatform は 4 でも 4.5 でも発生してしまうという点です。

2011年9月22日木曜日

Codeplex にアップしました

今まで CLR/H にてオープンにしていた自作の WF4 用のリホスティングデザイナー。色々思うところがあって、Codeplex 上にアップ、開発していく事に決めました。

ちなみに以前に見せた際にあった、クラウディアさん関係機能は OFF というかコメントアウトしてありますw

それと再配布回りを調べきっていない状態でのアップですので、近日中に v0.2 とする予定です。リボン周りとか確かダメだったよなぁ・・・。

2011年9月21日水曜日

Annotations によるワークフロー上のコメント

WF 4.5 になり追加された機能の中で、アノテーションというものがあります。簡単に書くとコメントを付箋のように付与できるとのことでしたので、実際にどのような感じになるかスクリーンショットを採ってみました。

2011年9月19日月曜日

CLR/H 第 62 回勉強会レポート

P9170401
9/17 に CLR/H 第 62 回勉強会が行われました。今回は WindowsPhone7 祭りとして、すべてが WP7 に関連する内容となっていました。

2011年9月16日金曜日

XBAP で WF デザイナー

以前、CLR/H 61 回勉強会の際に @jsakamoto さんに言われて気になっていたのを実際に試してみました。それは WF リホスティングデザイナは XBAP だと簡単にブラウザ上で利用できるんじゃないのか、というもので、聞いていて
「そういえば XBAP なんてあったなぁ、でも使ったことないから、WPF アプリとの差がわからんなー」
なんて思っていたので実際に試してみました。

2011年9月15日木曜日

WF 4.5 における新機能のオンオフ

MSDN にて WF 4.5 の新機能関係を調べていてこのような記述があるのがわかりました。

今回の WF 4.5 にて追加される機能については、自由に On / Off が行える感じです。

DesignerConfigurationService として提供されるこのクラスを通して、新機能(アノテーション、自動接続、パンモード・・・)の On / Off を制御するプロパティが提供されるとのことです。このあたりが、リホスティングしている場合に設定を行う箇所と思われます。

興味をひくのは、LoadingFromUntrustedSourceEnabledNamespaceConversionEnabled プロパティあたりですね。まだ開発者向けプレビューなので、今後変更されることも予想されますが、このような形での提供はありがたいですね。

Workflow Foundation 4.5 の新機能など

Windows 8 の開発者向けプレビューが登場したことに合わせて、.NET Framework 4.5 の情報も出始めてきました。MSDN にて色々書かれていますが、その中に Workflow Foundation の 4.5 における追加機能について記載があったので、意訳&勝手に解釈 してみます。

2011年9月14日水曜日

Windows 8 Developers Preview での VB6 アプリ

早速ダウンロード開始されていたので、Hyper-V上に環境を構築、VB6アプリの挙動を検証してみました。まだ本格的な検証は行っていませんが、軽く触った感じではかなり良好です。

2011年8月28日日曜日

CLR/H 第 61 回勉強会 TechParty 2011

P8270408
8/27  に行われた第 61 回勉強会のレポートです。今回は TechParty 2011 に参加し、札幌会場ということでの開催でもありました。

2011年8月22日月曜日

WF 標準アクティビティのアイコン

以前はアクティビティのインスタンスから逆に抽出して ToolboxIconWrapper クラスに指定するという、力技この上ない方法にて標準アクティビティのアイコンを表示していました。ところが最近、海外 MSDN Blog にて正式版とも言える方法が記載されていたので試してみました。

2011年8月19日金曜日

8/27 CLR/H 第61回勉強会 WF ハンズオン用の資料

※8/22 ご指摘いただいた表現誤りを修正しました


8/27 に行われる CLR/H 第 61 回勉強会のハンズオンとして、Workflow Foundation のセッションを行います。前回はスライドを用いた通常形式のセッションでしたが、今回は参加者が各自 PC を用意した上で実際に実装していただくハンズオン形式となります。
その際に参照していただく資料を用意しました。

当日はこの資料を元に、スライドも交えた形で行う予定です。 Ustream での中継も行いますので、遠隔地の方も是非参加してみてください。

2011年8月9日火曜日

WF をコードのみで利用する場合の注意

WF ではデザイナ上から利用するだけでなく、直接コードにて記述する事も可能です。その場合、各アクティビティに対して値を設定する場面で少し気を付ける必要があります。それはアクティビティコンテキストを用いた実行制御に関わる部分に、密接に関連があります。

2011年8月5日金曜日

標準アクティビティ+α でメール送信

Workflow Foundation を勉強するに当たり Microsoft からコードサンプルが提供されています。残念ながら英語のみで、サンプルの殆どは C# のみという VB 使いには厳しい現実ですが、その中で提供されている SendMail アクティビティのように、そのままでも結構使い出のあるアクティビティが存在しています。

2011年8月4日木曜日

標準アクティビティだけでファイル監視

あまりにも代わり映えのないタイトルが続いたので、今回からは Workflow で実行する内容をちゃんとタイトルに含ませるようにしますw

タイトルにもあるように今回実行するのは「特定のフォルダを監視してファイルが発生したら何かしらの処理を行う」という、フォルダ監視的なものです。

2011年8月3日水曜日

標準アクティビティだけで BAT ファイルを置換 (6)

タイトルが長いと面倒ですねw
今回は「フォルダ内にある、3 日前以前に作成されたファイルを削除」という処理を行ってみます。この処理を BAT ファイルで行うのは大変なのですが、需要はかなりあるのではないでしょうか。BAT ファイルのみで日付演算を行う事は、不可能ではないのですが非常に面倒です。その中でも楽に済ませたい場合は VBS を利用する事が多いと思います。

2011年8月2日火曜日

InvokeMethod アクティビティで利用できないメソッド

InvokeMethod アクティビティはこれまでかなり多用してきたことからもわかるように、非常に強力で「これさえあれば何でもできる」レベルのアクティビティとなっていますが、一部利用できないケースがある、というのがわかりました。

2011年8月1日月曜日

標準アクティビティだけで BAT ファイルを置換(5)

今回は BAT ファイルでループ制御を行うための FOR ステートメントを置き換えてみます。FOR ステートメント自体は非常に多機能で、単純なループ以上の事ができるのですが、まずは定番の「指定した条件に見合うファイル一覧を取得してループ」という形のものを置き換えてみます。

2011年7月29日金曜日

標準アクティビティだけで BAT ファイルを置換(4)

今回は BAT ファイルでどうこうしようとした場合に結構困る事の一つ、「今日の日付をファイル名に利用する」というのをワークフロー上で実現してみます。
BAT ファイル上でシステム日付を利用する場合は、一手間というか色々と小難しい書き方を利用します。

2011年7月28日木曜日

標準アクティビティだけで BAT ファイルを置換(3)

前回までで外部プロセスの非同期、同期実行が行えるようになったので今回は終了判定です。BAT ファイルで終了判定を行う場合は、環境変数の ERRORLEVEL を利用して判断することが多いと思います。

2011年7月27日水曜日

標準アクティビティだけで BAT ファイルを置換(2)

前回の記事で外部プロセスを起動するように Assign アクティビティを利用する方法を書きました。今回はそのようにして起動したプロセスが終了するまで待機させる方法を書きます。

BATファイル等で外部プロセスを起動する場合、かなりの割合で同期制御(終了するまで待機 = Start /w 等で実行)を行うのではないかと思います。これを普通にコーディングで実行するのであれば、次のようになります。

2011年7月26日火曜日

標準アクティビティだけで BAT ファイルを置換(1)

個人的に Workflow Foundation の適しているケースと感じている、BAT ファイル等でのスクリプトをどうすれば置き換えていけるか、というテーマで何回かに分割して書いていこうと思います。
BAT ファイル等で行われている処理内容は多岐にわたると思いますが、その中の一つ「別アプリケーションの実行」を標準アクティビティだけで置き換えてみようと思います。かなり力技です。

2011年7月24日日曜日

ファイル・フォルダ操作関係のアクティビティ

WF にてファイルやフォルダの操作をするアクティビティをある程度まとめて作ってみたので公開しておきます。各アクティビティにてやっている内容は非常に簡単なものなので、特に説明はいらないかと思います。なお、デザイナー上での直接入力にはまだ対応できていないので、次のアップデートなどで行う予定です。

ダウンロードはこちらから。

ジャンル

機能

ファイル

ファイルのコピー
  ファイルの削除
  ファイルの存在チェック
  ファイルのリネーム

フォルダ

フォルダの作成
  フォルダの削除
  フォルダのリネーム

一覧

ファイル一覧取得
  フォルダ一覧取得

その他

外部プロセス実行
  ファイルに文字列を出力

2011年7月20日水曜日

WF セッションのフォローアップ(2)

もう一つセッションで話せなかった話題について。

バッチスクリプトの置き換えは、WF を利用してみるのに適しているケース、とあの場で言いましたが、それを行うに当たり少し注意する点があります。

WF アプリケーション的なスタイルで行うには外部 AP 起動は問題ありませんが、WF サービスでこれを行おうとした場合に権限の問題が発生します。IIS を利用してサーバー上でプロセス起動、と同様の問題で IIS 等でホスティングしている場合、IIS の実行アカウントに権限を設定する必要が発生します。セルフホストを行う場合では、ホストするプロセスがサービスの場合は同様に、サービス実行アカウントに対して権限の設定が必要です。

2011年7月19日火曜日

WF セッションのフォローアップ

7/16 に行われたセッションでは色々喋りたくなってしまい、かなり駆け足になってしまい申し訳ありませんでした。このセッションにてもう少し話したいことがありましたので、セッションフォローアップという事にて記載します。

1:コンポーネント指向とは


言葉の定義としては、「ソフトウェアを機能ごとに部品として分割、必要に応じて組み合わせて利用する」、というような考え方になります。WF はこの考え方を実現する事に非常に適しています。それは「アクティビティ=コンポーネント」となり、「必要に応じて組み合わせる」事がデザイナの提供により非常に容易になっている事が大きな理由です。
通常の開発においても、適宜機能の分割を行いライブラリ化することはよくある事と思います。ですが、このライブラリを「必要に応じて組み合わせる」ことは、開発者でなければ難しいと思います。ですが、WF であればドラッグ&ドロップにてアクティビティを配置し、必要であればプロパティを設定する程度ですので、開発者でなくとも「必要に応じて組み合わせる」事が可能となります。
ポイントは「開発者でなくとも」です。この部分が WF の大きなメリットとなります。

2011年7月17日日曜日

第 60 回 CLR/H 勉強会 ~ WPF / WCF / WF 再入門デイ ~

7/16 に行われた CLR/H 第 60 回勉強会のまとめです。今回は雨の中多くの方に参加いただけました。

2011年7月16日土曜日

CLR/H 第60回 勉強会にて利用するスライド

7/16 に行います CLR/H 第60回勉強会にて利用するスライドをアップしておきます。



ダウンロードはこちらから。

2011年6月15日水曜日

WCF の拡張機能

現時点で WCF 用の拡張機能が何個か用意されています。

WCF Web API はよくある Web サービスを構築するための追加機能で現在 Preview 4 となっています。今まででも REST 形式の Web サービスであれば対応できているのですが、Web API の利用により、より最近らしい Web サービスの構築ができるようになるとのこと。話自体は去年とかからみかけていたのですが全く試していません。
どうやら今までの WCF Web サービスよりも HTTP に関係した部分で、より細かい制御を行えるようになる、とのことですが・・・。

jQuery Support はその名前の通り、WCF Web サービスを jQuery から利用しやすい形で構築できるようにするものです。元々 WCF Web サービス自体、.Net なアプリからのアクセスを主軸に置いていた点が大きく、それ以外のアプリからアクセスできるようにするには、基本 REST 形式の対応が必要でした。jQuery は非常に著名で多くの場面で利用されているので、この対応はかなり嬉しい人も多いんじゃないかと思います。

Express Interop Bindings は上二つとちょっと毛色が異なり、特定のアプリと接続するための設定や実装をより容易にするためのものです。そしてこれは VisualStudio のアドインという形での提供ですので開発者向けとなっています。現時点で対応を示しているのは次のものとなっています。

  • Oracle WebLogic
  • Oracle Metro
  • IBM WebSphere
  • Apache Axis2

Wizard 形式で設定できるらしい記述がされています。試そうにも残念ながらここで対象となるシステムが手元にないので、こればかりはどうしようかなぁ。

なお、試してみるのあたり一つ注意点が。

jQuery Support を利用するには WCF RIA Services の新バージョンが必要となります。恐らくほとんどの人は WCF RIA Servies V1 (SP1) がインストールされているかと思いますが、必要となるのは WCF RIA Services V1 SP2 となっています。そしてこれは Preview(April 2011) 版でのみ提供されていますので、この点だけ注意してください。

2011年6月2日木曜日

デザイナ上で複数行コメントを入力可能なアクティビティ

Twitter 上で @koty さんからこのような話が出たので作ってみました。
確かにデザイナ上というかワークフロー上にコメント的なものが用意できると見た目にわかりやすくなるなー、と思いながらとりあえず的な物としてですが・・・。

マルチコメント1

今回はデザイナー上で直接入力も行いたかったので、デザイナーの XAML とアクティビティのソースを記載します。

2011年5月31日火曜日

Azure Blob ストレージへ REST API にてアップロードするアクティビティ(仮)

ストレージ関係の REST API を暇を見つけながらちろちろやっている最中ですが、とりあえずアップロード(ただし条件付き)ができるところまではできましたので、恒例のアクティビティ化をしてみました。
条件付き、というのは本来ストレージへアップロードを行う場合には何点か考慮しなくてはいけないポイントがあり、現時点ではその考慮点の一部にしか対応できていないためです。何を考える必要があるかと言うと、次の点になります。

  • アップロードするファイルの容量

Windows Azure のストレージには大きくわけて 2 つの方式が提供されています。一つは BlockBlob と呼ばれる種類で、これは 64MB までの一つのファイル、または 4MB 単位に分割したファイル群という形でアップロードが可能です。分割するメリットは同時に複数セッションを利用してアップロード速度を向上させたり、エラー発生時のリトライ処理量を減らすなどがあたります。もう一つは PageBlob と呼ばれる種類でこちらは 1TB までのファイルを扱う事が可能な点と、バイト単位(イメージとしてはHDD等のセクタ)にて読み書きの処理が行える点がポイントとなります。現在ベータ版として提供されている Azure Drive (ストレージを通常の NTFS ドライブに見せかけて利用できる)は PageBlob をベースに作成されていると思われます。

2011年5月26日木曜日

Azure Storage REST API サンプル ~コンテナ関係~

Windows Azure Storage Services REST API という形で提供されている、REST 形式にて利用するストレージ関係のAPIの中で、コンテナ周りの API をアクティビティ化してみました。その際に色々分かったところもあるので、メモとして残しておきます。

コンテナ関係のAPI

List Containers 現在のコンテナ一覧を取得する
Create Container コンテナを新規に作成する
Delete Container コンテナを削除する
Get Container Properties コンテナの情報を取得する
Get Container ACL コンテナのアクセス制限を設定する
Set Container ACL コンテナのアクセス制限を取得する
Get Container Metadata コンテナにメタデータを取得する
Set Container Metadata コンテナにメタデータを設定する

カテゴライズした場合、もう一つ List Blobs という API もあるのですが、個人的にこれはBlob操作系と思っているので別の機会にします。

2011年5月25日水曜日

Azure Storage REST API の Authorization ヘッダ・改訂版

前回の記事で Auzre の Storage REST API で必須となる Authorization ヘッダの SharedKey 値の算出ロジックを記載しましたが、その後色々やっていくにつれ若干の修正が必要な事がわかりました。
変更点は今のところ1か所のみです。

2011年5月20日金曜日

Azure Storage 関係の REST API で利用する Authorization ヘッダ

現在 Azure のストレージ関係で利用する REST API を色々試行錯誤しながら試しているところですが、これら ストレージ用 REST API を利用するにあたり、真面目にやると物凄くよくわからない部分が Authorization ヘッダの SharedKey 値ではないでしょうか。
MSDN にある程度記述があるのですが、読んでいてもいまいちピンとこないというかさっぱりわかりませんw 色々と web 上の資料やサンプルコードを探しているうちに、海外サイトで丁度良いサンプルソースがあったのでこれを VB 用に移植したものを紹介します。

2011年5月19日木曜日

SQL Azure ファイアウォール管理 REST API のアクティビティ化

基本的に前回とほぼ同一ですが、SQL Azure のファイアウォール制御作成列挙削除)もアクティビティ化してみました。ファイアウォール制御 API 自体は特に難しいものでもなく、非常に簡単な形式となっています。メッセージ生成が必要なのも新規作成の際のみです。
前回同様ベースとなるクラスから。

2011年5月18日水曜日

SQL Azure Management REST API をアクティビティ化

SQL Azure には管理用の REST API が多数提供されています。
今回はサーバー管理用の REST API をアクティビティ化してみました。REST API 利用ですので、SDK 等の導入は一切必要ありません。
殆ど似た形になるので今回はベースクラスを作成し、各アクティビティはそれを継承する形にしています。まずはベースとなるアクティビティクラスから。

2011年5月17日火曜日

Windows Azure のサブスクリプション操作履歴を取得するアクティビティ

提供されている REST API の中にはサブスクリプションの操作履歴を取得するものがあります。それほど詳しく使ってはいないのですが今のところ管理ポータルからは見る事の出来ない情報になっています。
今回もいきなりソースを。

2011年5月16日月曜日

Windows Azure Management REST API でホスティング一覧を取得するアクティビティ

Code RecipeMSDN でサンプルが紹介されていたのでアクティビティにしてみました。
Windows Azure 管理ポータルで目視できる内容ですが、定期的に監視などする事を考えるとスクリプトまたはプログラム化する必要が高くなります。また SDK でマネージド DLL 等も配布されていますが、端末にそれを入れるのも億劫ですw
そのような場合は、REST API が提供されているのでこれを利用した監視等々を行う事になるかと思います。実際に REST API を利用するには一つだけ事前準備が必要です。
  • 管理用証明書を作成、設定する

当然と言えば当然ですが、アクセス制限を行うために Windows Azure ではクライアント証明書を利用します。証明書自体は正規のものを購入する、makecert ユーティリティで作成するなど方法があります。今回は makecert ユーティリティで作成しました。その際 MSDNSE の雑記 さんのところを参考にさせてもらいました。ありがとうございます。
できあがった証明書は自分の環境にインストール(作成した cer ファイルをダブルクリック等で実行するとインポートができます)、Windows Azure 管理ポータルからもインポートします。
AzurePortal
インポートすると管理ポータルでこのように確認ができます。ここで表示されている値で、ThumbPrint と書かれている値が後々必要になりますのでメモしておきます。
これでアクティビティの実装を行います。

Workflow に引数を設定して実行

以前、デザイナに「引数」タブがなかったので表示するようにしてみた記事を書きましたが、実際にそれを利用する場合は、次のようなロジックになります。なお Workflow では実行時に渡すものも引数と呼び、終了時に受け取るものも引数と呼びます。
1: '入力引数の設定
2: Dim inArgs As New Dictionary(Of String, Object)
3: inArgs.Add([引数名], Value)
4: 
5: Dim wfApps As New WorkflowApplication(wfFile, inArgs)
引数を渡す場合は、このような形で Dictionary を作成し WorkflowApplication や WorkflowInvoker に引き渡します。詳しく調査していないのですが、恐らく WorkflowApplication.HostEnvironment を通しても同様にアクセスできるのではないかな、と思っていますが試していませんw
反対に結果を受け取る場合のロジックは次のようになります。

2011年5月13日金曜日

REST っぽい Workflow サービスの公開

実際には Workflow サービスにおいて REST 形式での公開は行えません。というのも、MSDN に記載されている通り、メッセージング関係のアクティビティでは定型的な推測のみ行うように用意されており、WebGet 属性や WebInvoke 属性等を付与する事ができないためです。
ですが WCF の機能を利用する事により「それっぽい」形に仕上げる事はできます。
Arguments

2011年5月11日水曜日

IActivityTemplateFactory による カスタムアクティビティの統合

純粋に一つの処理を行うカスタムアクティビティは今までにも何度か作成したように非常に簡単です。ですが実際に利用する側となると、単一処理なアクティビティばかりでは、何度もデザイナ上に配置する必要が生じてしまい使いにくいものとなります。
そのような場面では IActivityTemplateFactory インターフェースを継承したクラスを用意し、デザイナにドロップした際に複数アクティビティを自動で展開させる事が可能です。

2011年5月10日火曜日

Workflow サービスを Windows Azure 上で公開する

Windows Azure でもWorkflowサービスはサポートされていますので、デプロイするだけで利用可能です。そこまでの流れとデバッグについてまとめておきます。
Express のみの環境で Windows Azure を利用するには Visual Web Developer が絶対必要です。デバッグを行うのであれば管理者権限で起動する必要もあります。
Workflow サービス自体は WCF の仕組みで動作していますので、プロジェクトの種類は WCF Service Web Role を選択します。
CreateNewSolution
選択しOKボタンクリックで新規にソリューションが作成され、このように表示されます。

2011年5月9日月曜日

Workflow 上の Receive アクティビティと WCF での実装

Workflow 上で Receive アクティビティ等を利用し送受信を行うサービスを構築できるのは以前の記事などで書いた通りです。それをWCFでロジックを組んだ場合にどうなるか、というのを比較してみると各プロパティでの設定がなんとなくでも見えてくるかと思います。

1: <ServiceContract()>
2: Public Interface IService1
3: 
4:     <OperationContract()>
5:     Function GetData(ByVal value As Integer) As String
6: 
7: End Interface

このソースが Receive アクティビティを利用した場合をWCFにて表したソースとなります。アクティビティ上で OperationName プロパティで指定した名称はそのまま Function 名となり、WorkflowService の Name プロパティで指定したものがインターフェース名(≒クラス名)となります。Receive アクティビティの Content で指定したものは、Function の引数として定義、または DataContract 属性を付与したクラスとなります。

このような事を自動で行っているために、WCF ではできている事が Workflow 上ではできていない点もあります。一つが Function に対しての属性付加 ( WebGet とか ) で、これができないので REST サービスとしての Workflow が行えていません。

ただ上記のようなロジックを組み、コード上で Workflow を利用する形式であればRESTであろうと行えるので、やりようはあるのですが Workflow 単体では残念ながらまだ手段がわかっていません。

2011年5月6日金曜日

IIS Express での Workflow サービスホスティング

IIS で Workflow サービスのホスティングを行う場合の操作について以前の記事で書きました。この方法は IIS Express でも当然有効ですが、一点だけハマった部分があるので書き残しておきます。

  • Windows Server AppFabric をインストールしている
  • AppFabric ランタイム機能のホスティングサービスを有効にしている
  • AppFabric ホスティングサービスにて永続化構成を設定していない

ネックとなったのは Windows Server AppFabric です。これは Windows Vista 以降の IIS で利用できるものなので、自分の Windows7 クライアントにもインストールはしていたのですが、何も設定を行っていなかったため、今回の現象に遭遇しました。厄介なのは、これが IIS 利用時には発生せずに IIS Express 利用時のみに発生する現象だった、という点です。

AppFabric1

これが Windows Server AppFabric の「機能の追加/削除」の GUI です。添付したイメージではホスティングサービスの機能が無効になっています。この状態であれば今回の現象は発生しません。

AppFabric2

こちらが「Configure AppFabric」のGUIです。このように「未設定」の場合に問題が発生します。

この状態で、IIS Express にて Workflow サービスをホスティングし呼び出してみると永続化のエラーが発生します。AppFabricPersistenceDB にログインできません、というエラーです。永続化の設定など、全く行っていなかったので最初は分かりませんでした。例外の情報からAppFabric関連というのは分かるのですが、設定を何も行っていなかったのもあり最初はお手上げでした。色々と試行錯誤の末、AppFabric のホスティングサービス自体を無効にしておけば回避できました。

ここさえ回避してあれば、IIS Express でも簡単に Workflow サービスが利用できます。必要なのは xamlx と web.config の 2 ファイルだけです。IIS Express は XP 環境でも動作しますので、XP 上で Workflow サービスを構成することもできます。

TrackingRecord によるトラッキング

WF の仕組みとして TrackingRecord によるトラッキングの仕組みが用意されています。これはワークフローが、またはアクティビティが何か動作をするたびに通知されるレコードで、全部で 13 種類の状態が通知されます。各トラッキングレコードが何を伝えてくれるかは MSDN を参照してください。

TrackingRecord : WorkflowInstanceRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 0, EventTime = 2011/05/02 9:59:55, ActivityDefinitionId = Sequence, State = Started }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 1, EventTime = 2011/05/02 9:59:55, Activity { Name=Sequence, ActivityId = 1, ActivityInstanceId = 1, TypeName=System.Activities.Statements.Sequence }, State = Executing }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 2, EventTime = 2011/05/02 9:59:56, Activity { Name=Assign, ActivityId = 7, ActivityInstanceId = 2, TypeName=System.Activities.Statements.Assign }, State = Executing }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 3, EventTime = 2011/05/02 9:59:56, Activity { Name=Assign, ActivityId = 7, ActivityInstanceId = 2, TypeName=System.Activities.Statements.Assign }, State = Closed }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 4, EventTime = 2011/05/02 9:59:56, Activity { Name=Delay, ActivityId = 5, ActivityInstanceId = 3, TypeName=System.Activities.Statements.Delay }, State = Executing }
TrackingRecord : WorkflowInstanceRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 5, EventTime = 2011/05/02 9:59:56, ActivityDefinitionId = Sequence, State = Idle }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 6, EventTime = 2011/05/02 9:59:57, Activity { Name=Delay, ActivityId = 5, ActivityInstanceId = 3, TypeName=System.Activities.Statements.Delay }, State = Closed }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 7, EventTime = 2011/05/02 9:59:57, Activity { Name=メッセージを表示, ActivityId = 2, ActivityInstanceId = 4, TypeName=Workflow4.Command.DisplayActivity }, State = Executing }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 8, EventTime = 2011/05/02 9:59:58, Activity { Name=メッセージを表示, ActivityId = 2, ActivityInstanceId = 4, TypeName=Workflow4.Command.DisplayActivity }, State = Closed }
TrackingRecord : ActivityStateRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 9, EventTime = 2011/05/02 9:59:58, Activity { Name=Sequence, ActivityId = 1, ActivityInstanceId = 1, TypeName=System.Activities.Statements.Sequence }, State = Closed }
TrackingRecord : WorkflowInstanceRecord { InstanceId = c0c010f2-d75e-4084-a697-16951fde0a57, RecordNumber = 10, EventTime = 2011/05/02 9:59:58, ActivityDefinitionId = Sequence, State = Completed }

実際にトラッキングを行った際には、上記のようなレコードが通知されます。この内容は前回の記事で実際に実行した際の内容です。デザイナ上でトラッキング内容に基づいて表示を行うのですが、その前に追跡用のプロファイルを作成する必要があります。これは「何をトラッキングし通知するか」を設定するものです。

1: 'トラッキングプロファイルの生成
2: customTracker = New VisualTrackingParticipant '独自に用意したトラッキング用クラス
3: Dim trcProfile As New TrackingProfile With {.Name = "CustomTrackingProfile"}
4: 'トラッキングが必要なアクティビティの名前を設定
5: Dim ctQuery As New CustomTrackingQuery With {.Name = "*", .ActivityName = "*"}
6: trcProfile.Queries.Add(ctQuery)
7: 'トラッキングが必要なステータスを設定
8: Dim wfiQuery As New WorkflowInstanceQuery
9: wfiQuery.States.Add(WorkflowInstanceStates.Started)
10: wfiQuery.States.Add(WorkflowInstanceStates.Aborted)
11: wfiQuery.States.Add(WorkflowInstanceStates.Canceled)
12: wfiQuery.States.Add(WorkflowInstanceStates.Completed)
13: wfiQuery.States.Add(WorkflowInstanceStates.Idle)
14: wfiQuery.States.Add(WorkflowInstanceStates.Persisted)
15: wfiQuery.States.Add(WorkflowInstanceStates.Resumed)
16: wfiQuery.States.Add(WorkflowInstanceStates.Suspended)
17: wfiQuery.States.Add(WorkflowInstanceStates.Terminated)
18: wfiQuery.States.Add(WorkflowInstanceStates.UnhandledException)
19: wfiQuery.States.Add(WorkflowInstanceStates.Unloaded)
20: wfiQuery.States.Add(WorkflowInstanceStates.Unsuspended)
21: trcProfile.Queries.Add(wfiQuery)
22: 'ステータスのトラッキングが必要なアクティビティの名前を設定
23: Dim asQuery As New ActivityStateQuery With {.ActivityName = "*"}
24: asQuery.States.Add("*")
25: asQuery.Variables.Add("*")
26: trcProfile.Queries.Add(asQuery)
27: 
28: customTracker.TrackingProfile = trcProfile
29: _wfApps.Extensions.Add(customTracker)

トラッキングプロファイルを設定するのはこのようなロジックとなります。作成したプロファイルを、WorkflowApplication の Extensions として追加していますが、これは WorkflowInvoker も同様です。

1: Imports System.Activities
2: Imports System.Activities.Tracking
3: Imports System.Collections.Generic
4: 
5: Public Class VisualTrackingParticipant
6:     Inherits Tracking.TrackingParticipant
7: 
8:     Public Event TrackingRecordReceived As EventHandler(Of TrackingEventArgs)
9: 
10:     Public Property ActivityIdToWorkflowElementMap As Dictionary(Of Integer, activity)
11:     Public Property ActivityElementMap As Dictionary(Of Object, Debugger.SourceLocation)
12: 
13:     Protected Overrides Sub Track(ByVal record As System.Activities.Tracking.TrackingRecord, ByVal timeout As System.TimeSpan)
14:         OnTrackingRecordReceived(record, timeout)
15:     End Sub
16: 
17:     Protected Sub OnTrackingRecordReceived(ByVal record As TrackingRecord, ByVal timeout As TimeSpan)
18: 
19:         Dim resultArgs As New TrackingEventArgs With {.Record = record, .Timeout = timeout}
20:         Select Case True
21:             Case TypeOf record Is WorkflowInstanceRecord '100
22:             Case TypeOf record Is WorkflowInstanceUnhandledExceptionRecord '101
23:             Case TypeOf record Is WorkflowInstanceAbortedRecord '102
24: 
25:             Case TypeOf record Is ActivityStateRecord '103
26:                 If ActivityIdToWorkflowElementMap.ContainsKey(DirectCast(record, ActivityStateRecord).Activity.Id) Then
27:                     resultArgs.Activity = ActivityIdToWorkflowElementMap.Item(DirectCast(record, ActivityStateRecord).Activity.Id)
28:                 End If
29:             Case TypeOf record Is ActivityScheduledRecord '104
30:                 If ActivityIdToWorkflowElementMap.ContainsKey(DirectCast(record, ActivityScheduledRecord).Activity.Id) Then
31:                     resultArgs.Activity = ActivityIdToWorkflowElementMap.Item(DirectCast(record, ActivityScheduledRecord).Activity.Id)
32:                 End If
33:             Case TypeOf record Is FaultPropagationRecord '105
34:             Case TypeOf record Is CancelRequestedRecord '106
35:             Case TypeOf record Is BookmarkResumptionRecord '107
36:             Case TypeOf record Is CustomTrackingRecord '108,110,111
37: 
38:             Case TypeOf record Is WorkflowInstanceSuspendedRecord '112
39:             Case TypeOf record Is WorkflowInstanceTerminatedRecord '113
40: 
41:         End Select
42:         RaiseEvent TrackingRecordReceived(Me, resultArgs)
43: 
44:     End Sub
45: End Class
46: 

独自に用意したトラッキング用クラスはこのようなロジックで行っています。内容としては対象アクティビティが関連する ActivityStateRecord や ActivityScheduledRecord が通知された際に、TrackingRecord の内容から対象アクティビティを確定させてイベントに通知させることを行っています。イベント受け取り側ではこの内容を元に、WorkflowDesigner.DevugManagerView.CurrentLocation にその時点でのアクティビティを設定する事で、デザイナ上に黄色い枠線で囲まれて表示が行われるようになります。

2011年5月3日火曜日

リホスティングデザイナにて引数を設定

今までのリホスティングしたデザイナのスクリーンショットでは引数の設定ができていませんでした。調べてみるとちょっと一手間加えてあげる必要がある、と海外 MSDN フォーラムにて問い合わせされていたのでそれを試してみました。

   1:  Dim wfFile As Object = New Sequence
   2:   
   3:  Dim activityBuilderType As New ActivityBuilder
   4:  activityBuilderType.Name = "ActivityBuilder"
   5:  activityBuilderType.Implementation = wfFile
   6:  designer.Load(activityBuilderType)



このような形で ActivityBuilder にてアクティビティをラップするようにし、それをデザイナ上でロードすることで引数の設定ができるようになります。


image


ただし今の時点で自分が調べ切れていないのですが、以前に書いた WorkflowService の場合はこの方法が利用できない様子です。まぁサービスで引数はない(パラメータなどを利用するため)ので影響はないですが。

2011年5月2日月曜日

ワークフローのトラッキング

デザイナをリホスティングしている環境でも、ワークフローの実行トラッキングを行う事ができます。やること自体は非常に簡単で、

  1. 実行情報の出力
  2. 出力されたトラッキング情報を元にデバッガの位置を設定

この二つを行えばデザイナ上でのトラッキングが可能です。実際のロジックは次回以降にて掲載する予定ですので、今回はトラッキングを行った際の挙動を貼り付けておきます。


このような感じでトラッキングを行う事ができます。

2011年4月28日木曜日

Workflow サービスを Workflow 上で利用する

前回のように作成したワークフローサービスを、別のワークフロー上で利用する事も当然できます。動作原理は WCF によるサービスですので、当然コードのみでも利用できますし、VS 上で Web 参照を追加して利用する事もできます。ワークフロー上で利用する場合は、前回のサービス作成と逆のアクティビティを利用します。

UseWFService1

これが全体図です。前回は 受信→返却送信、という流れで作成しましたが、サービスを利用する側となると 送信→返却受信という流れになります。やはり 1 セットで設置できるアクティビティが用意されており、それが SendAndReceiveReply アクティビティとなります。デザイナ上にドロップすると、Send アクティビティと ReceiveReply アクティビティが設置されます。リクエストを送信するための Send アクティビティではサービスを呼び出すための設定が必要です。

  • EndpointAddress:サービスのアドレスをUriクラスのインスタンスとして設定
  • Content:サービスへ送信する値やパラメータを設定
  • ServiceContractName:サービス側で設定されている同名のプロパティと設定を合わせる

サービスからの結果を受信する ReceiveReply アクティビティでは Content プロパティに対して受け取る値やパラメータの設定だけが必要です。

このようにワークフローを設定し実行すると、前回作成した適当な値を返すワークフローサービスが動作し結果を返却してくれます。

UseWFService2

WCF で提供されるサービスを利用する事自体かなり簡略化されていますが、ワークフローから利用する場合はさらに簡単で、一切のコーディング作業が必要ないことがわかると思います。またサービス自体もコーディング全く無しで準備可能ですので、開発者でなくともサービスを作成・提供することが可能です。

特に現在は Windows Azure にて IIS を利用する事が可能となっています。Azure Platform を利用する事で更に WF を有効に活用できるのではないでしょうか。

IIS による Workflow サービス公開

WF4 を利用して外部にサービスとして公開する方法としては何通りかありますが、その中でも比較的簡単にサービス公開する方法である、IIS を利用した方法です。IIS を利用してワークフローをサービス公開するには大きく分けて二つの作業が必要になります。

  • ワークフローサービスとして公開するワークフローの作成
  • IIS の設定

ワークフローサービスとしてのワークフローですが、実際には今まで利用しているワークフローと殆ど違いがありません。IIS でホスティングを行う場合があるので、拡張子が xaml ではなく xamlx を利用しているだけで、内部に記述されている内容には殆ど違いがありません。唯一の違いはルートレベルに利用するアクティビティを WorkflowService アクティビティにするだけです。

service0

WorkflowService アクティビティにはプロパティが 3 つ公開されています。この部分でサービス名や config ファイル上の設定などを指定します。今回はサンプルという事で CodeRecipe で公開されているサンプルに近いものを作成します。サービスの処理内容としては、「適当な文字列を受け取って、適当に編集して、適当に返却する」というサンプルでしかありえない簡易な物とします。

サービスとして公開している場合、リクエストを受けるクチと返事を返すクチが必要となります。受け口は Receive アクティビティ、返却口は SendReply アクティビティとなります。これらは個別にデザイナ上にドロップしても構いませんが、大体は面倒なので 1 セットになっている ReceiveAndSendReply アクティビティを利用する事が多いと思います。また必要となる一部の設定を自動で行ってくれますので、できるだけ利用するのが楽だと思います。

service1

Receive アクティビティでは多くのプロパティが公開されているので少々戸惑いますが、今回のように簡易なサービスを利用する場合にはそれほど設定箇所はありません。

  • OperationName プロパティ:サービスのメソッド名
  • CanCreateInstance プロパティ:リクエスト受信時に新規インスタンスを生成するか
  • Content プロパティ:リクエストで受け付ける引数の設定

OperationName にメソッド名を定義し、CanCreateInstance にはチェックをつけておきます。そしてメソッドの引数を定義するために CorrelatesOn プロパティを設定します。プロパティダイアログにボタンが表示されているのでそれをクリックすると、コンテントエディタが表示されます。

service1-2

このエディタで受け取るリクエストの引数を設定します。メッセージとして設定する場合は単一の値、または WCF で利用される DataContract 属性を付けたクラスを指定します。

そして適当な処理の後では何かしらの値を返却するケースがあります。その場合に SendReply アクティビティを利用します。

service2

Receive アクティビティとプロパティは内容が近いです。こちらで必要なのは返却する内容を Content コレクションプロパティで設定します。

service2-2

今回は適当に編集した値を一つだけ返却しますのでこのように設定します。なおここでは変数を利用していますので、ワークフローの変数としても定義は行っています。

これでサービスとして提供するワークフロー自体は完成です。xamlx として保存します。もう一つ必要なファイルが IIS 上で動作する際の設定ファイルとなる web.config ですが、今回は WCF における既定の構成を利用しますので、以下の内容をそのまま利用します。

1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3:   <system.web>
4:     <compilation debug="true" targetFramework="4.0" />
5:   </system.web>
6:   <system.serviceModel>
7:     <behaviors>
8:       <serviceBehaviors>
9:         <behavior>
10:           <serviceMetadata httpGetEnabled="true"/>
11:           <serviceDebug includeExceptionDetailInFaults="false"/>
12:         </behavior>
13:       </serviceBehaviors>
14:     </behaviors>
15:   </system.serviceModel>
16:   <system.webServer>
17:     <modules runAllManagedModulesForAllRequests="true"/>
18:   </system.webServer>
19: </configuration>

この 2 つのファイルを IIS 上に用意した仮想フォルダにコピーするだけでワークフローサービスとしては動作します。動作しない場合、ファイアウォールで通信を許可しているか、IIS で利用するアプリケーションプールの設定が .NET4 用になっているか、等を確認してみてください。

今回は動作確認に、WCF テストクライアントを利用しました。

service3

このように通常と殆ど変りのないワークフローな xamlx ファイルを IIS に配置しただけでサービスとして利用できているのがわかると思います。外部公開するサービス、と言われると難しいイメージを覚えられることもあると思いますが、WF4 を利用した場合のサービス公開はこのように非常に簡単なものとなっています。

2011年4月27日水曜日

SQL Server のテーブルを全て CSV 出力するワークフロー

SQL Server でテーブルの内容を CSV 出力する事はそれなりに頻度があるかと思います。大体は BCP 等のユーティリティを利用して行うとか、それをスクリプトにまとめておくとか、そのような形ではないでしょうか。同じことをワークフローでも表現してみました。

TableToCsv1

今回は次のような流れのワークフローです。

  1. データベースからテーブル一覧を取得
  2. テーブルごとにデータを抽出
  3. 抽出したデータを CSV 出力

テーブル一覧を取得する部分は今回新規に用意したアクティビティですが、それ以外は今までの記事で利用したものとなっています。ロジックはこのような感じです。

1: Imports System.Activities
2: 
3: Public Class GetSQLTableListActivity
4:     Inherits AsyncCodeActivity
5: 
6:     Private Const SQL_GETTABLE = "SELECT * FROM SYS.TABLES"
7: 
8:     Property ConnectionString As InArgument(Of String)
9:     Property Condition As String = ""
10:     Property TableList As OutArgument(Of String())
11: 
12:     Public Sub New()
13:         Me.DisplayName = "SQL Server のテーブル一覧を取得"
14:     End Sub
15: 
16:     Private Delegate Function GetSQLTableListDelegate(ByVal conString As String, ByVal conditionStrings As String) As String()
17: 
18:     Protected Overrides Function BeginExecute(ByVal context As System.Activities.AsyncCodeActivityContext, ByVal callback As System.AsyncCallback, ByVal state As Object) As System.IAsyncResult
19:         Dim conStr = context.GetValue(Me.ConnectionString)
20:         Dim asyncGetSQLTableListDel = New GetSQLTableListDelegate(AddressOf GetSQLTableList)
21:         context.UserState = asyncGetSQLTableListDel
22: 
23:         Return asyncGetSQLTableListDel.BeginInvoke(conStr, Me.Condition, callback, state)
24:     End Function
25: 
26:     Protected Overrides Sub EndExecute(ByVal context As System.Activities.AsyncCodeActivityContext, ByVal result As System.IAsyncResult)
27:         Dim asyncGetSQLTableListDel = TryCast(context.UserState, GetSQLTableListDelegate)
28:         Dim resultStrings = asyncGetSQLTableListDel.EndInvoke(result)
29:         TableList.Set(context, resultStrings)
30:     End Sub
31: 
32:     Private Function GetSQLTableList(ByVal conString As String, ByVal conditionStrings As String) As String()
33:         Dim result As String()
34: 
35:         Dim tabList As New DataSet
36:         Try
37:             Using sqlConn As New SqlClient.SqlConnection(conString)
38:                 sqlConn.Open()
39:                 'テーブル一覧の取得
40:                 Dim execSql As String = SQL_GETTABLE
41:                 If conditionStrings.Trim <> "" Then
42:                     execSql += " WHERE name like '%" + conditionStrings + "%'"
43:                 End If
44:                 execSql += " ORDER BY name "
45: 
46:                 Dim dataAdapter As New SqlClient.SqlDataAdapter
47:                 dataAdapter.SelectCommand = New SqlClient.SqlCommand(execSql, sqlConn)
48:                 dataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
49:                 dataAdapter.Fill(tabList)
50:                 sqlConn.Close()
51:             End Using
52:         Catch ex As Exception
53: 
54:         End Try
55:         '結果を String() に出力
56:         If tabList.Tables.Count > 0 Then
57:             Dim resultList As New List(Of String)
58:             For Each childRow In tabList.Tables(0).Rows
59:                 resultList.Add(childRow.item("name").ToString)
60:             Next
61:             result = resultList.ToArray
62:         Else
63:             result = Nothing
64:         End If
65: 
66:         Return result
67:     End Function
68: 
69: End Class

SQL Server  では SELECT * FROM SYS.TABLES とすることでテーブル一覧が取得できますので、その結果を今回は String の配列として返却するようにしています。

そうして得たテーブル一覧に対して ForEach アクティビティでループ、その内部では取得したテーブル名を元にデータを取得、その結果を利用して ForEach アクティビティで更にループ、以前利用した CSVOutput なアクティビティを利用して1行ずつファイルへと出力しています。

このようにワークフローとして処理を記述すると、スクリプトやツールの知識がなくとも行われている処理内容が非常にイメージしやすくなります。このあたりが Workflow の醍醐味なのではないか、と個人的には思っています。

Bookmark を利用したワークフローとの連携

Workflow では実行されるワークフローと、ホストするアプリケーション等外部アプリと連携するための仕組みとしてブックマークがあります。ただし連携する方向は、ホストアプリケーション→ワークフロー、という一方のみです。CodeRecipe を参考に、動作サンプルとしてブックマークを作成しホストアプリケーションから値を受け取るアクティビティを作成します。

1: Imports System.Activities
2: 
3: Public Class CooperationHostActivity
4:     Inherits NativeActivity
5: 
6:     Public Property BookmarkName As String
7:     Public Property HostedValue As OutArgument(Of String)
8: 
9:     Protected Overrides ReadOnly Property CanInduceIdle As Boolean
10:         Get
11:             Return True
12:         End Get
13:     End Property
14: 
15:     Protected Overloads Overrides Sub Execute(ByVal context As System.Activities.NativeActivityContext)
16:         If Me.BookmarkName.Trim = "" Then Return
17:         context.CreateBookmark(Me.BookmarkName, New BookmarkCallback(AddressOf OnResume))
18:     End Sub
19: 
20:     Private Sub OnResume(ByVal context As NativeActivityContext, ByVal bookmark As Bookmark, ByVal value As Object)
21:         context.SetValue(Me.HostedValue, value)
22:     End Sub
23: 
24: End Class

継承元が NativeActivity となっているのを除けば、今までと大差ない内容です。ブックマークを Execute メソッドにて作成していますが、この際ブックマークが呼び出された際のメソッドをコールバックとして登録しておく必要があります。このアクティビティを利用して次のようなワークフローを作成します。

Bookmark0

ブックマークを作成しホスト側より値を受け取り、その内容を表示する単純なワークフローです。今回は Writeline アクティビティを利用したため、ホストアプリケーションはコンソールアプリケーションとして用意しました。

1: Imports System.Threading
2: Imports System.Activities
3: Imports System.Activities.XamlIntegration
4: 
5: Module Module1
6: 
7:     Sub Main()
8:         Dim resetEvent As New AutoResetEvent(False)
9:         Dim wfFile = ActivityXamlServices.Load("sample.xaml")
10:         Dim _wfApps As New System.Activities.WorkflowApplication(wfFile)
11:         'ワークフロー実行完了時に待機状態を終了する
12:         _wfApps.Completed = Sub(e As WorkflowApplicationCompletedEventArgs)
13:                                 resetEvent.Set()
14:                             End Sub
15:         _wfApps.Run()
16: 
17:         Console.WriteLine("何か値を入力してください")
18:         _wfApps.ResumeBookmark("TestBookmark", Console.ReadLine())
19: 
20:         resetEvent.WaitOne()
21:         Console.ReadLine()
22: 
23:     End Sub
24: 
25: End Module

ホスト側アプリケーションはこのような形で用意しました。先に用意したワークフローを呼び出し実行、コンソールで適当な値を入力させ、その値をブックマークに対して送り出しています。今回は文字列にて呼び出すブックマーク名を設定していますが、ここは Bookmark クラスのインスタンスを設定する事も可能です。

image

実行するとこのようになります。最終行の文言はワークフロー側から表示が行われていますが、そこまでの 2 行はホスト側アプリケーションによる表示です。このようにブックマークを利用する事で、ワークフローとアプリケーションとの間で連携を取ることができるようになります。ワークフローエンジン上で重複禁止なので、ブックマークの名前付けには気を付ける必要がありますが・・・