WindowsLiveWriter Archive

追記:現在はWindows Live Writerが使えるようになったようです。はてなはフットワークが軽くていいですね。

はてなインターンで実装されたというはてなダイアリーのAtom Pub APIを使って、Windows Live Writerからはてダに投稿できないか試してみました。
結論から先に言ってしまうと、登録出来ませんでした。残念…。 とりあえず、どこで失敗しているっぽいか調べた際のレポートを載せておきます。

imageどこで失敗するかというと、Windows Live Writerに新しいアカウントを追加する際。FiddlerでWLWの通信を覗いてみたところ、アカウントの追加画面でBlogのタイプをAtom Pub APIに設定し、エンドポイントURLを入力してやって次の画面に進もうとすると、WLWはそのエンドポイントURLに対してまず認証無しでGETリクエストを投げるようです。当然はてなのAtom Pub APIはこれを拒否し、401 Unauthorizedを返すのですが、imageこれに対してWLWは今度はちゃんとWSSE認証のためのヘッダを付けてGETリクエストを送るようです。 良い感じですね。ところがこれに対してはてなAtom Pubは403 Forbiddenを返してきます。なんで?

401 Unauthorizedを返してこないので、認証には成功したようなのですが、ちょっとこれは謎仕様。このためWLWは一つ目のSSのようなダイアログが出てこれ以上登録を進めることが出来なくなります。ん~何が悪いんでしょうかね…。

AUG
22

SyntaxHighlighter一部改修メモ

Published:2008-08-22 16:44:58 UTC

ソースコードをハイライト表示してくれるので非常に便利なSyntaxHighlighter。JZ5さんがSyntaxHighlighter for Windows Live WriterというプラグインでWLW上でスマートコンテントとして管理できるようにしてくれているので、WLW好きの自分としては是非このBlogにも組み込みたいと思い、作業していたのですが、その中でSyntaxHighlighterの表示の不具合にぶつかりました。今回のエントリではその対応策を記します。

SyntaxHighlighterの持つ問題

image SyntaxHighlighterは、通常、一行あたりの文字数が多くSyntaxHighlighterの表示部の横幅を超えるようなソースコードの場合、white-space:normal;の指定により、折り返し表示してくれるようになっています。ですが、半角文字列の折り返しは単語毎に行われるというブラウザの仕様のためか、場合によってはソースコードの折り返しが上手く行われず、横スクロールバーが表示されてしまうという問題があります。そうなると、スクロールした部分は背景の塗り分けが上手く行われず、SSのように違和感のある表示になってしまう、という問題があります。

対応策

上手く折り返し表示させる方法がよく分からなかったので、自分の場合、常に折り返し無しで表示することにしました。そして背景の塗り分け自体も廃し、常時横スクロールバーを表示。また、上のツールメニューもあわせて表示の仕方を変更しました。

長々と言葉で説明しても冗長になるだけなので、SyntaxHighlighterのCSSを上書きするのに使用したCSSファイルを示します。

.dp-highlighter{
	overflow-y:visible;
	overflow-x:scroll;
	background-color:#fcfcfc;
	width:100%;
}
.dp-highlighter ol li,.dp-highlighter ol li.alt{
	background-color:#fcfcfc;
	white-space:pre;
}
.dp-highlighter ol li, .dp-highlighter .columns div, .dp-highlighter .tools {
	border-left:3px solid #e26c6c;
}
.dp-highlighter .tools{
	font-size:120%;
	height:2em;
	padding:0px;
	background-color:#fcfcfc;
}
.dp-highlighter .tools a{
	font-size:100%;
	display:block;
	color:#888888;
	float:left;
	height:1.5em;
	margin:0px;
	padding-top:0.4em;
	padding-bottom:0.1em;
	padding-left:0.5em;
	padding-right:0.5em;
	background-image:url("images/shToolsBG.png");
}
.dp-highlighter .tools a:hover{
	background-image:none;
	background-color:#ffffff;
}
.dp-highlighter ol.dp-c{
	clear:both;
	background-color:#fcfcfc;
}

実際に適用するとこんな感じ。

image

スクロールさせても崩れてません。

image

今回は不具合修正をきっかけとして既製のライブラリのCSSの上書きに取り組みましたが、今回のツールメニューや左ボーダーの変更のように、単なるデザインの変更にも使えるので、結構ブラックボックス化しがちなライブラリのデザインを、サイトのデザインと調和させる目的でも色々弄ってみてはいかがでしょうか。

追記

このCSSは桁の表示には未対応です。まぁ全角文字が含まれているとどうせズレが生じるし、放置で良いかな・・・。

AUG
13

WPCustomFieldsEditorよもやま噺

Published:2008-08-13 19:07:33 UTC

このエントリではWPCustomFieldsEditorを製作するにあたって蓄えたトリビア(死語?)紹介をしてみます。後半愚痴だか雑記だかよく分からなくなっていますが。 ん?二度ネタが多い?それは仕様です。

ログイン情報の取得方法

WPCustomFieldsEditorではXML-RPCを使ってWordPressを操作しています。WordPressをXML-RPCで操作するには、WordPressのエンドポイントURLとログインするためのユーザー名とパスワードが必要となります。これらは、リフレクションなどを使って、Windows Live Writer(以下WLW)が内部に保持している情報を取得しています。エンドポイントURLはBlogクラスのPostApiUrlプロパティから、ユーザー名とパスワードはXmlRpcBlogClientクラスのUsernameプロパティ、Passwordプロパティからそれぞれ取得できます。これらのクラスのインスタンスの取得方法については、SharpLab. – 中まで見よう!Windows Live Writerというエントリに書きましたのでそちらを参照してください。

WP-XML-RPC APIの情報の集め方

WordPressをXML-RPCで操作していると述べましたが、WordPressにはmetaWeblog APIを拡張したWP-XML-RPC APIがあり、これを使用しています。metaWeblog APIについてはMovableType で使える XML-RPC APIというページが詳しいです。WordPressが独自に拡張した部分についてはXML-RPC wp « WordPress Codexに纏まっています。

ただ、これだけでは残念ながらWordPressのXML-RPCについて網羅しきれていません。最近新しく追加された機能などについて調べる場合はwp-xmlrpc Info PageからMLのアーカイブをさらう必要があります。

それでも良く分からなかったら?幸いWordPressはOSSです。ソースコードを読みましょう。その際、便利なのがこちら、PHPXref 0.7: WordPress (latest release)。PHPXrefというツールで、クロスリファレンス化したWordPressのソースコードが掲載されています。

WP-XML-RPC APIによるカスタムフィールドの扱い方

[wp-xmlrpc] exposing and manipulating custom fieldsに記述があります。大体分かり易い記述ですが、ちょっと躓くところがあったので記しておきます。以下の部分。

If a custom field entry included with a post contains an "id" value then an update is done. If there is no "id" then an add is done. If there is an "id" value and no "key" value then the custom field with that id is deleted.

「なになに…idがなければ新しいカスタムフィールドとして追加され、idはあってもkeyがなければそのカスタムフィールドは削除されるとな?」と理解し、追加したい場合はidに空文字列を持たせる形で実装を進めたのですが、うんともすんとも動かない。カスタムフィールドを削除しようと思ってkeyに空文字列を渡した場合には空文字列をキーにしたカスタムフィールドが出来てしまうという始末。(管理画面からは空文字列をキーにすることは出来ないのでバグでしょう。)

実はno idという状態とはidの値を空にしろ、という意味ではなく、idというメンバ自体を持たせるな、ということでした。今振り返ってみて素直に読めば確かにその方が読んでいて通りが良いですが、なんだかなー、もーちょっとわかりやすくしてくれよ、と思いました、はい。

アンダーバーで始まるフィールド

SharpLab. – WPCustomFieldsEditor制作中というエントリにも書いたのものですが。

WordPressの管理画面からは見えないのですが、WP-XML-RPC API経由だと_edit_last、_edit_lockや、_encloseme、_pingmeなどの謎のカスタムフィールドが見える場合があります。これらアンダーバーでキー名が始まるカスタムフィールドですが、結局ググってもよくわからなかったので、WPCustomFieldsEditorでは一律無視することにしています。従って、ユーザーがアンダーバーでキー名が始まるカスタムフィールドを作成した場合も巻き添えで無視されてしまうので、運用には十分注意してください。

AUG
13

WPCustomFieldsEditor

Published:2008-08-13 11:18:23 UTC

これは何?

Windows Live WriterにWordPressのカスタムフィールド編集機能を追加するプラグインです。カスタムフィールドはエントリに独自のメタデータを付加したい場合のために確保されたフィールドで、WordPressをCMSとして多少手の込んだサイト管理に使用する場合には非常に重宝する機能です。このプラグインでは、エントリに付加するカスタムフィールドを、投稿時に編集する機能をWindows Live Writerに提供します。

ダウンロード

WPCustomFieldsEditor.zip

動作環境

  • Microsoft Windows XP SP2 以降または Windows Vista(Windows Live Writerに準拠)
  • Microsoft .NET Framework 2.0以上
  • Windows Live Writer Beta(Build14.0.5025.904)
  • WordPress 2.5以上

※現在、Writer Zoneで配布されているTechnical Preview版では、おそらく動作しなくなっています。ご注意ください。

インストール方法

ダウンロードしたファイルを展開してsetup.exeを実行してください。

アンインストール方法

コントロールパネルのプログラムの追加と削除からWPCustomFieldsEditorを選択し削除してください。

操作説明

image エントリの投稿を行うと、スプラッシュウィンドウに続いてカスタムフィールドの編集画面が現れます。この画面からカスタムフィールドの追加・削除・編集を行うことが出来ます。


image

更新履歴

  • 2008-10-01 ver.1.03に差し替え。内部動作を変更。
  • 2008-09-20 ver.1.02に差し替え。WLW Beta(Build14.0.5025.904)に対応。
  • 2008-08-13 Blogシステムの判別ミスがあったのでver.1.01に差し替え
  • 2008-08-13 イニシャルリリース
AUG
10

WPCustomFieldsEditor制作中

Published:2008-08-10 01:45:00 UTC

image 

WordPressのカスタムフィールドをWindowsLiveWriterから編集するためのプラグインを製作中。プラグインの形式はpublish notification hooksプラグイン。とりあえずXML-RPCを使って記事に付加されたカスタムフィールドの一覧を取得するところまで漕ぎ着けた。ちなみにXML-RPCでWordPressを操作する際に必要となるID、PasswordにはSharpLab. – 中まで見よう!Windows Live Writerというエントリで紹介した方法を使用してWLWが内部に保持している情報を取得して使っています。エンドポイントURLも確かBlogクラスあたりのメンバにあったのを使用。

さて、ここまででカスタムフィールドの仕様に関して気づいたことが何点か。

  • _edit_last、_edit_lockや、_encloseme、_pingmeなどの謎のカスタムフィールドがWordPressによって勝手に追加されている。アンダーバーが付いているカスタムフィールドはWordPressによって自動的に追加されたもの?ちなみにこれらはWordPressの管理画面からは不可視。
  • カスタムフィールドのキーは一意である必要はない。キーとは別にidが振られており、それで管理が行われている。(参考:[wp-xmlrpc] exposing and manipulating custom fields

来週暇なんで作業が進むといいなー。

ちょっとだけ状況が改善。

「SharpLab. – publish notification hooksでpost内容を安全に書き換えるには」のコメント欄を受けて、「サーバーに修正後のエントリをアップ、そのアップされたエントリをWLWでDLして再読み込み」という方法を試してみた。

        public override bool OnPrePublish(System.Windows.Forms.IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish) {

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);
            Blog blog = new Blog(postEditorForm.CurrentBlogId);

            //publishingContextからリフレクションでBlogPostEditingManagerを取得
            FieldInfo editingContextFieldInfo = publishingContext.GetType().GetField("_editingContext", BindingFlags.NonPublic | BindingFlags.Instance);
            BlogPostEditingManager manager = (BlogPostEditingManager)editingContextFieldInfo.GetValue(publishingContext);

            PropertyInfo localFilePropertyInfo = manager.GetType().GetProperty("LocalFile", BindingFlags.NonPublic | BindingFlags.Instance);
            PostEditorFile postEditorFile = (PostEditorFile)localFilePropertyInfo.GetValue(manager,null);

            BlogPost blogPost = (BlogPost)publishingContext.PostInfo; ;
            blogPost.Title = "test";
            return true;
        }

このようにOnPrePublishメソッド内では投稿内容の書き換えだけを行って、

        public override void OnPostPublish(IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish) {

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);
            Blog blog = new Blog(postEditorForm.CurrentBlogId);

            //publishingContextからリフレクションでBlogPostEditingManagerを取得
            FieldInfo editingContextFieldInfo = publishingContext.GetType().GetField("_editingContext", BindingFlags.NonPublic | BindingFlags.Instance);
            BlogPostEditingManager manager = (BlogPostEditingManager)editingContextFieldInfo.GetValue(publishingContext);
            BlogPost blogPost = blog.GetPost(publishingContext.PostInfo.Id, publishingContext.PostInfo.IsPage);
            manager.EditPost(new BlogPostEditingContext(postEditorForm.CurrentBlogId, blogPost));
        }

image

OnPostPublishメソッド内で記事の再読み込みを行うというやり方でテスト。

YATTA!この場合だと、画像が消えてしまうことなく、書き換え内容を投稿画面に反映することが出来た。だが一方で、「Smart Content」部を選択しても、右のように"Selected item cannot be edited."というメッセージが出て、編集出来なくなるという問題が。また、画像も良く見てみると、ローカル画像という扱いではなく、Web画像という扱いになってしまっている。つまりこの方法ではWindows Live Writerがローカルに保存した記事についての情報(.wpost拡張子でMy Weblog Posts以下に保存されている奴)を利用出来ていないようだ。なかなか難しいな…。このやり方でのOnPrePublishメソッド部のみ実行し、その後手動でサイドバーのRecently Postedの一覧の中から投稿したエントリを選択するというやり方なら、上手くマージされた状態で読み込め、「Smart Content」部も再編集可能なので、どこかに方法はあるはずだとは思うのだが…。

追記:やっぱり問題が発生するようです。エントリ内の写真が消えたりする問題が起きるようなので、この方法も駄目でした…orz

ひとつ前のエントリ(中まで知ろう!Windows Live Writer)で、Windows Live Writerの、SDKには載っていないクラスを色々と紹介しました。その内容をうけて、このエントリではPublish Notification Hook プラグインで、投稿前に記事内容を書き換える方法を紹介したいと思います。以前にも、SharpLab. – publish notification hooksでpost内容を書き換えるにはというエントリでpublish notification hooksプラグインで投稿内容を書き換える方法を紹介したことがありました。ですが、

WLW 自体は書き換えられることを想定してないので、プラグインから書き換えても投稿後にエディタ中の表示は変化しません。

Publish Notification Hook プラグイン 値の書き換え-katamari.wankuma.com

というJZ5さんの検証エントリの通り、投稿後の画面がおかしくなる問題がありました。今回の方法ではその回避を図っています。

とりあえずソースコードを示します。

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using WindowsLive.Writer.Api;
using WindowsLive.Writer.BlogClient;
using WindowsLive.Writer.BlogClient.Clients;
using WindowsLive.Writer.PostEditor;
using WindowsLive.Writer.Extensibility.BlogClient;

using WriterMshtml = WindowsLive.Writer.Mshtml;

namespace SharpLab.WPCustomFieldsEditor {
    [WriterPlugin("0aaad6ce-da8b-4f78-a73c-c73f3c6c163d", "WPCustomFieldsEditor", PublisherUrl = "http://www.sharplab.net/")]
    public class PublishObserver : PublishNotificationHook {
        public override bool OnPrePublish(System.Windows.Forms.IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish) {

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);
            Blog blog = new Blog(postEditorForm.CurrentBlogId);

            //publishingContextからリフレクションでBlogPostEditingManagerを取得
            FieldInfo fieldInfo = publishingContext.GetType().GetField("_editingContext", BindingFlags.NonPublic | BindingFlags.Instance);
            BlogPostEditingManager manager = (BlogPostEditingManager)fieldInfo.GetValue(publishingContext);
            BlogPost blogPost = (BlogPost)publishingContext.PostInfo;

            blogPost.Title = "test";//エントリ内容への操作

            manager.EditPost(new BlogPostEditingContext(postEditorForm.CurrentBlogId, blogPost));

            return true;
        }

        private PostEditorForm getPostEditorForm(IWin32Window postProgressForm) {
            return (PostEditorForm)((Form)Form.FromHandle(postProgressForm.Handle)).Owner;
        }
    }
}

細かく見ていきましょう。

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);

この行ではPostEditorFormクラスのインスタンスを取得しています。前エントリ参照。

           Blog blog = new Blog(postEditorForm.CurrentBlogId);

この行ではBlogクラスのインスタンスを取得しています。前エントリ参照。

            FieldInfo fieldInfo = publishingContext.GetType().GetField("_editingContext", BindingFlags.NonPublic | BindingFlags.Instance);
            BlogPostEditingManager manager = (BlogPostEditingManager)fieldInfo.GetValue(publishingContext);

imageここでは、BlogPostEditingManagerクラスのインスタンスを取得してます。OnPrePublishメソッドの引数として渡されたpublishingContextにはBlogPostHtmlEditorクラス(WindowsLive.Writer.PostEditor.PostHtmlEditing名前空間に所属)のインスタンスが格納されており、その_editingContextというパブリックでないフィールドにBlogPostEditingManagerが格納されています。BlogPostHtmlEditorクラス自体もパブリックなクラスではないので、ここではリフレクションで取得しています。なお、BlogPostEditingManagerクラスはエントリを編集画面に読み込んだり、削除したりできるクラスです。正直、自分も良く分かっていません(笑)。

 

            BlogPost blogPost = (BlogPost)publishingContext.PostInfo;

ここでは編集対象のエントリを表すBlogPostクラスのインスタンスを取得しています。前エントリ参照。

            blogPost.Title = "test";//エントリ内容への操作

エントリ内容への書き換えをここで行うことが出来ます。この例ではタイトルの書き換えをしています。試したわけではありませんが、カテゴリや概要に対して変更を加えることもできる筈です。

            manager.EditPost(new BlogPostEditingContext(postEditorForm.CurrentBlogId, blogPost));

そして、書き換えた後の大事な後始末、書き換えたエントリのPostEditorEormへの再読み込みをここで行っております。BlogPostEditingManagerクラスのEditPostメソッドに、それっぽい引数を与えて呼び出せば読み込んでくれるようです。

JUL
30

WYSIWYG編集が可能で、Wordを扱うかのような感覚でBlogをサクサク書くことが出来るMS謹製投稿クライアントWindows Live Writer。本体だけでも相当強力なソフトですが、機能強化のための各種プラグインを開発することもできるようになっており、.NETをかじっている自分にはなかなか興味をそそられるソフトでもあります。その開発の仕方はJZ5さんこと、松江祐輔さんが書かれた使ってみよう! Windows Live SDK/API:第7回 Windows Live Writer … 技術評論社という記事がチュートリアルとしてとても分かり易いものとなっています。詳しいリファレンスとしてはWindows Live Writer SDKが現在の正式版に対応する公式で、Writer DevZone: Technical Preview: Now Available for Downloadにこの前出たTecnology Preview版のSDKが転がっています。どっちも英語ですけど。

で、このエントリでは、ここ数日オブジェクトブラウザを通じてWindows Live WriterのDLL群とにらめっこした結果わかった、SDKに載っていない本体の内部構造の話をしてみようかと。Windows Live Writerの中にどんなクラスがあるかや、どうやってそのインスタンスをプラグイン側から取得するかのお話。

Windows Live WriterのメインFormの取得方法

image 何はなくとも、記事編集画面が無ければ始まらない。Windows Live Writerの記事編集画面のFormのインスタンスをプラグインから取得する方法から説明を始めます。プラグインが呼び出された時に呼ばれるメソッドのうちいくつかは、dialogOwnerという、System.Windows.Forms.IWin32Window型の引数を持っています。このdialogOwnerという引数が今回のカギとなります。読んでの通り、dialogOwnerは親Formを示しており、SmartContentSource.CreateContentメソッドなら、記事編集画面のForm、PublishNotificationHook.OnPrePublishメソッドやOnPostPublishメソッドなら投稿中のプログレス表示を行うFormとなります。

        private PostEditorForm getPostEditorForm(IWin32Window postProgressForm) {
            return (PostEditorForm)((Form)Form.FromHandle(postProgressForm.Handle)).Owner;
        }

PublishNotificationHookの方から取得できるdialogOwnerからメインFormのインスタンスを取得したいならば、上記のようなメソッドを用意して取得すればOK。見ての通り、メインFormのクラス名はPostEditorFormで、WindowsLive.Writer.PostEditor名前空間に所属しているクラスです。今後は記事編集画面のFormのことはPostEditorFormと呼ぶことにします。

Blogクラスのインスタンスの取得

imageさて、前の項で取得できたPostEditorFormクラスには、CurrentBlogIdというプロパティがあります。このプロパティには、Windows Live Writerで管理しているBlogを識別するためのGUIDが入っており、これを基に現在編集対象としているBlogを表すBlogクラスのインスタンスを取得可能です。こんな感じに。↓

            Blog blog = new Blog(postEditorForm.CurrentBlogId);

BlogクラスはWindowsLive.Writer.BlogClient名前空間に所属しているクラスで、メンバには記事の取得や投稿に関するメソッドなど、Blogに関する様々な操作を実現するメソッドやプロパティが含まれています。Blogクラスをオブジェクトブラウザで表示したもののSSを示しましたが、サイズの関係でSSに写っていないものもたくさんあるので、是非自分で確かめてみてください。

BlogClientクラスのインスタンスの取得

ところでBlogクラスには、パブリックではないプロパティとしてBlogClientというプロパティがあります。このプロパティには、IBlogClient(WindowsLive.Writer.Extensibility.BlogClient名前空間に所属)というインターフェイスを実装したクラスのインスタンスが含まれています。一例を挙げると、WordPressClientクラスや、MovableTypeClientクラス、WindowsLiveSpacesClientクラス(全てWindowsLive.Writer.BlogClient.Clients名前空間に所属)などです。これらにはUsernameや、Passwordというプロパティが含まれており、自前でXML-RPCを使ってサーバーとやり取りしたい場合などに活用できます。(WordPressはMetaWeblobAPIの拡張に熱心であるので、Windows Live Writerが対応していない機能もあり、意外と使いたくなる場面があるものです)

publishingContext.PostInfoの実体

PublishNotificationHook.OnPrePublishメソッドやOnPostPublishメソッドのpublishingContextという引数には、PostInfoというIPostInfo型のプロパティがあるのは御存知だと思います。以前自分はこのプロパティに格納されているインスタンスの、IPostInfoインターフェイスでは読み取り専用になっているプロパティに対してリフレクションで値をセットするコードがなぜ動くのかが分からないとかぼやいていました

調べてみたところ、リフレクションでアクセスするのは、参照するのに使われたインターフェイスのメンバではなく、インスタンスのメンバだから、ということのようです。用語法をあまり理解できていないので、おかしな説明になっているかもしれません。要するに、PostInfoに対してリフレクションでアクセスできるのは、IPostInfoインターフェイスのメンバだけではなく、BlogPostクラスのメンバなのだ、ということです。これなら前のエントリのpi.CanWriteの部分がtrueを返すのも納得できます。

まぁとりあえずpublishingContext.PostInfoにはBlogPostクラスのインスタンスが入っているということです。そこで、こんな感じにキャストしてやると、

            BlogPost blogPost = (BlogPost)publishingContext.PostInfo;

よりエントリの情報を詳細に得ることができるようになります。投稿スラッグや概要(Excerpt)、投稿日時を表すっぽいプロパティもあるので、チェックしてみてはいかがでしょうか。

次のエントリでは、これらを利用して、Publish Notification Hook プラグインで、投稿前に記事内容を書き換える方法を紹介したいと思います。プラグインからの書き換え後、エディタ中の表示が変化しない問題を解決するために、エントリを管理しているクラスの説明も少しだけします。

前のエントリでは

表示モードを「HTMLコード」としていた場合、HTMLDocumentに対してプラグインから操作後に表示モードを「標準」に戻すと、HTMLDocumentに対する操作内容が飛んでしまう

という問題で躓いていたが、HTMLDocumentに対して操作を行う前に表示モードを「標準」にしておくことで対処できた。

こんな感じ。HTMLDocumentを直接操作できるようになって、うはー 夢が広がりんぐ

なお、表示モードの切り替えがタブ式になったTechnology Preview版限定。

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using WindowsLive.Writer.Api;
using WindowsLive.Writer.BlogClient;
using WindowsLive.Writer.BlogClient.Clients;
using WindowsLive.Writer.PostEditor;
using WindowsLive.Writer.Extensibility.BlogClient;

using WriterMshtml = WindowsLive.Writer.Mshtml;

namespace SharpLab.WPCustomFieldsEditor {
    [WriterPlugin("0aaad6ce-da8b-4f78-a73c-c73f3c6c163d", "WPCustomFieldsEditor", PublisherUrl = "http://www.sharplab.net/")]
    public class PublishObserver : PublishNotificationHook {
        public override bool OnPrePublish(System.Windows.Forms.IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish) {

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);

            WindowsLive.Writer.Controls.MiniTabsControl MiniTabsControl = (WindowsLive.Writer.Controls.MiniTabsControl)findControlByName(postEditorForm, "MiniTabsControl", "WindowsLive.Writer.Controls");
            MiniTabsControl.SelectTab(0);

            WriterMshtml.MshtmlEditor mshtmlEditor = (WriterMshtml.MshtmlEditor)findControlByName(postEditorForm, "MshtmlEditor", "WindowsLive.Writer.Mshtml");
            mshtml.IHTMLDocument2 doc = mshtmlEditor.HTMLDocument;
            //あとは煮るなり焼くなり。
        }

        private PostEditorForm getPostEditorForm(IWin32Window postProgressForm) {
            return (PostEditorForm)((Form)Form.FromHandle(postProgressForm.Handle)).Owner;
        }

        private Control findControlByName(Control control, string controlName, string controlNamespace) {

            foreach (Control cChild in control.Controls) {

                Type t = cChild.GetType();

                if (t.Name == controlName && t.Namespace == controlNamespace) {
                    return cChild;
                }

                if (cChild.HasChildren) {
                    Control returned = findControlByName(cChild, controlName, controlNamespace);
                    if (returned != null) {
                        return returned;
                    }
                }
            }

            return null;
        }
    }
}
JUL
19

WordPress 2.6を新規インストールした場合、XML-RPC API経由での投稿機能は、デフォルトでは無効になるようになったらしい。ver.2.6以前からのアップデートの場合は有効のまま。新規インストールしたWordPressにWindows Live Writerなどの投稿クライアントを組み合わせて運用することを考えている場合は注意しましょう。XML-RPC APIの有効化は管理画面の「設定」→「投稿設定」から。以下は情報元からの引用。

XML-RPC is disabled by default for new installs of WordPress. Upgrading will NOT disable XML-RPC (ticket 7157)

WordPress 2.6 – XML-RPC & AtomPub Changes – Joseph Scott’s Blog

このエントリには他にもXML-RPC APIのver.2.51からの変更点(ページテンプレートの取得、Blogオプションの取得/設定が出来るようになった、等)が列挙されているので、このエントリは一見の価値有り。

また、このBlogにはこんな記事もあった。

Custom fields for posts and pages are now exposed and manageable from metaWeblog.getPost/newPost/editPost, wp.getPage/newPage/editPage via the custom_fields field. I was really happy to get this in, I think there is a lot of potential in being able to manage custom fields externally.

WordPresss 2.5 – Joseph Scott’s Blog

WordPress 2.5からはカスタムフィールドのデータをXML-RPC APIから扱えるようになっていたらしい。知らんかった。憶えておこう。