Oli*_*ock 9 .net c# windows com
我试图让COM启动我的进程外.NET COM服务器.如果使用x64编译服务器进程,它可以工作,但是如果我使用AnyCPU(这是我想要的),那么它会挂起一段时间并最终因0x80080005(CO_E_SERVER_EXEC_FAILURE)而失败.我怎样才能让它发挥作用?
另一个人有类似的问题,但MSFT的答案令人困惑.他似乎建议它只能通过DCOM(见链接)或COM +工作.我怀疑要么是要做很多工作,要么比分发我的.exe构建为x64和x86要糟糕得多.
你可能想知道我为什么要实现IPersistFile.这是因为我的真正问题是让BindMoniker()从32位C++程序运行到我的AnyCPU .Net程序.我把问题简化为这里提出的更简单的例子.
这是客户端代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
static extern object CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
[Flags]
enum CLSCTX : uint
{
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000,
}
private void Form1_Load(object sender, EventArgs e)
{
IPersistFile pf = (IPersistFile)CoCreateInstance(
new Guid("1984D314-FC8D-44bc-9146-8A13500666A6"),
null,
CLSCTX.CLSCTX_LOCAL_SERVER,
new Guid("0000010b-0000-0000-C000-000000000046")); // IPersistFile
pf.Load("c:\\bozo", 0);
}
}
Run Code Online (Sandbox Code Playgroud)
这是服务器:
static class Program
{
[STAThread]
static void Main()
{
if (Environment.CommandLine.Contains("/reg")) {
RegistryKey cls = Registry.LocalMachine.CreateSubKey(String.Format(
"SOFTWARE\\Classes\\CLSID\\{0}", PersistFile.ClassID.ToString("B")));
cls.SetValue("InprocHandler32", "Ole32.dll");
RegistryKey ls32 = cls.CreateSubKey("LocalServer32");
ls32.SetValue(null, '"' + Application.ExecutablePath + '"');
ls32.SetValue("ServerExecutable", Application.ExecutablePath);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
RegistrationServices reg = new RegistrationServices();
reg.RegisterTypeForComClients(
typeof(PersistFile),
RegistrationClassContext.LocalServer,
RegistrationConnectionType.MultipleUse);
Application.Run(new Form1());
}
}
[ComVisible(true),
Guid("1984D314-FC8D-44bc-9146-8A13500666A6"),
ClassInterface(ClassInterfaceType.None)]
public class PersistFile : IPersistFile
{
public static Guid ClassID
{
get
{
GuidAttribute a = (GuidAttribute)typeof(PersistFile).GetCustomAttributes(typeof(GuidAttribute), false)[0];
return new Guid(a.Value);
}
}
#region IPersistFile
public void GetClassID(out Guid pClassID)
{
MessageBox.Show("GetClassID");
pClassID = ClassID;
}
public int IsDirty()
{
MessageBox.Show("IsDirty");
return 1;
}
public void Load(string pszFileName, int dwMode)
{
MessageBox.Show(String.Format("Load {0}", pszFileName));
}
public void Save(string pszFileName, bool fRemember)
{
MessageBox.Show("Save");
throw new NotImplementedException();
}
public void SaveCompleted(string pszFileName)
{
MessageBox.Show("SaveCompleted");
throw new NotImplementedException();
}
public void GetCurFile(out string ppszFileName)
{
MessageBox.Show("GetCurFile");
throw new NotImplementedException();
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
尝试使用RegistrationServices类来注册您的 com 程序集。它还会选择正确的注册表路径并执行一些其他操作。
例子:
Assembly currentAssembly = Assembly.GetExecutingAssembly();
System.Runtime.InteropServices.RegistrationServices regAsm = new System.Runtime.InteropServices.RegistrationServices();
bool isRegistered = regAsm.RegisterAssembly(currentAssembly, System.Runtime.InteropServices.AssemblyRegistrationFlags.SetCodeBase);
Run Code Online (Sandbox Code Playgroud)
我还认为,根据 .NET com 服务器,.NET 客户端程序集存在一些问题,但我找不到任何资源......
希望,这会有所帮助...