使ってみよう! Windows Live SDK/API

第23回Windows Live フォト ギャラリー ─⁠─ はてなフォトライフ プラグインの作成 Part II

前回に続いてPhoto Gallery Publishing Plug-in Platformについてです。サンプルとしてLiveフォト ギャラリーなどで使える はてなフォトライフへ写真をアップロードするプラグインを作ります。今回は実際にプラグインのコードの記述しアップロードができるところまで作成します。

プラグインの処理

コードを書く前に、プラグインが行う処理を確認しておきましょう。Liveアプリケーション上でひとつ以上の動画像を選択した状態で、アップロードメニュー[1]からアップロード先を選択すると、対象のプラグインの処理が実行されます。アップロード先の選択からアップロード完了までに、Liveアプリケーションとプラグインとの間では複数回のやり取りをしています。あるアップロードに対して行われるこの一連のやり取りを、本記事中ではセッションと記載しています。

1. 設定ウィンドウの表示

プラグインは最初に設定ウィンドウを表示します。ウィンドウ表示は必須ではありませんが、通常はアップロードするサービスへの認証処理やアップロード確認などのために利用します。Flickrへのアップロードの場合は図1のようなウィンドウが用意されています。

図1 設定ウィンドウ
図1 設定ウィンドウ

この段階でのプラグインが、Liveアプリケーションとのやり取りによって可能な処理は以下の通りです。

  • プラグイン固有の設定の参照・保存
  • アップロード対象の動画像情報の参照
  • セッションに必要な情報の保存

「セッションに必要な情報の保存」とは、プラグイン自身がこの後の処理に必要とする情報を保存しておくという意味です。⁠アップロード対象の動画像情報の参照」「セッションに必要な情報の保存」はどちらもセッション情報の参照・編集として考えることができます。

必要な処理を終えた後、セッションの続行または中断をLiveアプリケーションに通知し次のステップへ進み(または終了し)ます。

2. 動画像のアップロード

続いて、ユーザーが選択した動画像のアップロード処理を行います。アップロード中には、図2のように進行を示すウィンドウが表示されます。このウィンドウはLiveアプリケーションが用意したものです。

図2 進行通知ウィンドウ
図2 進行通知ウィンドウ

この段階でのプラグインは、Liveアプリケーションとのやり取りにより以下の処理が可能です。

  • アップロード対象の動画像情報の参照
  • セッションに必要な情報の参照・編集・保存
  • 動画像のストリームの参照
  • 進行状況の通知
  • ユーザーによるアップロードのキャンセル通知の受信
  • ウィンドウの表示

上のふたつは設定ウィンドウ表示のときと同じくセッション情報の参照と編集です。

この処理は、アップロード対象の動画像の個数分だけ繰り返することになります。セッション内の動画像ごとにアップロードの成功・失敗をLiveアプリケーションに通知し、すべて完了すると次のステップに進みます。

3. 結果ウィンドウの表示

図3のようなアップロードの結果を示すウィンドウが最後に表示されて一連の処理は終了です。

図3 結果ウィンドウ
図3 結果ウィンドウ

表示されるウィンドウはLiveアプリケーションが用意したものですが、ウィンドウ中の「表示」ボタンと「詳細情報」リンクはプラグインの設定により表示・非表示が決まります。

ここでのやり取りにより可能な処理は以下の通りです。

  • アップロード対象の動画像情報の参照
  • セッションに必要な情報の参照
  • 表示ボタン・詳細情報リンクの表示とクリック時の処理

表示ボタンと詳細情報リンクは以下の違いがあります。

詳細情報リンク

Liveアプリケーションを親ウィンドウとしてプラグインが用意したウィンドウを表示することができます。結果ウィンドウだけでは何枚中何枚がアップロードに成功したことのみしかユーザーはわかりません。これを補うために使用することができます。

表示ボタン

表示ボタンをクリックすると結果ウィンドウは閉じられます。アップロード先のサービスのWebページへ移動するために使用することが想定されています。

プロジェクトの作成

それではプラグインを作成していきましょう。プラグインは.NET Frameworkのクラスライブラリとして作成します。本連載では Visual Studio 2008とVisual Basicを使用しています。

プロジェクトの新規作成

まずはWindowsのクラスライブラリのプロジェクトを新規に作成します図4⁠。

図4 新しいプロジェクトの作成
図4 新しいプロジェクトの作成

参照の追加

続いて必要な参照をふたつ追加します。ソリューションプロパティからプロジェクトを右クリックして表示されるメニューから追加が可能です。

参照の追加ウィンドウの参照タブを選択し、Live フォト ギャラリーがインストールされている場所[2]から「Microsoft.WindowsLive.PublishPlugins」を追加します図5⁠。

この中にプラグインが実装すべきInterfaceの情報があります。

図5 参照の追加
図5 参照の追加

.NETタブから「System.Windows.Forms」も追加します。

Interfaceの実装

IPublishPluginというInterfaceを通してプラグインとLiveアプリケーションはやり取りを行います。プラグインはこのInterfaceを実装する必要があります。プロジェクトにあるクラスファイルを適当な名前に変更しInterfaceを実装しましょう。コードは次のようになります。

Imports Microsoft.WindowsLive.PublishPlugins
Imports System.Windows.Forms
Imports System.Xml

Public Class HatenaFotolifePlugin
    Implements IPublishPlugin

    Public Function ShowConfigurationSettings(ByVal parentWindow As IWin32Window, ByVal sessionXml As XmlDocument, ByVal persistXml As XmlDocument, ByVal publishProperties As IPublishProperties) As Boolean Implements IPublishPlugin.ShowConfigurationSettings
    End Function

    Public Function PublishItem(ByVal parentWindow As IWin32Window, ByVal mediaObjectId As String, ByVal stream As System.IO.Stream, ByVal sessionXml As XmlDocument, ByVal publishProperties As IPublishProperties, ByVal callback As IPublishProgressCallback, ByVal cancelEvent As System.Threading.EventWaitHandle) As Boolean Implements IPublishPlugin.PublishItem
    End Function

    Public Function HasPublishResults(ByVal sessionXml As XmlDocument) As Boolean Implements IPublishPlugin.HasPublishResults
    End Function

    Public Function HasSummaryInformation(ByVal sessionXml As XmlDocument) As Boolean Implements IPublishPlugin.HasSummaryInformation
    End Function

    Public Sub LaunchPublishResults(ByVal sessionXml As XmlDocument) Implements IPublishPlugin.LaunchPublishResults
    End Sub

    Public Sub ShowSummaryInformation(ByVal parentWindow As IWin32Window, ByVal sessionXml As XmlDocument) Implements IPublishPlugin.ShowSummaryInformation
    End Sub
End Class

本記事ではクラス名を「HatenaFotolifePlugin」としています。クラスに「Implements IPublishPlugin」を入力すると、Visual Studioが上記のメソッドを自動で挿入します。これらのメソッドの処理を記述していくとプラグインの完成です。

プラグインの登録

まだ何もメソッドの処理を記述していませんが、Liveアプリケーションがプラグインを認識するための条件は既に満たしています。デバッグにも必要になるので、この時点でビルドしたアセンブリ(DLLファイル)をLiveアプリケーションが参照できるように登録してみましょう。

プラグインの登録はレジストリを編集する必要があります。ここでは直接レジストリエディタ[3]を使用して以下のキーと値を追加してください図6⁠。

キーの場所[4]
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Live\PublishPlugins\[任意の名前]
値(いずれも文字列値)
名前
AssemblyPath DLLファイルへの絶対パス(ファイル名を含む)
ClassName 名前空間を含めたプラグインのクラス名
FriendlyName Liveアプリケーションのメニューに表示される名前
図6 レジストリエディタによる編集
図6 レジストリエディタによる編集

追加した後、Live フォト ギャラリーを起動するとアップロードメニューに追加した項目が表示されていると思います。

デバッグに関してですが、Visual Stuidoからデバッグを行う場合はプロジェクトのプロパティのデバッグタブにある開始動作から「外部プログラムの開始」を選択し、Live フォト ギャラリー(WLXPhotoGallery.exe)を選択します。そうするとデバッグ実行時にLive フォト ギャラリーが起動し、ブレークポイントの使用や変数の参照などが可能です。

はてなフォトライフAPIの利用

はてなフォトライフに写真をアップロードするコードは前回の記事中に書いています。前回のコードに少し変更を加えてプラグインクラスに追加します。

前回作成したメソッドは次の3個でした。

  • CreateWsseHeaderValue
  • GetPostUri
  • PostPhoto

そして、XMLを使用するためにImportsステートメントで次のように名前空間を指定していました。

Imports <xmlns="http://purl.org/atom/ns#">
Imports <xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#">
Imports <xmlns:dc="http://purl.org/dc/elements/1.1/">

プラグインでもXMLを扱うためデフォルトの名前空間を次のように変更します。

Imports <xmlns:atom="http://purl.org/atom/ns#"> ' 変更
Imports <xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#">
Imports <xmlns:dc="http://purl.org/dc/elements/1.1/">

この変更に併せてGetPostUriメソッドの以下の部分を変更します。

' <link rel="service.post">要素の取得
' 以下へ変更 Dim elements = From e In document.<feed>.<link> Where e.@rel = "service.post"
Dim elements = From e In document.<atom:feed>.<atom:link> Where e.@rel = "service.post"

PostPhotoメソッドは少し引数が多くなりますが、写真の名前とContent Type(image/jpegnなど)のStringおよびSystem.IO.Streamを引数に加えます。そして、引数の値を使用するようにコードを変更します。写真のバイトデータは引数のStreamから取得し、サーバーへ渡す<entry>要素も以下のコードのように記述します。メソッドの全文を示します。

Protected Shared Sub PostPhoto(ByVal userName As String, ByVal password As String, _
                               ByVal postUri As String, ByVal title As String, ByVal contentType As String, ByVal photoStream As System.IO.Stream)
    ' リクエストの作成
    Dim request = DirectCast(WebRequest.Create(postUri), HttpWebRequest)
    With request
        .Method = "POST"

        ' WSSE認証用
        .Headers.Add(HttpRequestHeader.Authorization, "WSSE profile=""UsernameToken""")
        .Headers.Add("X-WSSE", CreateWsseHeaderValue(userName, password))

        .ContentType = "application/x.atom+xml"
        .Accept = "application/x.atom+xml, application/xml, text/xml, */*"
        .ServicePoint.Expect100Continue = False
    End With

    ' 写真をバイト配列として読み込み
    Dim photoBuffer = New Byte() {}
    Using reader = New System.IO.BinaryReader(photoStream)
        If photoStream.Length <= Integer.MaxValue Then
            photoBuffer = reader.ReadBytes(CInt(photoStream.Length))
        End If
    End Using

    ' <entry>要素
    Dim entry = <entry xmlns="http://purl.org/atom/ns#">
                    <title><%= title %></title>
                    <content mode="base64" type=<%= contentType %>><%= Convert.ToBase64String(photoBuffer) %></content>
                    <hatena:generator url="http://gihyo.jp/dev/serial/01/wl-sdk/" version="1.0">gihyo.jp sample tool</hatena:generator>
                </entry>

    ' <entry>要素をバイト配列へ変換
    Dim entryBuffer = System.Text.Encoding.UTF8.GetBytes(entry.ToString)
    request.ContentLength = entryBuffer.Length

    ' POSTデータ書き込み
    Using stream = request.GetRequestStream
        stream.Write(entryBuffer, 0, entryBuffer.Length)
    End Using

    ' レスポンス取得
    Dim document As XDocument ' (記事中では使用していません)
    Using response = DirectCast(request.GetResponse, HttpWebResponse), _
          reader = New System.IO.StreamReader(response.GetResponseStream, System.Text.Encoding.UTF8)
        document = XDocument.Load(reader)
    End Using
End Sub

作成するプラグインではアップロード先のフォルダを指定しませんので、<dc:subject>要素は前回のコードから削除しています。

CreateWsseHeaderValueメソッドは変更せずに使用します。

設定ウィンドウの表示

それではInterfaceのメソッドを実装していきましょう。まず、設定ウィンドウの表示処理を実装します。設定ウィンドウの表示等を行うメソッドはShowConfigurationSettingsです。

今回作成するプラグインでは最低限必要なものとしてユーザー名とパスワードをユーザーが入力するウィンドウを作成します。ユーザー名は一度入力されたものはプラグイン固有の設定として保存しておき、次回のアップロード時に入力が省けるよう設計します。パスワードは保存せずに毎回入力するものとします。

ShowConfigurationSettingsメソッド内部で次の処理を順に行います。

  1. プラグイン設定から以前入力したユーザー名情報を取得
  2. 設定ウィンドウの表示(ユーザー名とパスワードの入力)
  3. 入力された情報から、はてなフォトライフPostURIの取得
  4. ユーザー名をプラグイン設定として保存
  5. PostURI・ユーザー名・パスワードをセッション情報として保存

ウィンドウの作成

プロジェクトにユーザー名等を入力するためのWindowsフォームを追加します。作成するウィンドウを図7に示します。図7を参考にコントロールを配置してください。オレンジ色の文字は記事中で使用しているコントロール名です。

図7 ユーザー名とパスワード入力用Form
図7 ユーザー名とパスワード入力用Form

Windows フォーム内のコードを以下に示します。

' ユーザー名
Public ReadOnly Property UserName() As String
    Get
        Return UserNameTextBox.Text
    End Get
End Property

' パスワード
Public ReadOnly Property Password() As String
    Get
        Return PasswordTextBox.Text
    End Get
End Property

' コンストラクタ
Public Sub New(ByVal userName As String)
    Me.InitializeComponent()
    UserNameTextBox.Text = userName ' ユーザー名をTextBoxに設定
    PublishButton.Enabled = False ' 投稿ボタン無効化
    Me.StartPosition = Windows.Forms.FormStartPosition.CenterParent ' 親ウィンドウの中央に表示
End Sub

' TextBoxに値が入力されている場合、投稿ボタンを有効にする
Private Sub UserNameComboBox_Or_PasswordTextBox_TextChanged( _
    ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles UserNameTextBox.TextChanged, _
            PasswordTextBox.TextChanged
    ' 投稿ボタンの有効・無効化
    PublishButton.Enabled = CBool(UserNameTextBox.Text <> "" AndAlso PasswordTextBox.Text <> "")
End Sub

' 投稿ボタンクリック
Private Sub PublishButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PublishButton.Click
    Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub

' キャンセルボタンクリック
Private Sub CancelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelButton.Click
    Me.DialogResult = Windows.Forms.DialogResult.Cancel
End Sub

ポイントは、ユーザー名をコンストラクタ引数で受け取る部分と、入力した値はプロパティとして参照できるようにしている部分です。

メソッドの引数と戻り値

ShowConfigurationSettingsメソッドには以下の引数があります。

引数名 説明
parentWindow Liveアプリケーションのウィンドウハンドル。設定ウィンドウを表示する際に親ウィンドウと指定するために使用します。
sessionXml アップロード対象の動画像情報のXML文書。プラグインが使用する一時的な情報はこのXML文書を書き換えて保持します。
persistXml プラグイン固有の設定保存用のXML文書。プラグインは自由に形式を決定し使用できます。
publishProperties 動画像の関連データへアクセスするためのIPublishPropertiesというInterfaceのオブジェクト。

引数にあるようにLiveアプリケーションとプラグインと情報のやり取りにXML文書(XmlDocumentオブジェクト)が利用されています。加えてIPublishProperties Interfaceによりメタデータへアクセスが可能です。sessionXmlとpersistXmlについては後述しています。publishPropertiesは今回使用していません。

メソッドの戻り値はBoolean型です。処理を続ける場合にはTrueを、中断する場合はFalseを返します。

メソッドの実装

ShowConfigurationSettingsメソッドに処理を追記します。

引数のpersistXmlについてですが、これを使用してプラグインの設定を保存します。ここではユーザー名を保存するため次の書式で使用することにします。

<UserName>[ユーザー名]</UserName>

初めてプラグインが実行されたとき、persistXmlは何も記述されていないXML文書になっています。

PostURIを取得するところまで書いてみましょう。コードは次のように書くことができます。

' XDocument へ変換
Dim persist As XDocument
Try
    If persistXml.InnerXml <> "" Then
        persist = XDocument.Parse(persistXml.InnerXml)
    Else
        persist = New XDocument
    End If
Catch xmlEx As Xml.XmlException
    persist = New XDocument
End Try

Dim userName As String
Dim password As String

' ConfigureForm 表示
Dim result As DialogResult
Using frm = New ConfigureForm(persist.<UserName>.Value) ' <UserName>要素を指定
    result = frm.ShowDialog(parentWindow)
    If result = Windows.Forms.DialogResult.OK Then
        ' 投稿ボタンをクリックした場合
        userName = frm.UserName
        password = frm.Password
    Else
        ' キャンセルボタンをクリックした場合
        Return False
    End If
End Using

' PostURI 取得
Dim title As String = Nothing
Dim postUri As String
Try
    postUri = GetPostUri(userName, password, title)
Catch webEx As WebException
    MessageBox.Show(webEx.Message, "Error")
    Return False
End Try

次は、この後の処理で使用するために取得したPostURI・ユーザー名・パスワードをsessionXmlへ追記します。次の書式になるよう要素を追加します。

<PhotoGalleryPublishSession>
  <PublishParameters>
    <PostUri>[PostURI]</PostUri>
    <UserName>[ユーザー名]</UserName>
    <Password>[パスワード]</Password>
  </PublishParameters>
</PhotoGalleryPublishSession>

コードは次のようになります。コードの最後では、persistXmlへユーザー名を、sessionXmlへセッション情報を反映させています。

' Session XML にユーザー情報とPostURI 保存
Dim session = XDocument.Parse(sessionXml.InnerXml)
With session.<PhotoGalleryPublishSession>.<PublishParameters>.First
    .Add(<PostUri><%= postUri %></PostUri>)
    .Add(<UserName><%= userName %></UserName>)
    .Add(<Password><%= password %></Password>)
End With

' XmlDocument へ反映
persistXml.LoadXml(<UserName><%= userName %></UserName>.ToString)
sessionXml.LoadXml(session.ToString)
Return True

上記のコードでは引数のXmlDocumentオブジェクトからXDocumentオブジェクトへ変換してVisual BasicのXMLリテラルを使用してXMLの操作をしています。編集内容を反映させるため最後にXmlDocumentオブジェクトへ戻しています。

Session XMLとPersist XML

既に設定ウィンドウ表示処理に出てきたようにLiveアプリケーションとプラグインとのやり取りにはXLM文書(XmlDocumentオブジェクト)が利用されています。ここでは各メソッドの引数にあるpersistXmlとsessionXmlについて説明します。

Session XML

Session XMLはユーザーが選択した動画像の情報を参照するためと、アップロード処理にプラグインが必要な情報を一時的に保持するために使用します。プラグインが使用する情報の保持はSession XMLを使用せず、プラグインクラスのプロパティやPrivate変数として値を保持したほうがスマートのように思えますが、Photo Gallery Publishing Plug-in Platformによる投稿プラグインではプラグインのメソッド呼び出し時に同じインスタンスが使用されるとは限りません。そのため、必要な情報は一度Session XMLを通してLiveアプリケーションに渡し、再度Liveアプリケーションから受け取る必要があります。

Session XMLの例を以下に示します。

<PhotoGalleryPublishSession versionMajor="1" versionMinor="0">
  <PublishParameters>
    <MaxWidth>1024</MaxWidth>
    <MaxHeight>1024</MaxHeight>
  </PublishParameters>
  <ItemSet>
    <Item id="19">
      <FullFilePath>C:\Users\UserName\Pictures\background.jpg</FullFilePath>
      <OriginalFileName>background.jpg</OriginalFileName>
      <OriginalFileExtension>.jpg</OriginalFileExtension>
      <PerceivedType>image</PerceivedType>
      <Title></Title>
      <OriginalWidth>2560</OriginalWidth>
      <OriginalHeight>1920</OriginalHeight>
      <LengthMS>0</LengthMS>
      <FileSize>1620000</FileSize>
      <KeywordSet>
        <Keyword>meatball</Keyword>
        <Keyword>double tooth</Keyword>
      </KeywordSet>
      <PeopleRegionSet>
        <PersonRegion left="0.6" top="0.1" width="0.1" height="0.2">M.K</PersonRegion>
      </PeopleRegionSet>
    </Item>
    <Item id="20">
      ...
    </Item>
    <Item id="21">
      ...
    </Item>
  </ItemSet>
</PhotoGalleryPublishSession>

<ItemSet>要素内に選択された動画像の数だけ<Item>要素があり、各動画像の情報が記載されていることがわかります。動画と画像の判別は<Item>要素内にある<PerceivedType>要素の値(imageまたはvideo)により可能です。また、<Item>要素内には<Keyword>要素と<PersonRegion>要素があり、Live フォト ギャラリーでユーザーが付けたタグおよび人物タグの情報の取得も可能となっています。

プラグインが使用するセッション中の情報は、ユーザーや動画像に関するパラメータは<PublishParameters>要素以下に要素を追加し、成功・失敗などのログはXML文書の最後に要素を追加して利用することが想定されているようです。

Persist XML

Persist XMLはプラグイン固有の設定を保存するために使用します。XML文書の内容はプラグインが自由に決定でき、ShowConfigurationSettingsメソッド呼び出し時にLiveアプリケーションから渡されます。変更した内容の保存は、ShowConfigurationSettingsメソッドの戻り値をTrueとしたときのみLiveアプリケーションにより行われます。

Persist XMLはプラグインの全般的な設定を保存するために用意されているもので、ユーザーパスワードなど重要な情報の保存に使用してはいけません。本記事で作成するプラグインではユーザー名の保存に使用しています。

動画像のアップロード

アップロード処理を行うメソッドはPublishItemです。ユーザーが選択した動画像の個数の回数だけメソッドが呼ばれます。作成するプラグインでは、1回の呼び出しに対して以下の処理を行います。

  1. Session XMLから画像の情報を取得(画像形式、ファイル名、タイトルなど)
  2. 同様に PostURI・ユーザー名・パスワードを取得
  3. はてなフォトライフへ画像をアップロード

メソッドの引数と戻り値

PublishItemメソッドには以下の引数があります。

引数名 説明
parentWindow Liveアプリケーションのウィンドウハンドル。各アップロード処理に何かしらのウィンドウ表示が可能です。
mediaObjectId Liveアプリケーションが付けた動画像のID。Session XMLの<Item>要素id属性と一致しています。
stream アップロードする動画像のバイナリストリーム。
sessionXml ShowConfigurationSettingsメソッド内で編集されたSession XML。
publishProperties IPublishPropertiesオブジェクト。
callback 進行状況の通知およびユーザーによるキャンセル検出のためのIPublishProgressCallbackというInterfaceのオブジェクト。
cancelEvent ユーザーによるキャンセル検出するためのEventWaitHandleオブジェクト。

publishProperties、callback、cancelEventは今回使用しません。

戻り値はShowConfigurationSettingsメソッドと同じくBoolean型です。アップロードが成功した場合はTrueを返し、失敗した場合はFalseを返すようにします。Falseを返した場合もセッションのキャンセルにはならず、さらに動画像がある場合は続けてPublishItemメソッドが呼び出されます。

メソッドの実装

まず、引数のsessionXmlとmediaObjectIdから対象となる動画像の情報を参照します。sessionXmlの<Item>要素のid属性の値がmediaObjectIdと一致している要素がアップロードの対象です。ここでは<Item>要素の情報を使用して以下の処理を行います。

  • 動画・画像の判別
  • 拡張子からContent Type文字列の作成
  • タイトルまたはファイル名から写真名の決定

動画が選択されていた場合は処理を終了し、Content Type文字列は拡張子をみて決定することにします。また、アップロードする写真の名前はLive フォト ギャラリー上でタイトルが付けられていた場合それを利用し、ない場合はファイル名とします。

以上のコードは次のように書くことができます。

' XDocument へ変換
Dim session = XDocument.Parse(sessionXml.InnerXml)

' <Item id="mediaObjectId">要素取得
Dim item = (From e In session.<PhotoGalleryPublishSession>.<ItemSet>.<Item> _
            Where e.@id = mediaObjectId).First

' <PerceivedType>要素がimageの場合は処理を抜ける
If item.<PerceivedType>.Value <> "image" Then
    Return False
End If

' 拡張子から ContentType 文字列作成
Dim contentType As String
Select Case item.<OriginalFileExtension>.Value.ToLower
    Case ".jpg", ".jpeg"
        contentType = "image/jpeg"
    Case ".gif"
        contentType = "image/gif"
    Case ".png"
        contentType = "image/png"
    Case ".bmp"
        contentType = "image/bmp"
    Case Else
        Return False ' サポート外の拡張子
End Select

' 写真名にはタイトルまたはファイル名を使用する
Dim title As String
If item.<Title>.Value <> "" Then
    title = item.<Title>.Value
Else
    title = item.<OriginalFileName>.Value
End If

画像自体のデータはStreamで渡されていますので、Session XMLからPostURI・ユーザー名・パスワードを取得して、それらを作成済みの はてなフォトライフへアップロードするメソッドに渡せば処理は完了です。続きのコードは以下のようになります。

Try
    ' アップロード
    Dim params = session.<PhotoGalleryPublishSession>.<PublishParameters>
    PostPhoto(params.<UserName>.Value, params.<Password>.Value, params.<PostUri>.Value, title, contentType, stream)
    Return True
Catch webEx As WebException
    Return False
End Try

結果ウィンドウの表示

最後に結果ウィンドウの表示です。結果ウィンドウ自体はLiveアプリケーションが表示しますので、表示ボタンと詳細情報リンクの実装となります。今回は、表示ボタンのみ有効にし、クリックすると はてなフォトライフのWebページへ移動するようにします。

表示ボタンと詳細情報リンクの有効化はHasPublishResultsメソッドとHasSummaryInformationメソッドの戻り値の設定により行います。どちらのメソッドも戻り値がBoolean型で、Trueの場合対象のボタンまたはリンクが有効になります。

Public Function HasPublishResults(ByVal sessionXml As XmlDocument) As Boolean Implements IPublishPlugin.HasPublishResults
    ' 表示ボタン有効
    Return True
End Function

Public Function HasSummaryInformation(ByVal sessionXml As XmlDocument) As Boolean Implements IPublishPlugin.HasSummaryInformation
    ' 詳細情報リンク無効
    Return False
End Function

表示ボタンクリック時の動作はLaunchPublishResultsメソッドに記述します。引数はSession XMLです。

Public Sub LaunchPublishResults(ByVal sessionXml As XmlDocument) Implements IPublishPlugin.LaunchPublishResults
    Dim session = XDocument.Parse(sessionXml.InnerXml)
    Dim userName = session.<PhotoGalleryPublishSession>.<PublishParameters>.<UserName>.Value
    Try
        ' はてなフォトライフのユーザーページを開く
        Process.Start("http://f.hatena.ne.jp/" & userName)
    Catch ex As Exception
        ' Do nothing
    End Try
End Sub

詳細情報リンククリック時の動作はShowSummaryInformationメソッドに記述します。ウィンドウの表示が想定されているため引数には、Session XMLに加えIWin32Windowオブジェクトがあります。HasSummaryInformationメソッドでFalseを返すと、このメソッドが呼ばれることはありません。

Public Sub ShowSummaryInformation(ByVal parentWindow As IWin32Window, ByVal sessionXml As XmlDocument) Implements IPublishPlugin.ShowSummaryInformation
    ' 呼ばれない
End Sub

プラグインの実行

以上でLive フォト ギャラリーからはてなフォトライフへ写真のアップロードが可能になりました。実際に動かしてみましょう図8⁠。うまく動いたでしょうか?

図8 実行結果
図8 実行結果

もしセッション中に例外がスローされた場合はLiveアプリケーション側で吸収され詳細はわかりません。処理を細かく切り分けて失敗している原因を探すとよいでしょう。


次回もPhoto Gallery Publishing Plug-in Platformを利用したプラグイン作成の予定です。

おすすめ記事

記事・ニュース一覧