言語:C# / Ver:2008 / プラットフォーム:Windows Vista
現在、Windows 7 Professional 64bit上にて、デスクトップ検索のアドオンをC#で開発しています。MSDNの技術情報や、SDKのサンプル、オープンソースプロジェクト「MILPA」に含まれているSearchHelperのコードをもとにDLLファイルを作ってはみたのですが、何かが不足しているようで、OSがアドオンとして認識しません(認識された場合はLoadメソッドが呼び出される)。ビルドのやりかたに問題があるかもしれませんので、SkyDriveにて問題のプロジェクトと、参考のための正常にアドオンとして動作するC言語バージョンのプロジェクトをアップロードしておりますので、よろしければ知恵をお貸しください。ちなみに、C++/CLIでアドオンを開発した場合、アドオンとしては認識するものの、CLIのクラスが参照された時点でなぜかフリーズしてしまいます。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using CT = System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using Microsoft.Win32;
using System.IO;
namespace Test.ShellExt
{
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("0000010C-0000-0000-C000-000000000046")]
public interface IPersist
{
void GetClassID(ref Guid pClassID);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000109-0000-0000-C000-000000000046")]
public interface IPersistStream : IPersist
{
[PreserveSig]
int IsDirty();
void Load([In] CT.IStream pStm);
void Save([In] CT.IStream pStm, [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
void GetSizeMax(out long pcbSize);
}
[StructLayout(LayoutKind.Sequential)]
public struct FILTERREGION
{
public uint cwcExtent;
public uint cwcStart;
public uint idChunk;
}
[StructLayout(LayoutKind.Explicit)]
public struct PROPSPEC_DATA
{
[FieldOffset(0)]
public UInt32 propid;
[FieldOffset(0)]
public IntPtr lpwstr;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROPSPEC
{
public uint ulKind;
public PROPSPEC_DATA data;
}
[StructLayout(LayoutKind.Sequential)]
public struct FULLPROPSPEC
{
public Guid guidPropSet;
public PROPSPEC psProperty;
}
public enum CHUNK_BREAKTYPE : uint
{
CHUNK_NO_BREAK = 0,
CHUNK_EOW = 1,
CHUNK_EOS = 2,
CHUNK_EOP = 3,
CHUNK_EOC = 4,
}
[Flags]
public enum CHUNKSTATE
{
CHUNK_TEXT = 1,
CHUNK_VALUE = 2,
CHUNK_FILTER_OWNED_VALUE = 4,
}
[Flags]
public enum IFILTER_INIT
{
NONE = 0,
CANON_PARAGRAPHS = 1,
HARD_LINE_BREAKS = 2,
CANON_HYPHENS = 4,
CANON_SPACES = 8,
APPLY_INDEX_ATTRIBUTES = 16,
APPLY_OTHER_ATTRIBUTES = 32,
INDEXING_ONLY = 64,
SEARCH_LINKS = 128,
APPLY_CRAWL_ATTRIBUTES = 256,
FILTER_OWNED_VALUE_OK = 512
}
[StructLayout(LayoutKind.Sequential)]
public struct STAT_CHUNK
{
public FULLPROPSPEC attribute;
public CHUNK_BREAKTYPE breakType;
public uint cwcLenSource;
public uint cwcStartSource;
public CHUNKSTATE flags;
public uint idChunk;
public uint idChunkSource;
public uint locale;
}
[ComImport]
[Guid("89BCB740-6119-101A-BCB7-00DD010655AF")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFilter
{
void Init(
[MarshalAs(UnmanagedType.U4)] IFILTER_INIT grfFlags,
uint cAttributes,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] FULLPROPSPEC[] aAttributes,
ref uint pdwFlags
);
[PreserveSig]
int GetChunk(out STAT_CHUNK pStat);
[PreserveSig]
int GetText(ref int pcwcBuffer, [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer);
[PreserveSig]
int GetValue(ref IntPtr ppPropValue);
void BindRegion([MarshalAs(UnmanagedType.Struct)]FILTERREGION origPos, ref Guid riid, ref UIntPtr ppunk);
}
[ComVisible(true)]
[Guid("A607B2D0-24BE-4FE3-8794-2CDAC3D40EA7")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("VVFilter")]
public class TestFilter : IFilter, IPersistStream
{
public const int E_NOTIMPL = (unchecked((int)0x80004001L));
public const int FILTER_E_NO_VALUES = (unchecked((int)0x80041706));
public const int FILTER_E_NO_TEXT = (unchecked((int)0x80041705));
public static readonly Guid TESTFILTER_ID = new Guid("A607B2D0-24BE-4FE3-8794-2CDAC3D40EA7");
public TestFilter()
{
}
~TestFilter()
{
}
[ComRegisterFunction]
public static void RegisterFunction(Type t)
{
try {
Console.WriteLine("Regist start");
RegistryKey regHKCR, subkey, guidkey;
string fid = TESTFILTER_ID.ToString("B");
string hid = "{AE63F9EB-DFA3-4032-A435-923E7C903E05}";
regHKCR = Registry.ClassesRoot;
subkey = regHKCR.CreateSubKey("CLSID");
guidkey = subkey.CreateSubKey(fid);
guidkey.SetValue(string.Empty, "Test IFilter Class");
subkey = regHKCR.CreateSubKey("CLSID");
guidkey = subkey.CreateSubKey(hid);
guidkey.SetValue(string.Empty, "Test IFilter Handler");
subkey = guidkey.CreateSubKey("PersistentAddinsRegistered");
subkey = guidkey.CreateSubKey("PersistentAddinsRegistered\\{89BCB740-6119-101A-BCB7-00DD010655AF}");
subkey.SetValue(string.Empty, fid);
regHKCR = Registry.ClassesRoot;
subkey = regHKCR.CreateSubKey(".test");
subkey = subkey.CreateSubKey("PersistentHandler");
subkey.SetValue(string.Empty, hid);
subkey = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\RSSearch\\ContentIndexCommon\\Filters\\Extension\\.test");
subkey.SetValue(string.Empty, fid);
Console.WriteLine("Finish");
} catch (Exception ex) {
#if DEBUG
Console.WriteLine(ex.Message + System.Environment.NewLine + ex.StackTrace);
#endif
}
}
[ComUnregisterFunction]
public static void UnregisterFunction(Type t)
{
Console.WriteLine("Unregist Start");
RegistryKey regHKCR, subkey;
try {
regHKCR = Registry.ClassesRoot;
subkey = regHKCR.OpenSubKey(".test", true);
subkey.DeleteSubKeyTree("PersistentHandler");
subkey = regHKCR.OpenSubKey("CLSID", true);
subkey.DeleteSubKeyTree(TESTFILTER_ID.ToString("B"));
} catch (Exception ex) {
Console.Write(ex.Message);
}
Console.WriteLine("Unregist Finish");
}
// IFilter メンバ
public void BindRegion([MarshalAs(UnmanagedType.Struct)]FILTERREGION origPos, ref Guid riid, ref UIntPtr ppunk)
{
}
public int GetChunk(out STAT_CHUNK pStat)
{
throw new NotImplementedException();
}
public int GetText(ref int pcwcBuffer, [Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder buffer)
{
return FILTER_E_NO_TEXT;
}
[PreserveSig]
public int GetValue(ref IntPtr ppPropValue)
{
return FILTER_E_NO_VALUES;
}
public void Init(
[MarshalAs(UnmanagedType.U4)] IFILTER_INIT grfFlags,
uint cAttributes,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] FULLPROPSPEC[] aAttributes,
ref uint pdwFlags
)
{
}
// IPersistStream メンバ
public void GetSizeMax(out long pcbSize)
{
pcbSize = 0;
}
public int IsDirty()
{
return E_NOTIMPL;
}
public void Load(CT.IStream pstm)
{
CT.STATSTG s;
pstm.Stat(out s, 0);
}
public void Save(CT.IStream pStm, bool fClearDirty) { }
// IPersist メンバ
public void GetClassID(ref Guid pClassID)
{
pClassID = TESTFILTER_ID;
}
}
}