.NET で MSHTML をロードすると、IEコンポーネントで動作しない機能がある
.NET 2.0 で tlbimp した MSHTML.dll をロードすると、IEコンポーネントの印刷(プレビュー)機能や、IShellUIHelper.ShowBrowserUI の「お気に入りの整理」などが使用できなくなる。 解決 単に COM 参照で、 Microsoft HTML Object Library を追加したら動作した。
.NET 2.0 で tlbimp した MSHTML.dll をロードすると、IEコンポーネントの印刷(プレビュー)機能や、IShellUIHelper.ShowBrowserUI の「お気に入りの整理」などが使用できなくなる。 解決 単に COM 参照で、 Microsoft HTML Object Library を追加したら動作した。
IE7 では、ShellUIHelper に検索プロバイダの登録機能などを定義している IShellUIHelper2 が追加実装されているので SHDocVw が次のようになる。Guid は A7FE6EDA-1932-4281-B881-87B31B8BC52C である。 using System.Runtime.InteropServices; namespace SHDocVw { \[Guid("A7FE6EDA-1932-4281-B881-87B31B8BC52C")\] \[CoClass(typeof(ShellUIHelperClass))\] public interface ShellUIHelper : IShellUIHelper2 { } } このインスタンスをIE6環境で生成しようとすると、IShellUIHelper2 がないため InvalidCastException で落ちる。そのため、個別に COM コクラスを定義する。以前のGuid は、64AB4BB7-111E-11D1-8F79-00C04FC2FBE1 である。 using System.Runtime.InteropServices; namespace net.tilfin { \[ComImport(), Guid("64AB4BB7-111E-11D1-8F79-00C04FC2FBE1")\] public class ShellUIHelper { } } 「お気に入りの整理」を呼び出すサンプル .NET 2.0 で IDocHostUIHandler ではなくそこから参照している MSHTML をロード後に ShowBrowserUI や IE コンポーネントで印刷機能がなぜか効かなくなる。(調査中) object oHelper = new net.tilfin.ShellUIHelper(); SHDocVw.IShellUIHelper helper = (SHDocVw.IShellUIHelper)oHelper; helper.ShowBrowserUI("OrganizeFavorites", ref arg);
.NET 2.0 になり、アンマネージドとの相互変換時の変数型の定義を明確にしないと、InvalidVariant MDA メッセージが投げられるようになった。動作確認した定義は以下の通り。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 using System; using System.Runtime.InteropServices; using MSHTML; namespace net.tilfin { [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), GuidAttribute("bd3f23c0-d43e-11cf-893b-00aa00bdce1a")] public interface IDocHostUIHandler { [PreserveSig] uint ShowContextMenu( uint dwID, ref tagPOINT ppt, [MarshalAs(UnmanagedType.IUnknown)] object pcmdtReserved, [MarshalAs(UnmanagedType.IDispatch)] object pdispReserved ); void GetHostInfo(ref DOCHOSTUIINFO pInfo); void ShowUI(uint dwID, [In, MarshalAs(UnmanagedType.Interface)] IOleInPlaceActiveObject activeObject, [In, MarshalAs(UnmanagedType.Interface)] IOleCommandTarget commandTarget, [In, MarshalAs(UnmanagedType.Interface)] IOleInPlaceFrame frame, [In, MarshalAs(UnmanagedType.Interface)] Object doc); void HideUI(); void UpdateUI(); void EnableModeless(int fEnable); void OnDocWindowActivate(int fActivate); void OnFrameWindowActivate(int fActivate); void ResizeBorder(ref tagRECT prcBorder, int pUIWindow, int fFrameWindow); \[PreserveSig\] uint TranslateAccelerator(ref tagMSG lpMsg, ref Guid pguidCmdGroup, uint nCmdID); void GetOptionKeyPath(\[MarshalAs(UnmanagedType.BStr)\] ref string pchKey, uint dw); void GetDropTarget( \[MarshalAs(UnmanagedType.Interface)\] IDropTarget pDropTarget, \[Out, MarshalAs(UnmanagedType.Interface)\] out IDropTarget ppDropTarget); void GetExternal(\[MarshalAs(UnmanagedType.IDispatch)\] out object ppDispatch); \[PreserveSig\] uint TranslateUrl( uint dwTranslate, \[MarshalAs(UnmanagedType.BStr)\] string pchURLIn, \[MarshalAs(UnmanagedType.BStr)\] ref string ppchURLOut ); System.Windows.Forms.IDataObject FilterDataObject(System.Windows.Forms.IDataObject pDO); } }
他にも方法はあるだろうがレジストリから取得するのが一番良さそう。 文字列でIEのバージョンを返す。エントリがなく取得に失敗したら null を返す。 1 2 3 4 5 6 7 8 9 10 11 12 13 public static string getInternetExplorerVersion() { string rKeyName = @"SOFTWARE\\Microsoft\\Internet Explorer"; string rValueName = "Version"; try { Microsoft.Win32.RegistryKey rKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(rKeyName); string sVersion = (string)rKey.GetValue(rValueName); rKey.Close(); return sVersion; } catch (NullReferenceException) { return null; } }
ディレクトリパスをファイル名の結合をするときに、/ \ といった区切り文字を気にしないで行いたい。.NET では、Path という便利なクラスが用意されているが、Java ではそのようなユーティリティクラスはない。File のコンストラクタがその役目を担ってくれる。 Java String filePath = new File(dirPath, fileName).getPath(); C# string filePath = Path.Combine(dirPath, fileName);
下記のような、メールヘッダのDate値を変換する。 Date: Sun, 02 Jul 2006 19:45:13 +0100 CultureInfoを en-US にしないと、曜日、月の省略語を正しく認識できない。 // 変換に失敗すると FormatException を投げる。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static DateTime ParseMailDate(string field){ // (JST) などを取り払う int i = field.LastIndexOf("("); if (i > -1){ field = field.Substring(0, i).TrimEnd(); } string[] expectedFormats = {"ddd, d MMM yyyy HH':'mm':'ss zzz", "ddd, d MMM yyyy H':'m':'s zzz", "d MMM yyyy HH':'mm':'ss zzz", "ddd, d MMM yyyy HH':'mm':'ss", "ddd, d MMM yyyy H':'m':'s", "d MMM yyyy HH':'mm':'ss"}; // ゴミがあったら削除 if (field.Length > 31) { field = field.Substring(0, field.LastIndexOf(' ') \- 1); } return System.DateTime.ParseExact(field, expectedFormats, System.Globalization.CultureInfo.GetCultureInfo("en-US"), System.Globalization.DateTimeStyles.None); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 private struct WindowData { public System.Windows.Forms.HtmlDocument document; public IConnectionPoint icpWin; public int cookieWin; public IConnectionPoint icpDoc; public int cookieDoc; } private WindowData setWindowComConnect(object pDisp){ WindowData data = new WindowData(); // UCOM Connect Guid guid; data.document = (HTMLDocument)((SHDocVw.IWebBrowser2)pDisp).Document; // Document IConnectionPointContainer pConPtCon = (IConnectionPointContainer)data.document; guid = typeof(HTMLDocumentEvents2).GUID; pConPtCon.FindConnectionPoint(ref guid, out data.icpDoc); data.icpDoc.Advise(this, out data.cookieDoc); // Window IConnectionPointContainer pCpcWin = (IConnectionPointContainer)data.document.parentWindow; guid = typeof(HTMLWindowEvents2).GUID; pCpcWin.FindConnectionPoint(ref guid, out data.icpWin); data.icpWin.Advise(this, out data.cookieWin); return data; } private void unsetWindowComConnect(WindowData data){ if (data.icpWin != null) { try { data.icpWin.Unadvise(data.cookieWin); Marshal.ReleaseComObject(data.icpWin); } catch (Exception ex) { } } if (data.icpDoc != null) { data.icpDoc.Unadvise(data.cookieDoc); Marshal.ReleaseComObject(data.icpDoc); } if (data.document != null) { Marshal.ReleaseComObject(data.document); } }