标签: com

COM互操作是否尊重.NET AppDomain边界以进行程序集加载?

这是核心问题:我有一个在单独的AppDomain中使用COM互操作的.NET应用程序.COM的东西似乎是将程序集加载回默认域,而不是从中调用COM内容的AppDomain.

我想知道的是:这是预期的行为,还是我做错了导致这些COM相关程序集被加载到错误的AppDomain中?请参阅以下情况的更详细说明......

该应用程序由3个程序集组成: - 主EXE,应用程序的入口点. - common.dll,只包含一个接口IController(采用IPlugin风格) - controller.dll,包含一个实现IController和MarshalByRefObject的Controller类.此类完成所有工作并使用COM interop与另一个应用程序进行交互.

主要EXE的相关部分如下所示:

AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain");
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller");
result = c.Run();
AppDomain.Unload(controller_domain);
Run Code Online (Sandbox Code Playgroud)

common.dll只包含以下两件事:

public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun}
public interface IController
{
    ControllerRunResult Run();
}
Run Code Online (Sandbox Code Playgroud)

controller.dll包含这个类(也调用COM互操作的东西):

public class Controller: IController, MarshalByRefObject
Run Code Online (Sandbox Code Playgroud)

首次运行应用程序时,Assembly.GetAssemblies()看起来像预期的那样,在两个AppDomain中都加载了common.dll,并且只将controller.dll加载到控制器域中.在调用c.Run()之后,我看到与COM互操作内容相关的程序集已加载到默认的AppDomain中,而不是在发生COM互操作的AppDomain中.

为什么会发生这种情况?

如果你有兴趣,这里有一些背景知识:

最初这是一个AppDomain应用程序.它与之接口的COM东西是一个服务器API,它在长时间使用时不稳定.当COM东西发生COMException(没有关于其原因的有用诊断信息)时,整个应用程序必须重新启动才能再次使用COM连接.只需重新连接到COM应用服务器,就会再次导致COM异常.为了解决这个问题,我试图将COM互操作内容移动到一个单独的AppDomain中,这样当神秘的COMExceptions出现时,我可以卸载发生它的AppDomain,创建一个新的并再次启动,所有这些都无需手动重启应用程序.无论如何,这就是理论......

c# com interop com-interop appdomain

8
推荐指数
1
解决办法
3397
查看次数

C#interop:在将新工作表添加到现有文件后,excel进程不会退出

可能重复:
如何在C#中正确清理Excel互操作对象

我在这里阅读了许多关于管理COM引用的其他线程,同时使用.Net-Excel互操作来确保Excel进程在退出时正确退出,到目前为止,这些技术已经运行良好,但我最近遇到了一个将新工作表添加到现有工作簿文件时出现问题.

下面的代码留下了僵尸Excel进程.

如果我将工作表添加到新创建的工作簿文件,它将退出正常.如果我运行除.Add()行之外的代码,它会退出.(我正在读取的现有文件是由注释掉的代码创建的空文件)

有任何想法吗?

//using Excel = Microsoft.Office.Interop.Excel;
//using System.Runtime.InteropServices;
public static void AddTest()
{
  string filename = @"C:\addtest.xls";
  object m = Type.Missing;
  Excel.Application excelapp = new Excel.Application();
  if (excelapp == null) throw new Exception("Can't start Excel");
  Excel.Workbooks wbs = excelapp.Workbooks;

  //if I create a new file and then add a worksheet,
  //it will exit normally (i.e. if you uncomment the next two lines
  //and comment out the .Open() line below):
  //Excel.Workbook wb = wbs.Add(Excel.XlWBATemplate.xlWBATWorksheet);
  //wb.SaveAs(filename, …
Run Code Online (Sandbox Code Playgroud)

c# com excel interop pia

8
推荐指数
2
解决办法
3万
查看次数

即使找到接口,CoCreateInstance也会返回E_NOINTERFACE

我有一个COM类在一个应用程序中CMyCOMServer实现IMyInterface,两个都具有正确的GUID.CMyCOMServer::QueryInterface如果请求IUnknown或IMyInterface,则返回S_OK(并将其自身转换为正确的类型),否则返回E_NOINTERFACE.

在同一台PC上的另一个应用程序中,我打电话给:

HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER,
 __uuidof(IMyInterface ),(void **)&pInterface);
Run Code Online (Sandbox Code Playgroud)

它返回E_NOINTERFACE.所以我认为我做错了什么并添加了一个断点CMyCOMServer::QueryInterface.我发现在CoCreateInstance调用时,QueryInterface会针对不同的接口多次触发:

  • 首先,要求IUnknown - 没问题
  • 然后,请求几个接口,如IMarshall等...这些不受支持,因此返回E_NOINTERFACE
  • 最后,请求IMyInterface.我验证QueryInterface返回S_OK并按(IMyInterface *)this预期设置为接口指针

所以我的困惑是为什么调用CoCreateInstance给我留下一个NULL指针并返回E_NOINTERFACE代码,当COM服务器应用程序显然返回我要求的接口?

编辑:我的客户端应用程序在启动时调用CoInitialize(NULL),这没有任何区别.

c++ windows com com-interop visual-c++

8
推荐指数
2
解决办法
1万
查看次数

com4j与jacob从Java调用COM方法

我维护一个使用Jacob或Java-COM Bridge 的遗留Java应用程序,通过MS VBA和MS Word的COM接口进行调用.我一直在关注来自Sun的com4j,看起来很有希望.

它对我来说很好的原因是它使用vtable绑定到方法,而不是IDispatch.假设我们操作的所有COM对象都存在vtable接口,使用它们而不是IDispatch似乎更简洁.回到COM和CORBA热门二进制接口技术的时代,我似乎记得通过vtable的早期绑定比通过IDispatch的后期绑定提供了更好的性能.

有没有人从雅各布迁移到com4j?如果是这样,那么陷阱和经验教训是什么?

java com com+ com-interop jacob

8
推荐指数
1
解决办法
6923
查看次数

如何使用ITypeInfo指针获取类型的名称?

应该是一个简单的问题,但搜索文档让我疯了.假设我有一个coclass或接口的ITypeInfo指针.如何获取该类或接口的名称?

com automation

8
推荐指数
1
解决办法
2008
查看次数

如何为所有用户注册COM对象

我用来regsvr32 MyCOM.dll为我的应用程序注册我的com对象.这在我的管理员帐户下工作正常.如果将用户切换为非管理员,则程序失败.似乎没有为非管理员用户加载COM对象.关于为什么会这样或可能的解决方案的任何想法?

windows com permissions privileges

8
推荐指数
2
解决办法
3万
查看次数

如何抑制由我​​无法更改的代码显示的对话框?

我有来自第三方的Inproc COM服务器.如果它捕获特定类型的错误,我调用的函数之一将显示错误消息对话框.问题是我正在尝试批量处理数据,而我使用的数据源导致错误对话框弹出很多.如果它生成了1000个对话框,这不会成为问题,而是它会阻塞,直到您按OK才会返回该功能.

在此输入图像描述

如何禁止显示对话框,或以编程方式按OK?

这是一个调用堆栈的副本,​​因为它正在等待我按OK

    [Managed to Native Transition]  
>   System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) Line 2198 + 0x1e bytes   C#
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) Line 3422 + 0x1b bytes C#
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) Line 3306 + 0xc bytes   C#
    System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) Line 1495 + 0x31 bytes    C#
    UniversalDataImporter.exe!UniversalDataImporter.Program.Main() Line 18 + 0x1d bytes C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) Line 2023 + 0x18 bytes  C#
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes  
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object …

.net c# com messagebox .net-4.0

8
推荐指数
1
解决办法
7990
查看次数

SetApartmentState和[STAThread]

在Watin的源代码中,有这段代码:

    public void NavigateToNoWait(Uri url)
    {
        var thread = new Thread(GoToNoWaitInternal);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start(url);
        thread.Join(500);
    }

    [STAThread]
    private void GoToNoWaitInternal(object uriIn)
    {
        var uri = (Uri)uriIn;
        NavigateTo(uri);
    }
Run Code Online (Sandbox Code Playgroud)

由于创建的线程设置了其单元状态,为什么该[STAThread]属性被添加到方法中?我对特定的代码段不感兴趣,但我想知道是否STAThread需要属性.

笔记:

  • 该方法GoToNoWaitInternal不在别处使用.
  • 整个watin项目是关于操纵WebBrowser对象(一般的Internet Explorer窗口).因此,我们正在操纵COM对象.

c# com multithreading watin sta

8
推荐指数
1
解决办法
7085
查看次数

如何在Java中使用C#System.DBNull.value?

我正在将一些用C#编写的代码翻译成Java.此代码使用COM对象与第三方应用程序进行交互.我设法使用com4j库处理COM对象,但其中一个方法需要System.DBNull.value传递给它,这是一个C#对象.

如何从Java应用程序处理它?

c# java com

8
推荐指数
1
解决办法
1707
查看次数

在C#中使用相同的COM接口在2个不同的库之间进行转换

我有一对使用相同COM接口的库.在一个库中,我有一个实现该接口的类.另一个库需要一个实现接口的对象.

但是两个库都有自己的接口定义.两者略有不同,但基本上是相同的界面.

所以我尝试将它们放在如下:

 Library2.Interface intf = (Library2.Interface)impl;
Run Code Online (Sandbox Code Playgroud)

但这引起了例外.如果我执行以下操作:

 Library1.Interface intf = (Library1.Interface)impl;
Run Code Online (Sandbox Code Playgroud)

然后它没有问题,但我不能再将类传递给Library2.

我天真地假设两个具有相同GUID的接口都可以防止这是一个问题,但我似乎错了.有谁知道如何在两个库之间进行转换?也许是通过某种元帅?

.net c# com casting com-interop

8
推荐指数
1
解决办法
536
查看次数