标签: com

替换Visual C++中的#import

我们有大型C++项目,我们用它来编译/ MP交换机以利用多个内核.

但是,我们最近引入了一些在几个tlb上使用#import的代码,而#import与/ MP不兼容,这意味着我们回到单线程构建和更多时间来获取咖啡.

关于如何让#import和/ MP玩得好的任何建议?是否有一个工具可以从#import静态生成C++标头作为预构建步骤?

更新:

以下马特的建议很有效.对于其他在谷歌上绊倒这个的人:

  1. 创建一个单独的静态lib项目
  2. 设置足够的包含,以便您可以将该#import语句放在lib项目中
  3. 使您的主项目依赖于lib项目(以确保正确的构建顺序)
  4. 将lib项目的临时构建文件夹添加到主项目的包含路径
  5. #include.tlh您正在执行的生成的文件#import
  6. 启用/MP开关并失去咖啡休息时间......

com visual-c++

29
推荐指数
3
解决办法
5168
查看次数

访问COM组件时出错

我为Microsoft Office Word构建了一个加载项.当Word以管理员身份运行时使用加载项没有问题,但是当它不以管理员身份运行时,访问功能区元素有两个常见的例外.

第一个例外:

Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Core.IRibbonUI'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{000C03A7-0000-0000-C000-000000000046}' failed due to the following error:  could not be found. (Exception from HRESULT: 0x80030002 (STG_E_FILENOTFOUND)).
   at Microsoft.Office.Core.IRibbonUI.InvalidateControl(String ControlID)
Run Code Online (Sandbox Code Playgroud)

通过以下代码使控件无效时,会发生此错误:

ribbon.InvalidateControl("control-id");
Run Code Online (Sandbox Code Playgroud)

第二个例外:

Unable to cast COM object of type 'Microsoft.Office.Interop.Word.ApplicationClass' to interface type 'Microsoft.Office.Interop.Word._Application'. This operation failed because the QueryInterface call on the COM component for the interface …
Run Code Online (Sandbox Code Playgroud)

c# com office-2007 ms-word

29
推荐指数
2
解决办法
5万
查看次数

*每个*Excel互操作对象是否需要使用Marshal.ReleaseComObject释放?

编辑

另请参阅如何正确清理Excel互操作对象?.我最近遇到了这个问题,它提供了很多关于如何正确处理COM对象的问题的见解.绝对检查超出第一个(标记的)答案,因为其他答案超出了简单的"不要使用两个点"和" ReleaseComObject用于每个com对象"的建议.

我首先重新审视了这个问题,因为我意识到尽管注册和处理所有COM对象非常彻底,但我的Excel实例仍然没有得到妥善处理.事实证明,有些方法可以创建完全不明显的COM对象(即,即使您从不使用两个点,也可以错过COM对象).此外,即使您是彻底的,如果您的项目增长超过一定的大小,错过COM对象的机会接近100%.当发生这种情况时,很难找到你错过的那个.上面链接的问题的答案提供了一些其他技术,以确保Excel实例肯定关闭.同时,我对我ComObjectManager(下面)做了一个小的(但重要的)更新,以反映我从上面链接的问题中学到的东西.

原始问题

我已经看到了几个Marshal.ReleaseComObject()与Excel Interop对象一起使用的例子(即来自命名空间Microsoft.Office.Interop.Excel的对象),但我已经看到它用于不同程度.

我想知道我是否可以逃避这样的事情:

var application = new ApplicationClass();
try
{
    // do work with application, workbooks, worksheets, cells, etc.
}
finally
{
    Marashal.ReleaseComObject(application)
}
Run Code Online (Sandbox Code Playgroud)

或者,如果我需要释放创建的每个对象,如此方法:

public void CreateExcelWorkbookWithSingleSheet()
{
    var application = new ApplicationClass();
    var workbook = application.Workbooks.Add(_missing);
    var worksheets = workbook.Worksheets;
    for (var worksheetIndex = 1; worksheetIndex < worksheets.Count; worksheetIndex++)
    {
        var worksheet = (WorksheetClass)worksheets[worksheetIndex];
        worksheet.Delete();
        Marshal.ReleaseComObject(worksheet);
    }
    workbook.SaveAs(
        WorkbookPath, _missing, _missing, _missing, _missing, _missing,
        XlSaveAsAccessMode.xlExclusive, _missing, …
Run Code Online (Sandbox Code Playgroud)

.net c# com excel office-interop

28
推荐指数
2
解决办法
4776
查看次数

HRESULT:0x80040154(REGDB_E_CLASSNOTREG))

我正在构建一个GIS应用程序,但每当我运行代码时,它都会给我这个错误

System.Runtime.InteropServices.COMException未处理检索具有CLSID {FBF5715D-A05D-11D4-A64C-0008C711C8C1}的组件的COM类工厂由于以下错误而失败:80040154未注册类(HRESULT异常:0x80040154(REGDB_E_CLASSNOTREG)) .

此外,在项目属性中,禁用COM Interop注册选项.

.net c# windows com

28
推荐指数
2
解决办法
10万
查看次数

传统DLL和COM DLL之间的区别

我正在学习COM.我发现COM DLL是基于传统的DLL基础结构构建的.当我们构建COM DLL时,我们仍然依赖传统的DLL导出方法来引导我们进入内部COM共同类.

如果COM用于二进制级别的组件重用,我认为传统的DLL可以实现相同的功能.它们都暴露了函数,它们都是二进制的,那么转向COM方法有什么意义呢?

目前,我感觉传统的DLL以" 平面 "方式公开方法,而COM DLL以" OOP "层次方式公开方法.OOP方式似乎是一种更好的方法.这可能是COM占主导地位的原因吗?

非常感谢.

c++ com

28
推荐指数
6
解决办法
2万
查看次数

PIA嵌入是否在.NET 4.0 beta 2中被破坏?

不久前,我在Visual Studio beta 1中编写了一些Word互操作示例,并将引用设置Microsoft.Office.Interop.Word为嵌入(在引用属性中设置"嵌入互操作类型"= true).这些工作正常,我暂时没有运行它们......直到今天.

当然,现在我在Visual Studio 2010和.NET 4.0的beta 2下运行 - 它似乎有点破碎.

这是有问题的代码(只是虚拟示例代码):

using Microsoft.Office.Interop.Word;

class WordImprovement1
{
    static void Main()
    {
        Application app = new Application { Visible = true };
        app.Documents.Add();
        Document doc = app.ActiveDocument;            
        Paragraph para = doc.Paragraphs.Add();
        para.Range.Text = "Thank goodness for C# 4";

        object filename = "demo.doc";
        object format = WdSaveFormat.wdFormatDocument97;
        doc.SaveAs(FileName: ref filename, FileFormat: ref format);
        doc.Close();
        app.Quit();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我大多数情况下的例外情况,当"嵌入互操作类型"设置为"true"或我在命令行上使用"/ l"链接时:

System.MissingMethodException: Method not found:
'Void Microsoft.Office.Interop.Word._Application.set_Visible(Boolean)'.
   at WordImprovement1.Main() …
Run Code Online (Sandbox Code Playgroud)

com interop .net-4.0 .net-4.0-beta-2 c#-4.0

27
推荐指数
1
解决办法
1211
查看次数

如何将WebBrowser控件放入IE9标准?

我正在使用自动化(即COM自动化)在Internet Explorer(9)中显示一些HTML:

ie = CoInternetExplorer.Create;
ie.Navigate2("about:blank");
webDocument = ie.Document;
webDocument.Write(szSourceHTML);
webDocument.Close();
ie.Visible = True;
Run Code Online (Sandbox Code Playgroud)

出现Internet Explorer,显示我的html,其开头为:

<!DOCTYPE html>
<HTML>
<HEAD>
   ...
Run Code Online (Sandbox Code Playgroud)

注意: html5标准模式选择加入doctypehtml

除非文件不符合ie9标准模式; 它是在ie8标准模式下: 替代文字


如果我先将html保存到我的电脑:

替代文字

然后查看那个 html文档,将IE放入标准模式:

替代文字

我的问题是如何更新我的SpawnIEWithSource(String html)功能以使浏览器进入标准模式?

void SpawnIEWithSource(String html)
{
   Variant ie = CoInternetExplorer.Create();
   ie.Navigate2("about:blank");
   webDocument = ie.Document;
   webDocument.Write(html);
   webDocument.Close();
   ie.Visible = true;
}
Run Code Online (Sandbox Code Playgroud)

编辑:一个更详细,更不易理解或可读的代码示例,这无助于进一步提出问题可能是:

IWebBrowser2 ie;
CoCreateInstance(CLASS_InternetExplorer, null, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_WebBrowser2, ie);
ie.AddRef();
ie.Navigate2("about:blank");

IHtmlDocument doc;
dispDoc = ie.Document;
dispDoc.AddRef();
dispDoc.QueryInterface(IHTMLDocument2, doc);
dispDoc.Release()
doc.Write(html); 
doc.Close();
doc.Release();
ie.Visible = true;
ie.Release(); …
Run Code Online (Sandbox Code Playgroud)

com standards html5 automation internet-explorer-9

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

Active Directory COM异常 - 发生操作错误(0x80072020)

当我尝试使用方法GroupPrincipal.FindByIdentity查询Active Directory时,我收到间歇性COM异常" 发生操作错误(0x80072020) "(如下所示)

这是我的代码:

PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName);
GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, "Group to find");
Run Code Online (Sandbox Code Playgroud)

我收到例外:

Inner Exception: System.Runtime.InteropServices.COMException (0x80072020): An operations error occurred.
  at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
  at System.DirectoryServices.DirectoryEntry.Bind()
  at System.DirectoryServices.DirectoryEntry.get_AdsObject()
  at System.DirectoryServices.PropertyValueCollection.PopulateList()
  at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
  at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)
  at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInitNoContainer()
  at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()
  at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()
  at System.DirectoryServices.AccountManagement.PrincipalContext.get_QueryCtx()
  at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)
  at System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, String identityValue)
  at System.DirectoryServices.AccountManagement.GroupPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, …
Run Code Online (Sandbox Code Playgroud)

.net c# com exception active-directory

27
推荐指数
3
解决办法
5万
查看次数

与[ComVisible]默认和公共类COM暴露有什么关系?

MSDN有关于[ComVisible]属性的这篇文章.我不太清楚当一个人设置时会发生什么[ComVisible(true)].

MSDN说

默认值为true,这表明托管类型是COM可见.不需要此属性来使公共托管程序集类型可见 ; 它们在默认情况下对COM可见.只有公共类型才能显示.

所以他们说公共类型默认是COM可见的.但他们也说只有通过设置才能看到公共类型[ComVisible(true)].它没有意义:如果默认情况下公共类型是可见的,那么设置如何[ComVisible(true)]使公共类型可见?如果它们已经可见,它们将如何变得更加醒目?

也许我的理解不正确.如果有人能对上述陈述有所了解,我将不胜感激.

c# com comvisible

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

StaTaskScheduler和STA线程消息泵送

TL; DR:运行任务中的死锁StaTaskScheduler.长版:

我使用的是StaTaskSchedulerParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留STA COM对象.StaTaskScheduler实现细节的描述如下:

好消息是TPL的实现能够在MTA或STA线程上运行,并考虑到底层API的相关差异,如WaitHandle.WaitAll(当方法提供多个等待句柄时,它只支持MTA线程).

我认为这意味着TPL的阻塞部分将使用等待API来提供消息,例如CoWaitForMultipleHandles,以避免在STA线程上调用时出现死锁情况.

在我的情况下,我相信发生以下情况:进程内STA COM对象A调用进程外对象B,然后期望从B通过回调作为传出调用的一部分.

以简化形式:

var result = await Task.Factory.StartNew(() =>
{
    // in-proc object A
    var a = new A(); 
    // out-of-proc object B
    var b = new B(); 
    // A calls B and B calls back A during the Method call
    return a.Method(b);     
}, CancellationToken.None, TaskCreationOptions.None, staTaskScheduler);
Run Code Online (Sandbox Code Playgroud)

问题是,a.Method(b)永远不会回来.据我所知,这是因为内部阻塞等待BlockingCollection<Task>不会引发消息,因此我对引用语句的假设可能是错误的.

EDITED相同的代码工作测试WinForms应用程序的UI线程上执行时(即,提供TaskScheduler.FromCurrentSynchronizationContext()的,而不是staTaskSchedulerTask.Factory.StartNew).

解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …

.net c# com task-parallel-library async-await

27
推荐指数
2
解决办法
9314
查看次数