【问题标题】:How to embed dll from "class project" into my project in vb.net如何将“类项目”中的 dll 嵌入到我在 vb.net 中的项目中
【发布时间】:2012-04-18 23:42:36
【问题描述】:

我有一个标准的“类库”项目,其中包含一组我用来导入几乎所有新项目的类。

我的工作方式是用一个空项目创建一个新的解决方案,这是我的主项目,然后我将提到的类库项目添加到解决方案中,这样我可以在解决方案资源管理器中看到这两个项目,甚至可以看到库代码或根据需要更新它。然后我在我的主项目中编写代码并编译。

这导致我在编译时有 2 个文件:文件 *.exestdlib.dll

在某些情况下,我将 lib 用于非常小的工具,我想以简单明了的方式重新分发这些工具,因此我想将从我的类库项目生成的 stdlib.dll 嵌入到我的 *.exe 文件中。

我很确定在我的 Microsoft Visual Basic 2010 Express 中必须有这样做的原因,但我不知道该怎么做。

有什么建议吗?

【问题讨论】:

标签: vb.net dll


【解决方案1】:

这是一个更“逐步”的Alex's procedure 版本,用于嵌入程序集。

  1. 将所需的程序集 (stdlib.dll) 添加到项目的资源中。
    转到 Project Properties 的 Resources 选项卡,然后选择 Add Resource > Add Existing File...
  2. 切换到应用程序标签并点击查看应用程序事件按钮。
  3. 将此代码添加到打开的 ApplicationEvents.vb 代码中。

    Private Sub AppStart(ByVal sender As Object, 
      ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ResolveAssemblies
    End Sub
    
    Private Function ResolveAssemblies(sender As Object, e As System.ResolveEventArgs) As Reflection.Assembly
        Dim desiredAssembly = New Reflection.AssemblyName(e.Name)
    
        If desiredAssembly.Name = "the name of your assembly" Then
            Return Reflection.Assembly.Load(My.Resources.STDLIB) 'replace with your assembly's resource name
        Else
            Return Nothing
        End If
    End Function 
    
  4. 现在编译您的项目,您会将依赖程序集作为单个文件合并到输出中。

请注意,有时您可能在输出文件夹中有依赖程序集。这是因为 VS 已预先配置为将所有依赖程序集复制到输出路径。您可以通过转到项目属性的 References 选项卡来覆盖它,然后将依赖程序集的 Copy Local 属性设置为 False。这将阻止程序集被复制到输出目录。

【讨论】:

  • 可能很愚蠢的问题:为什么在构建选项中选择嵌入式资源不为您执行此操作?换句话说:为什么需要任何代码?
  • @MauryMarkowitz:我能想到的唯一原因是...... 因为它是这样工作的。 考虑一下...... .NET 框架做了很多工作如果您将程序集作为 DLL 文件保留在 EXE 路径或其他标准路径中,则加载程序集。但是,如果您决定将其嵌入资源,则框架无法知道该资源是您要在运行时加载的程序集,还是您要以任何其他方式使用的东西。因此,它依赖于您告诉它所需的程序集在哪里,因此需要编写所有这些代码。
  • 给想知道的人的小提示:"the name of your assembly" 替换为程序集的确切名称,就像您输入代码一样。如果名称为Microsoft.WindowsAPICodePack,则字符串的值为"Microsoft.WindowsAPICodePack"
  • @AlexEssilfie 嗯。我希望微软在 VS 本身中实现一个更简单的解决方案,或者类似的东西。
【解决方案2】:

您可以通过选择“添加现有文件”将您的 Assembly(在您的情况下为 .dll)嵌入到您的项目中,然后将构建选项更改为“嵌入式资源”。

然后,您为 AppDomain.CurrentDomain.AssemblyResolve 事件添加一个 Handler,一旦您第一次访问代码中的库,该事件就会被触发。

该处理程序代码如下所示:(注意完全限定的程序集路径包括正确的命名空间。我会将其包装在一个函数中,该函数会在您的应用程序启动时被调用。

   AddHandler AppDomain.CurrentDomain.AssemblyResolve,
            Function(sender As Object, args As System.ResolveEventArgs) As System.Reflection.Assembly
                Dim ressourceName = "YourNamespace.YourSubNamespace." + New AssemblyName(args.Name).Name + ".dll"
                Using stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ressourceName)
                    Dim assemblyData(CInt(stream.Length)) As Byte
                    stream.Read(assemblyData, 0, assemblyData.Length)
                    Return Assembly.Load(assemblyData)
                End Using
            End Function

然后您无需任何其他文件即可部署您的工具。

【讨论】:

  • 它看起来比我想象的更“棘手”,但还是谢谢。我试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多