通常我们在程序的开头导入一个tlb文件
#include < stdio.h >
#import " sql.tlb "
Run Code Online (Sandbox Code Playgroud)
但是当我在程序中间满足某些条件时,我需要导入一个tlb文件
我怎样才能做到这一点.加载dll有LoadLibrary()但是加载tlb我可以使用LoadLibrary().
因为tlb是使用.dll生成的?
我和被称为COM Interop的野兽长期相遇...
我目前正在尝试从OLE/COM对象查看器生成的.idl文件生成.tlb.但是,当尝试运行Midl.exe来编译它时,我收到一个错误:
.\Sim.API.IDL(236) : error MIDL2025 : syntax error : expecting a type s
pecification near "ImportFileStatus"
Run Code Online (Sandbox Code Playgroud)
我的.idl文件超过1000行,所以我不特别想在这里发帖,我相信感兴趣的部分是:
typedef [uuid(980B172E-19C1-389A-BB74-29A54737C5B4), version(1.0) ,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Sim.API.ImportFileResult")
]
struct tagImportFileResult {
ImportFileStatus _status;
LPSTR _message;
} ImportFileResult;
Run Code Online (Sandbox Code Playgroud)
然后几行......
typedef [uuid(A4B9A0FF-A2D4-3EC5-AB7E-69311B9122C8), version(1.0) ,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "Sim.API.ImportFileStatus")
]
enum {
ImportFileStatus_Success = 0,
ImportFileStatus_VersionMismatch = 1,
ImportFileStatus_Failure = 2
} ImportFileStatus;
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,应该尊重这些以修复类型规范错误.但是,如果我这样做,我会遇到一个新问题.
midl\oleaut32.dll : warning MIDL2368 : error generating type library, ignored :
Could not set UUID : tagImportFileResult (0x800288C6)
Run Code Online (Sandbox Code Playgroud)
我对idl格式非常不熟悉,并且使用midl.exe,也许我正在做的事情有些明显错误?
一如既往的任何帮助将不胜感激:)
我有现有的COM接口.我不想创建一个将新接口公开为COM(带有新GUID)的.net程序集,但接口的结构必须相同.
如何创建一个公开此接口的.net类(C#)?
[
odl,
uuid(1ED4C594-DDD7-402F-90DE-7F85D65560C4),
hidden,
oleautomation
]
interface _IFlashPhase : IUnknown {
[propget]
HRESULT _stdcall ComponentName(
[in] short i,
[out, retval] BSTR* pVal);
[propput]
HRESULT _stdcall ComponentName(
[in] short i,
[in] BSTR pVal);
[propget]
HRESULT _stdcall ComponentMolePercent(
[in] short i,
[out, retval] double* pVal);
[propput]
HRESULT _stdcall ComponentMolePercent(
[in] short i,
[in] double pVal);
[propget]
HRESULT _stdcall ComponentFugacity(
[in] short i,
[out, retval] double* pVal);
[propput]
HRESULT _stdcall ComponentFugacity(
[in] short i,
[in] double pVal);
};
Run Code Online (Sandbox Code Playgroud) 我在使用COM传递指向本机代码的指针时遇到问题.我想在托管(C#)代码中构建一个字节数组,并将该数组传递给本机(C++)代码.我正在处理托管代码方面,我的同事拥有本机方面.请注意,我在托管方面更强大,而且我几乎一直在使用COM对象.
COM签名(简化)看起来像这样:
unsafe void DoSomething([In] byte* buffer, [In] uint length)
Run Code Online (Sandbox Code Playgroud)
我称之为:
var arr = File.ReadAllBytes(@"c:\temp\foo.bar");
fixed (byte* p = arr)
{
// let's see what we're actually pointing at
IntPtr ip = new IntPtr(p);
Console.WriteLine(ip.ToInt32().ToString("x"));
interop.DoSomething(p, arr.Length);
}
Run Code Online (Sandbox Code Playgroud)
在托管端调试,我看到打印出来的内存位置的数据(使用Visual Studio的内存视图).当我调试非托管端时,我也在该位置看到了正确的数据.但是,指针并没有指向正确的位置!它指向一个完全不同的内存位置.该位置包含我的数据的正确的第一个字节,但其余部分包含垃圾.然后,当然,发生了许多奇妙的崩溃.
所以,例如,我看到:
p)为0x1234567,0x1234567处的内存包含我文件的内容.buffer)是0x5678901,该位置的内存的第一个字节包含我文件的第一个字节,其余是垃圾.内存0x1234567包含我的文件的内容.我也试过自动封送:
void DoSomething([In] [MarshalAs(UnmanagedType.LPArray,
ArraySubType = UnmanagedType.U1)]
byte[] buffer,
[In] uint length)
Run Code Online (Sandbox Code Playgroud)
...在管理端使用直字节数组; 同样的结果.
我已经尝试分配内存Marshal.AllocHGlobal,将数据复制到其中Marshal.Copy并将结果传递IntPtr给a byte*.结果相同.
我到底错过了什么?
这是一个32位进程.我尝试过小型(300B)和大型(10MB)缓冲区大小.C#3.5,VS 2010.
我有一个用C#编写的dll,并且暴露给COM.我在构建器中使用dll ...我可以实例化该类,但是在编译C#方法调用的返回值时遇到了问题.
C#
public string GetValue([MarshalAs(UnmanagedType.LPWStr)] string key)
{
return "value";
}
Run Code Online (Sandbox Code Playgroud)
导入到构建器中的已翻译函数:
virtual HRESULT STDMETHODCALLTYPE GetValue(LPWSTR key/*[in]*/,
BSTR* pRetVal/*[out,retval]*/) = 0;
Run Code Online (Sandbox Code Playgroud)
我对C++知之甚少.'key'参数传递得很好,因为我能够在参数上使用'MarshalAs'属性,但我要么不知道如何为返回值声明它,要么不知道如何调用在C++方面的功能(我尝试了几件事,只是猜测).
更新:好的,我只是通过采取Anton的例子并根据Hans的评论尝试修改来解决问题.Antons的回答正如他所展示的那样,但由于对内存管理问题的关注,我最终没有在C#中应用return属性,而C++代码调用函数如下:
BSTR result;
obj->GetValue(key, &result);
SysFreeString(key);
SysFreeString(result);
Run Code Online (Sandbox Code Playgroud)
我希望我可以赞扬这两个答案,帮助我解决这个问题,他们都必须向我提供我需要的信息.
在我的C#代码中,我希望能够记录COMExceptions,以便不仅输出HRESULTs的十六进制表示形式(例如0x80004005),而且输出相应的WinError.h定义符号(例如E_FAIL)。
如果我调用ToString()异常引用,则只有十六进制表示形式。
是否有一种内置方法来获取对象内部值的类似E_FAIL人类可读的常量?HRESULTCOMException
我Microsoft Office Interop Word用来使用C#生成文档.为了使文档生成工作,应该有一个在进入"Microsoft Office Word 97 - 2003 Document"下Dcom Config Settings为如下所示:

首次安装Microsoft Office时,Local Path下面General Tab有正确的路径.如果我然后将计算机加入域,然后使用域用户重新启动系统,则Local Path变为空白,应用程序不会生成文档并出错.
即使我首先将计算机加入域,然后使用域用户登录然后安装Microsoft Office,Local Path首先显示正确,然后在重新启动后再次变为空白.同时,在同一时间,如果我登录Local User时,Path仍然存在.
是什么导致价值Local Path变为空白?
所有这些设置都在虚拟机上,并且自动化一词在域帐户上工作,因为我看到它在加入域的物理机器上工作.
UPDATE: What my application is doing:
Run Code Online (Sandbox Code Playgroud)
我的应用程序中有4-5个组件.
第一个是VSTO Word AddIn,它与Microsoft Word集成,我们在其中创建包含一些也保存在数据库中的表达式的新文档.表达式上也有条件,它们也可以嵌套.表达式包含XSD文件中的架构元素,这些元素保存在数据库中.创建此类文档后,其WordML将保存在数据库中.这一切都在VSTO AddIn中完成.
第二个是Web服务,它从另一个组件接收输入xml,该组件确认上面的XSD,架构元素嵌入到通过VSTO addIn创建的文档中的表达式中.此Web服务检查验证和其他几项任务.然后,它从数据库中获取相应的Word文档的WordML中,并将其传递到使用它的API,遍历它递归来替换输入XML其实际值的架构元素的话语互操作.然后,将WordML作为word文档保存到文件中.
这也会在保存文档之前将模板附加到文档中.它使用Word Interop的SaveAs功能将文件另存为PDF.
更新:我又通过我的完整的应用程序不见了,才知道我们被解析的Office Open XML(例如用于输送输入到Word文档)做的所有的事情,但是,我们使用的是Word自动化做的唯一的事情是以下:
所有这四个代码如下所示,仅包含相关的代码部分:
Microsoft.Office.Interop.Word.Document wordDocument = null;
object templateName = "templateFile.dotm";
wordDocument = this.WordApplication.Documents.Add(ref …Run Code Online (Sandbox Code Playgroud) 我有一个用C#编写的DLL,并设置为COM可见性.我将它设置为并排组件,并且可以将应用程序成功部署到客户端PC免费注册.我的问题与开发PC有关.是否可以在类似的免注册庄园中针对DLL进行编译,或者是否需要在开发机器上进行注册?我已经尝试通过Project -> References菜单直接添加DLL 并收到错误,指出"无法添加对特定文件的引用".DLL与.vbp文件位于同一目录中,我尝试添加DLL,无论是否存在客户端应用程序清单.
我为一个目前致力于在C#/。NET中创建Windows桌面应用程序的团队工作,该应用程序通过Office COM Interop与Microsoft Excel的本地用户实例进行交互。我目前负责指定新产品,但是有人告诉我,除非该应用程序可以在Mac和Windows上运行,否则该项目将无法继续进行-也就是说,我们必须能够生产Mac版本的应用程序可以本机安装在OSX上并与Microsoft Excel for Mac用户实例的对象模型进行交互。
使用Parallels,Mono或Wine运行该应用程序(请参见OSX中的Wine的COM互操作,此问题从未得到解答)不是解决方案,因为该应用程序的规范要求不得以任何方式修改用户计算机。我们只需要假设用户正在运行一个许可的Excel本地副本,然后使用该副本即可……这是我们在Windows上一贯所做的,而且效果很好。
我认为.NET Core是答案,但我找不到在任何地方明确表明我们可以(或将能够)在Mac OSX上使用Excel的本地副本运行.NET Core时从C#访问Excel对象库。适用于Mac。有人可以指出我已经讨论过的地方吗?但是,如果没有,那么请告诉我,如果这在他们的.NET Core路线图中,该如何向Microsoft查找?
我有一个混合的VB6(入口点)到.Net应用程序.
在.Net中,我有一个类,它具有Date属性(Date1-Date4),并且公开了,并且COM Visible等等于VB6代码.
在VB6代码中有一个方法,它采用Date ByRef并修改它.
使用在VB6(dt1-dt4)中声明的日期,这可以正常工作,我传递ByRef的日期变量得到更新,但是如果我在我的类(Date1-Date4)上传递.Net日期,它会更新.
work arround是将TmpDate传递给方法,然后将值分配给.Net属性.
然而,我想找到一个合适的解决方案,因为我正在替换VB6代码,这很容易被遗漏.
VB.Net宣言
<ComVisible(True)>
Public Class DotNetDatesClass
Implements INotifyPropertyChanged, IDotNetDatesClass
Private _Date1 As DateTime
<ComVisible(True)>
Public Property Date1 As DateTime Implements IDotNetDatesClass.Date1
Get
Return _Date1
End Get
Set(value As DateTime)
_Date1 = value
End Set
End Property
Run Code Online (Sandbox Code Playgroud)
VB6示例:
dotNetDates.Date1 = DEFAULT_DATE
dotNetDates.Date2 = DEFAULT_DATE
dotNetDates.Date3 = DEFAULT_DATE
dotNetDates.Date4 = DEFAULT_DATE
getDates connectionString, dotNetDates.Date1, dotNetDates.Date2, dotNetDates.Date3, dotNetDates.Date4
Run Code Online (Sandbox Code Playgroud)
解决方法:
Dim dt1 As Date
Dim dt2 As Date
Dim dt3 As Date
Dim dt4 As Date …Run Code Online (Sandbox Code Playgroud) com-interop ×10
c# ×6
com ×6
.net ×3
c++ ×3
idl ×2
vb6 ×2
.net-core ×1
dcom ×1
error-code ×1
excel ×1
macos ×1
marshalling ×1
midl ×1
regfreecom ×1
side-by-side ×1
typelib ×1
vb.net ×1
visual-c++ ×1