我们有大型C++项目,我们用它来编译/ MP交换机以利用多个内核.
但是,我们最近引入了一些在几个tlb上使用#import的代码,而#import与/ MP不兼容,这意味着我们回到单线程构建和更多时间来获取咖啡.
关于如何让#import和/ MP玩得好的任何建议?是否有一个工具可以从#import静态生成C++标头作为预构建步骤?
更新:
以下马特的建议很有效.对于其他在谷歌上绊倒这个的人:
#import语句放在lib项目中#include.tlh您正在执行的生成的文件#import/MP开关并失去咖啡休息时间......我为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) 编辑
另请参阅如何正确清理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) 我正在构建一个GIS应用程序,但每当我运行代码时,它都会给我这个错误
System.Runtime.InteropServices.COMException未处理检索具有CLSID {FBF5715D-A05D-11D4-A64C-0008C711C8C1}的组件的COM类工厂由于以下错误而失败:80040154未注册类(HRESULT异常:0x80040154(REGDB_E_CLASSNOTREG)) .
此外,在项目属性中,禁用COM Interop注册选项.
我正在学习COM.我发现COM DLL是基于传统的DLL基础结构构建的.当我们构建COM DLL时,我们仍然依赖传统的DLL导出方法来引导我们进入内部COM共同类.
如果COM用于二进制级别的组件重用,我认为传统的DLL可以实现相同的功能.它们都暴露了函数,它们都是二进制的,那么转向COM方法有什么意义呢?
目前,我感觉传统的DLL以" 平面 "方式公开方法,而COM DLL以" OOP "层次方式公开方法.OOP方式似乎是一种更好的方法.这可能是COM占主导地位的原因吗?
非常感谢.
不久前,我在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自动化)在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标准模式选择加入doctype
html
除非文件不符合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) 当我尝试使用方法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) MSDN有关于[ComVisible]属性的这篇文章.我不太清楚当一个人设置时会发生什么[ComVisible(true)].
MSDN说
该默认值为true,这表明托管类型是COM可见.不需要此属性来使公共托管程序集和类型可见 ; 它们在默认情况下对COM可见.只有公共类型才能显示.
所以他们说公共类型默认是COM可见的.但他们也说只有通过设置才能看到公共类型[ComVisible(true)].它没有意义:如果默认情况下公共类型是可见的,那么设置如何[ComVisible(true)]使公共类型可见?如果它们已经可见,它们将如何变得更加醒目?
也许我的理解不正确.如果有人能对上述陈述有所了解,我将不胜感激.
TL; DR:运行任务中的死锁StaTaskScheduler.长版:
我使用的是StaTaskScheduler从ParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留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()的,而不是staTaskScheduler到Task.Factory.StartNew).
解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …
com ×10
c# ×6
.net ×4
.net-4.0 ×1
async-await ×1
automation ×1
c#-4.0 ×1
c++ ×1
comvisible ×1
excel ×1
exception ×1
html5 ×1
interop ×1
ms-word ×1
office-2007 ×1
standards ×1
visual-c++ ×1
windows ×1