在VB.Net

时间:2017-07-21 21:52:59

标签: vb.net dll resources codedom

我在stackoverflow 上看到了很多答案,但是当我需要VB时,它们都没有帮助我完全满足我的需求,几乎所有这些都在C#中帮助我,所以我希望有人会帮我解决我的问题,这就是:

我使用exe在vb.net中编译了一个CodeDOM文件,并且我在其资源中添加了两个dll文件,并且工作正常,您甚至可以注意到它的大小添加资源后,exe的内容有所增加,但是当我运行exe文件时,My.Resources.Touchless文件就会出错,这会让我错误地说

  

“资源”不是“我的”的成员。

我需要的是从已编译的dll文件中读取这些exe文件,然后使用File.WriteAllBytes()...提取它们,如果我没有尝试提取文件从资源而不是我手动将它们复制到可执行路径,应用程序将完美地工作,所以问题只是尝试从资源调用dll文件。

以下是一些代码:

Public Shared Function Compile(ByVal Output As String, ByVal Source As String, ByVal Icon As String, ByVal resources As String) As Boolean
    Dim Parameters As New CompilerParameters()
    Dim cResults As CompilerResults = Nothing

    Dim Compiler As CodeDomProvider = CodeDomProvider.CreateProvider("VB")
    Parameters.GenerateExecutable = True
    Parameters.TreatWarningsAsErrors = False
    Parameters.OutputAssembly = Output
    Parameters.MainClass = "MyNamespace.MainWindow"
    Parameters.EmbeddedResources.Add(Path.GetTempPath & "TouchlessLib.dll")
    Parameters.EmbeddedResources.Add(Path.GetTempPath & "WebCamLib.dll")
    Parameters.ReferencedAssemblies.AddRange(New String() {"System.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "System.Management.dll", Path.GetTempPath & "TouchlessLib.dll"})
    Parameters.CompilerOptions = "/platform:x86 /target:winexe"
    If Not String.IsNullOrEmpty(Icon) Then
        File.Copy(Icon, "icon.ico")
        Parameters.CompilerOptions += " /win32icon:" & "icon.ico"
    End If
    cResults = Compiler.CompileAssemblyFromSource(Parameters, Source)
    If cResults.Errors.Count > 0 Then
        For Each compile_error As CompilerError In cResults.Errors
            Dim [error] As CompilerError = compile_error
            Console.Beep()
            MsgBox("Error: " & [error].ErrorText & vbCr & vbLf & [error].Line)
        Next
        Return False
    End If
    If Not (String.IsNullOrEmpty(Icon)) Then
        File.Delete("icon.ico")
    End If
    Return True
End Function

当我从编译好的exe文件中调用它们时,这样:

File.WriteAllBytes(Application.StartupPath & "\TouchlessLib.dll", My.Resources.TouchlessLib)
File.WriteAllBytes(Application.StartupPath & "\WebCamLib.dll", My.Resources.WebCamLib)

...我收到以下错误消息:

  

“资源”不是“我的”的成员。

2 个答案:

答案 0 :(得分:0)

My命名空间和任何相关功能是通过自动生成的代码创建的。由于你的代码现在是代码生成器而不是IDE,除非你的代码提供它,否则你不会有这些细节。

要提取嵌入式资源,您需要在使用CodeDOM编译的源代码中包含与以下内容类似的代码。

Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resouceNames As String() = asm.GetManifestResourceNames
For Each s As String In resouceNames
    Dim fi As New FileInfo(s)
    Using strm As Stream = asm.GetManifestResourceStream(s)
        Using fs As Stream = fi.Create()
            strm.CopyTo(fs)
        End Using
    End Using
Next

确保您还包括:

Imports System.Reflection
Imports System.IO

此代码检索正在执行的Assembly获取嵌入资源名称的数组。然后,它调用GetManifestResourceStream方法将命名资源作为流来获取。此流将复制到文件流中。

修改示例以满足您的需求。

请注意,我没有在此示例中包含任何错误检查/处理。处理IO的任何事情都应该有一些错误处理。

编辑: 根据下面的评论,似乎只有复制/粘贴类型的答案可以为OP做。

Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resourceName As String
Dim fi As FileInfo
resourceName = "TouchlessLib.dll"
fi = New FileInfo(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, resourceName))
Using strm As Stream = asm.GetManifestResourceStream(resourceName)
    Using fs As Stream = fi.Create()
        strm.CopyTo(fs)
    End Using
End Using

答案 1 :(得分:0)

尝试添加此类:

Imports System.Dynamic
Imports System.Reflection

Public Class DynamicResources
    Inherits DynamicObject
    Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As Object) As Boolean

        Dim asm As Assembly = Assembly.GetExecutingAssembly()
        Dim resouceNames As String() = asm.GetManifestResourceNames
        For Each s As String In resouceNames
            Dim name As String = IO.Path.GetFileNameWithoutExtension(s)
            Dim Manager As New Resources.ResourceManager(name, asm)
            Try
                Dim resource = Manager.GetObject(binder.Name)
                If Not resource Is Nothing Then
                    result = resource
                    Return True
                End If
            Catch ex As Exception

            End Try

        Next
        Return False
    End Function

End Class

你可以像这样使用它:

 Dim root as string=Application.StartupPath
 File.WriteAllBytes(Path.Combine(root, "TouchlessLib.dll"), DynamicResources.TouchlessLib)
 File.WriteAllBytes(Path.Combine(root, "WebCamLib.dll"), DynamicResources.WebCamLib)