用于独立 VB.NET 应用程序的免注册COM - 复杂情况



我阅读了整个互联网关于免注册的COM/DLL,但我的问题更复杂。

我正在 VB.NET 准备一个应用程序,该应用程序将在用户没有管理员权限的环境中使用,因此我不能简单地安装它或注册 COM。此 COM 是由 Microsoft 设计的 LogParser 库。 DLL 也不必嵌入 - 会很好,但它也可以在启动期间从 exe 中提取 - 我对这种方法没问题

通常在主窗体中,我有一个按钮,可以通过以下方式调用另一个窗体:LogParser_Form.Show()

这是另一种形式"导入MSUtil",它是一个Interop.MSUtil.dll由Fody Costura附加组件嵌入到exe中。 Form 还包含一个类,该类具有在 COM 中定义的变量的多个声明,例如: IISW3CLOG暗为新的 COMIISW3CInputContextClass (不止一个(

但是这个 dll 指的是更大的地方:LogParser.dll它实际上是一个需要注册的 COM 组件,所以单击按钮时我的LogParser_Form不会出现,但它会抛出一个异常,即找不到 COM 组件...... 不幸的是,Fody Costura或Ilmerge不为COM工作...

我尝试了多种清单文件等技巧,但没有运气......

你是我最后的希望 - 请帮助我...如何在不注册的情况下将此 COM 嵌入到 exe 中? 我想正确使用的清单文件可能会有所帮助,但我没有找到成功使用它的方法......

让免注册 COM 工作可能很棘手,但在正确配置时可以工作。关键问题是创建清单,其中记录了所有必需的依赖项。在您的情况下,您需要两个清单:

  • 应用程序的客户端清单
  • 日志分析器库的服务器清单。此部分需要一个用于分析类型库的工具,例如 OLE/COM 对象查看器 (oleview.exe(。它允许查看 LogParser.dll 中的嵌入式类型库。

让我们以 LogParser 帮助文件中记录的(略有修改的(C# 示例为例。在本例中,客户端名为"logqryclient.exe",运行时可调用包装器是通过类型库导入器 (tlbimp( 创建的。

using System;
using Interop.MSUtil;
namespace logqryclient
{
class Program
{
static void Main(string[] args)
{
try
{
// Instantiate the LogQuery object
ILogQuery oLogQuery = new LogQueryClassClass();
// Create the query
string query = @"SELECT TOP 50 SourceName, EventID, Message FROM System";
// Execute the query
ILogRecordset oRecordSet = oLogQuery.Execute(query, null);
// Browse the recordset
for (; !oRecordSet.atEnd(); oRecordSet.moveNext())
{
ILogRecord rec = oRecordSet.getRecord();
Console.WriteLine(rec.toNativeString(","));
}
// Close the recordset
oRecordSet.close();
}
catch (System.Runtime.InteropServices.COMException exc)
{
Console.WriteLine("Unexpected error: " + exc.Message);
}
}
}
}

若要在不注册 COM 类的情况下使用此代码,首先需要将 LogParser.dll 放入与客户端可执行文件相同的目录中。

接下来,您需要创建一个随附的服务器清单(此处名为"LogParser.manifest"(。这记录了接口的所有必要类和编组信息(线程切换需要(。如前所述,您需要一个类型库分析器来访问类和接口标识符。

在上述情况下,您需要以下各项的标识符:

  • ILogQuery 接口和 LogQueryClass 类
  • ILog记录集接口
  • ILog记录接口

因此,服务器清单可能如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="LogParser" version="1.0.0.0" />
<file name = "LogParser.dll">
<!-- LogQueryClass -->
<comClass 
clsid="{8CFEBA94-3FC2-45CA-B9A5-9EDACF704F66}"
threadingModel = "Apartment" />
<!-- Embedded type library -->
<typelib 
tlbid="{A7E75D86-41CD-4B6E-B4BD-CC2ED34B3FB0}" 
version="1.0" 
helpdir=""/>
</file>
<!-- Marshalling information for interfaces -->
<comInterfaceExternalProxyStub 
name="ILogQuery" 
iid="{3BDE06BC-89E4-42FD-BE64-832A5F33D7D3}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{A7E75D86-41CD-4B6E-B4BD-CC2ED34B3FB0}" />
<comInterfaceExternalProxyStub 
name="ILogRecordset" 
iid="{C9452B1B-093C-4842-ABD1-F81410926874}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{A7E75D86-41CD-4B6E-B4BD-CC2ED34B3FB0}" />
<comInterfaceExternalProxyStub 
name="ILogRecord" 
iid="{185FFF88-E24A-4984-9621-AA41BEAE8513}"
proxyStubClsid32="{00020424-0000-0000-c000-000000000046}"
baseInterface="{00000000-0000-0000-c000-000000000046}"
tlbid = "{A7E75D86-41CD-4B6E-B4BD-CC2ED34B3FB0}" />
</assembly>

若要允许客户端查找服务器清单并最终查找 LogParser 库,请将以下客户端清单嵌入到"logqryclient.exe"客户端中:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type = "win32"
name = "logqryclient"
version = "1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="LogParser"
version="1.0.0.0" />
</dependentAssembly>
</dependency>
</assembly>

现在,所有必需的信息都位于清单中,以便您可以在免注册配置中运行代码。

最新更新