COM对象通常具有确定性破坏:在释放最后一个引用时释放它们.
如何处理C# - COM Interop?这些类没有实现IDisposable,所以我认为无法触发显式的IUnknown :: Release.
随意测试显示未引用的COM对象被懒惰地收集(即垃圾收集器触发释放).对于需要被激活释放的OCM对象,我该怎么办?(例如持有大型或共享的关键资源)?
原始问题:我们有一个C#应用程序大量使用COM库,它像疯了一样泄漏.似乎问题是"在C++和C#代码之间"(我们可以访问它们),但我们无法确定它.
有没有办法将VB6组件编译成64位?
我的感觉是答案是"不",但我想证实这一点.
如果可以,请粘贴指向可确认的授权来源的链接.
环境:
Windows XP计算机
安装了Excel 2007和Excel 2003(按此顺序,而不是按时间顺序).
C#3.5
问题:
当我使用PIA进行一些Office自动化时,我使用以下代码行:
var excel = new ApplicationClass();
Run Code Online (Sandbox Code Playgroud)
PIA的版本特别指它为Excel 12.
C:\ WINDOWS\assembly\GAC\Microsoft.Office.Interop.Excel\12.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll
但是:
excel.Version;//this is 11.0 instead of 12.0
Run Code Online (Sandbox Code Playgroud)
因此,当我尝试打开一个扩展名为.xlsx的文件时,它会警告我文件转换中的功能丢失,并使用excel 2003打开它.我很确定它与安装顺序是2007 - > 2003,但我无法在我的机器上卸载2003 b/c我们在我们的网络服务器上有一些办公室自动化,用于使用excel 2003的无关项目.
我查看了Policy.11.0.Microsoft.Office.Interop.Excel.config的内容,但它说
<bindingRedirect oldVersion="11.0.0.0" newVersion="12.0.0.0"></bindingRedirect>
Run Code Online (Sandbox Code Playgroud)
所以,我不知所措.为什么我不能告诉COM Interop使用哪个版本的Excel?
我正在用C 开发一个COM代理对象,我的应用程序将使用它来为需要管理权限的某些操作调用UAC提升对话框.
计划是使它导出一个函数,该函数接受一个带有可变数量参数的函数的指针,并在不同的上下文中执行它.这样,应用程序可以使用此对象以管理员权限执行某些操作,他们需要做的就是使用该对象并将指针传递给必须使用所述权限执行的函数.
这部分工作,调用CoCreateInstance很好,函数指针传递,我的函数执行.但是,当我使用CoCreateInstanceAsAdmin创建此对象的实例时 ,会出现问题; 这是代码:
HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
// Manual implementation of CreateInstanceAsAdmin
CComPtr BindCtx;
HRESULT hr = CreateBindCtx(0,&BindCtx);
BIND_OPTS3 bo;
memset(&bo, 0, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.grfMode = STGM_READWRITE;
bo.hwnd = hwnd;
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
hr = BindCtx->SetBindOptions(&bo);
if (SUCCEEDED(hr))
{
// Use the passed in CLSID to help create the COM elevation moniker string
CComPtr Moniker;
WCHAR wszCLSID[50];
WCHAR wszMonikerName[300];
StringFromGUID2(rclsid,wszCLSID,sizeof(wszCLSID) …Run Code Online (Sandbox Code Playgroud) 警告:我不确定这是否可以被认为是一个正确的SO编程问题!
我在使用MS Office Suite时遇到了严重的性能损失,主要是因为我处理了数百万个COM来处理文档.部分问题是通过使用OOXML SDK而不是使用本机应用程序的API来解决的.但是,OOXML SDK本身会进行COM调用,这会减慢速度(是的,我已经适当地运行了Visual Studio的内置性能分析器和BoundsChecker,并确保算法是我们可以在整个过程中使用的最佳算法).我认为一层缓存可以加快速度(有时会将执行时间减少四分之一)(但显然,加速速度因我的访问模式而异,而访问模式又取决于文档的内容结构).
鉴于COM和C++已经存在了这么长时间,我很惊讶地看到在优化基于C++的COM应用程序上的材料很少.(快速搜索谷歌应该足以证明我的观点,但我不介意被证明是错误的!)
编辑:澄清:我不是真的在寻找替代方案(因为改变基础知识为时已晚).我有兴趣阅读过去人们可能面临的类似问题,以及他们如何解决这些限制.
是否可以使用注册免费COM与Dotnet互操作和C#?如果是这样,如何在C#项目中添加对COM对象的引用?
我有一个免费的ATL COM服务器DLL,带有嵌入式清单和两个测试客户端,一个cpp,另一个c#.cpp客户端使用import语句正确引用COM对象
#pragma comment(linker, "\"/manifestdependency:type='win32' name='TestComSvr2' version='1.0.0.0'\"")
Run Code Online (Sandbox Code Playgroud)
或者在Linker-> Manifest File选项下将'Additional Manifest Dependencies'设置为"type ='win32'name ='TestComSvr1'version ='1.0.0.0'",之后cpp客户端只要COM组件正确运行在同一目录中.
c#客户端虽然拒绝播放.
尝试将文件引用添加到未注册的COM组件dll或未注册的tlb会导致错误:
"无法添加对'blah blah'的引用.请确保该文件是可访问的,并且它是一个有效的程序集或COM组件".
仅使用'regtlib TestComSvr'注册类型库,然后创建文件或COM引用,导致c#项目无法构建:
"加载类型库/ DLL时出错.(HRESULT异常:0x80029C4A(TYPE_E_CANTLOADLIBRARY))".
通常在c#项目中注册COM组件并创建引用,将引用设置为Isolated,构建c#项目然后取消注册组件并运行c#项目会导致此异常:
由于以下错误,检索具有CLSID {B1D0A80F-0050-4856-BACD-87D664E58CBE}的组件的COM类工厂失败:80040154未注册类(HRESULT异常:0x80040154(REGDB_E_CLASSNOTREG)).
注意:即使这有效,但无论如何它都不是一个有用的案例,因为最终它仍然需要注册组件,我只是测试它的彻底性.
到目前为止,我能够从C#引用COM对象的唯一方法是通过注册COM对象本身,这当然完全违背了这一点,从那以后它根本就没有注册.
有人有任何想法吗?
(这是在带有VS2010 sp1的WinXP上).
我想使用await Task.Run(DoWork),在ThreadPool上做一些重复的单线程计算工作.问题是,我需要在里面使用STA COM对象DoWork,所以我想我不能使用ThreadPool因为我不能改变池线程的公寓状态.
我怎样才能在这种情况下使用async/ await?使用自定义任务调度程序创建自己的STA线程池听起来像是一项过度的工作.
我在Windows中使用C++控制台应用程序.我想在我的网站中使用这个应用程序,以便从客户端获取输入,然后调用此应用程序来处理它,输出将转发到Web服务器.我听说过COM DLL,但不知道如何为我的应用程序创建它.
所以我已经尝试在VBA类实例上调用ITypeInfo,虽然看起来很有希望但我想看看我是否可以获得对其包含项目的引用,类似于类型库.我认为ITypeInfo.GetContainingTypeLib可能很有用,但它会抛出一个异常,表明VBA不会合作.任何人都对VBA如何采用与标准COM规范不同的东西有任何想法?
C#类库代码在这里.注册COM interop并在AssemblyInfo.cs中设置COMVisible(true)以使其可从VBA访问.下面给出的VBA客户端代码.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace TypeLibraryInspector
{
[ComImport()]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo
(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo
);
//void GetTypeInfo(int typeInfoIndex, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler,
// MarshalTypeRef = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler))] out Type typeInfo);
//void GetTypeInfo(int typeInfoIndex, int lcid, out IntPtr piTypeInfo);
[PreserveSig]
int GetIDsOfNames
(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
); …Run Code Online (Sandbox Code Playgroud)