标签: com-interop

为什么办公室PIA没有正确安装到GAC?

我目前正在研究ac #project,我需要访问Outlook.开发工作是在两台不同的机器上完成的,其中一台机器安装了办公室,另一台则没有.我之前曾询问如何针对outlook com对象编译我的项目,其中一条评论建议我针对办公室主互操作程序集或PIA进行编译.在我下载的Office 2007 PIA中,有一个msi文件,应该为Office的不同部分安装许多PIA.我的问题是,这似乎不会发生.打字后,在我办公室的机器上

msiexec /i o2007pia.msi
Run Code Online (Sandbox Code Playgroud)

在提示符下,Windows安装程序启动,并显示一个消息框,显示"请等待Windows配置Microsoft Office 2007主互操作程序集.收集所需信息"以及大约33%的进度条,之后它将消失,之后

gacutil -l microsoft.office.interop.outlook
Run Code Online (Sandbox Code Playgroud)

Office 2007没有产生任何结果(我得到一个结果,版本为10.0.4504.0,是早期安装尝试与Office版本错误的结果.但Office 2007 PIA具有主要版本12.)

我看到了几个可能的解释,其中没有一个我真的相信:

  • GAC无法处理同一程序集的多个版本,因此不允许我安装较新版本.

  • 不知怎的,我不满足要求.这些基本上都是XPsp2,以及.Net 1.1或更高版本,我都有.要求部分还提到,下载适用于Office 2007,我没有安装,但我不认为这是一个要求.这既是因为没有被指定为要求,而且因为Hans Passant对我原来的问题的评论非常肯定PIA可以专门用于没有安装Office的开发,所以没有任何意义办公室作为先决条件.

那么有没有人知道为什么Office 2007 PIA没有正确安装,或者我能做些什么来接近答案?如果您需要更多信息,请告诉我.谢谢.

.net windows-xp gac com-interop office-pia

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

何时有必要/适当使用InAttribute和OutAttribute进行COM Interop

我正在尝试遍历各种项目中分散的COM互操作定义的混乱,并将它们收集到一个已知良好的位置,整个开发团队可以从中受益.这项工作的一部分涉及清理多年来积累的定义.

其中一些是从其他源代码借来的,有些是从pinvoke.net逐字复制的,有些看起来是直接从SDK头文件中翻译过来的.我注意到的一件事是关于何时使用各种编组属性没有一致性(即使在pinvoke.net示例中,这也非常棒).部分问题是,我不认为这里的任何人(包括我自己)完全理解何时需要各种属性,或者他们实际做了什么.到目前为止,获得这些权利似乎是猜测和随机变化的结合,直到COMExceptions停止发生,但我更倾向于翻译是正确的,因为有人实际上看了他们并宣布他们如此.

所以,我开始[In][Out].我知道这两个属性在概念上是什么:它们告诉编组人员数据必须走向哪个方向.例如,我假设 marshaller不会打扰将[In]数据复制回调用者,或者知道[Out]可能需要在被调用者端释放数据,等等.我不知道的事情是:

  1. 什么时候需要使用这些属性?也就是说,什么时候默认的编组行为是错误的,这样属性才能使其正确?
  2. 什么时候使用这些属性是安全的?也就是说,指定什么应该是默认行为会改变marshaller的工作方式?
  3. 什么时候使用这些属性是危险的?我假设显式标记输出参数[In]是坏的,但是标记输入参数[In, Out]实际上会破坏任何东西?

因此,给定一个假设的COM接口方法,其IDL如下所示:

HRESULT Foo(
    [in] ULONG a,
    [out] ULONG * b
    [in, out] ULONG * c);
Run Code Online (Sandbox Code Playgroud)

我可能会将此翻译为以下任何一种:

void Foo(
  uint cb,
  out uint b,
  ref uint c);

void Foo(
  uint cb,
  [Out] out uint b,
  [In, Out] ref uint c);

void Foo(
  [In] uint cb,
  [Out] out uint b,
  [In, Out] ref uint c); …
Run Code Online (Sandbox Code Playgroud)

c# com-interop

16
推荐指数
1
解决办法
2689
查看次数

为什么在VB6中C#null被翻译为空,而不是Nothing

我有一个引用VB6 DLL的C#应用​​程序.当我将C#中的null传递给VB6 dll函数时,null在VB6中被转换为值Empty(value),而不是Nothing(object).例如:

 // function in vb6 dll that referenced by c# app
 Public Sub TestFunc(ByVal oValue As Variant)
 {
   ...
   if oValue is Nothing then
     set oValue = someObject
   end if
   ...

 }

 // main c# code
 private void Form1_Load(object sender, EventArgs e)
 {
    object testObject = new object();
    testObject = null;
    TestFunc(testObject);
 }
Run Code Online (Sandbox Code Playgroud)

当我传递一个对象(非null)时,它将作为对象传递给VB6.但是当null传递给vb6时,它变为值类型为Empty,而不是对象类型Nothing.谁知道为什么?无论如何,当从c#app传递时,我可以强制null为VB6中的Nothing吗?

非常感谢.

c# vb6 com com-interop

15
推荐指数
2
解决办法
2224
查看次数

注册托管COM组件时是否需要"已实现的类别"键?

手动注册COM Interop的托管类时,需要某些注册表项.例如

HKEY_CLASSES_ROOT
  CLSID\[My Cls Id]
    InprocServer32
     (Default) = "mscoree.dll"
     Assembly = [My assembly name]
     etc.
Run Code Online (Sandbox Code Playgroud)

我注意到当VS为COM Interop注册一个库时,它还会添加一个键

HKEY_CLASSES_ROOT
  CLSID\[My Cls Id]
    Implemented Categories
      {62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}
Run Code Online (Sandbox Code Playgroud)

这个关键是什么,是否绝对必要?据我所知,如果没有它,生活就会好起来,但也许我没有遇到需要它的情况.

.net registry com-interop

15
推荐指数
1
解决办法
4985
查看次数

我是否需要在每个'foreach'迭代中释放COM对象?

这是(潜在的)问题:

我创建一个COM对象,然后使用'foreach'迭代它返回的集合中的每个元素.我是否需要释放我在集合中迭代的每个元素?(参见下面的代码.)如果是这样的话,我无法想出一种有效地从'finally'语句中释放它的方法,以防万一在项目被操作时出现错误.

有什么建议?

private static void doStuff()
{
    ComObjectClass manager = null;

    try
    {
        manager = new ComObjectClass();
        foreach (ComObject item in manager.GetCollectionOfItems())
        {
            Log.Debug(item.Name);
            releaseComObject(item); // <-- Do I need this line?
                                    //     It isn't in a 'finally' block...
                                    //             ...Possible memory leak?
        }
    }
    catch (Exception) { }
    finally
    {
        releaseComObject(manager);
    }
}

private static void releaseComObject(object instance)
{
    if (instance != null)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(instance);
        }
        catch
        {
            /* log potential memory leak */
            Log.Debug("Potential memory …
Run Code Online (Sandbox Code Playgroud)

c# com memory-leaks memory-management com-interop

14
推荐指数
1
解决办法
2868
查看次数

如何正确编组VB脚本数组与用C#编写的COM组件编组

我正在C#(.NET 4.0)中构建一个COM对象,用于经典的asp站点.现在我想知道在组件和asp站点之间来回编组VB脚本数组(单维和多维)的正确方法是什么?代码示例将受到高度赞赏.

.net arrays com-interop marshalling asp-classic

14
推荐指数
1
解决办法
5114
查看次数

Marshal.GetActiveObject()在C#中抛出MK_E_UNAVAILABLE异常

以下vbscript代码完美地工作:

Dim App 
Set App = GetObject("","QuickTest.Application")
App.Quit
Run Code Online (Sandbox Code Playgroud)

但是当我将它翻译成C#代码时,如下所示:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        object qtApp = Marshal.GetActiveObject("QuickTest.Application");
        (qtApp as QuickTest.Application).Quit();
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了例外:

mscorlib.dll中发生未处理的"System.Runtime.InteropServices.COMException"类型异常

附加信息:( HRESULT异常:0x800401E3(MK_E_UNAVAILABLE))

我不认为问题与ROT有关,因为vbscript代码有效.那么C#代码有什么问题?

c# com-interop

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

释放临时COM对象

使用COM对象考虑以下C#代码.


MyComObject o = new MyComObject;
try
{
 var baz = o.Foo.Bar.Baz;
 try
 { 
  // do something with baz
 }
 finally
 {
  Marshal.ReleaseComObject(baz);
 }
}
finally
{
 Marshal.ReleaseComObject(o);
}

这将释放COM对象obaz,而不是临时对象returnd的o.Fooo.Foo.Bar.当这些对象拥有大量非托管内存或其他资源时,这可能会导致问题.

一个明显但丑陋的解决方案是,使用try-finally和更加混乱代码Marshal.ReleaseComObject.请参阅 C#+ COM Interop,确定性版本

作为一种解决方法,我创建了一个帮助类


class TemporaryComObjects: IDisposable
{
 public C T<C>(C comObject)
 {
  m_objects.Add(comObject);
  return comObject;
 }
 public void Dispose()
 {
  foreach (object o in m_objects)
   Marshal.ReleaseComObject(o);
 }
}

用法:


using (TemporaryComObjects t = new TemporaryComObjects())
{ …
Run Code Online (Sandbox Code Playgroud)

.net c# com interop com-interop

13
推荐指数
1
解决办法
2028
查看次数

在构建服务器上注册COM引用的DLL

我们正在开发一个引用一些COM库的C#应用​​程序(例如AutoIT).

我在源控件下包含所有引用的组件,在第三方"Libs"文件夹中.

问题是COM dll在.csproj文件中没有HintPath属性,我认为必须使用regsvr32(或使用某种脚本)手动注册这些属性.

我目前正在寻找创建一个将在每次构建之前运行的MSBuild脚本,但是我无法弄清楚我应该手动调用regsvr32.exe还是使用一些预定义的MSBuild任务?

目前,这是我作为测试所支持的:

 <?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
  <ItemGroup>
    <MyAssemblies Include="D:\*.dll" />
  </ItemGroup>
  <Target Name="Build">
    <RegisterAssembly
      Assemblies="@(MyAssemblies)" >
    </RegisterAssembly>
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

这会生成我在给定文件夹中放置的DLL不是有效DLL的错误.

什么是这个问题的好方法?

编辑:

引用COM dll的项目在.csproj文件中有类似的内容:

<COMReference Include="AutoItX3Lib">
      <Guid>{F8937E53-D444-4E71-9275-35B64210CC3B}</Guid>
      <VersionMajor>1</VersionMajor>
      <VersionMinor>0</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>tlbimp</WrapperTool>
      <Isolated>False</Isolated>
    </COMReference>
Run Code Online (Sandbox Code Playgroud)

这不包括任何提示路径作为其他托管程序集,因此在构建服务器上,找不到引用的COM dll.

使用REGSVR32在构建服务器上注册COM dll时,构建成功.

c# msbuild continuous-integration interop com-interop

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

用强名称签署我的程序集会阻止它工作

我的一位同事在VB.net中创建了一个程序集,用于通过COM互操作与JScript一起使用.组件过去工作正常,但我们签了它,现在它似乎只适用于Windows 7机器.我测试了2台Windows 7机器和2台Windows Vista机器.

当我们签署程序集并尝试在JScript中实例化ActiveX对象时,将返回一个错误,但没有消息,只有一个数字:

错误:
错误号:-2146234304

在Google上搜索错误编号并没有太多回复.

如果我们从程序集中删除强名称,它就可以正常工作.关于什么可能是问题的任何想法?不确定它是否有所作为,但正在使用VS 2010编译和签署程序集.

.net javascript strongname assemblies com-interop

12
推荐指数
2
解决办法
3467
查看次数