在VB.Net中使用CodeDOM从资源添加后提取'dll'文件

在VB.Net中使用CodeDOM从资源添加后提取'dll'文件,vb.net,dll,resources,codedom,Vb.net,Dll,Resources,Codedom,我在stackoverflow上看到了很多答案,但是没有一个答案能帮助我准确地完成我需要的东西,当我需要VB时,几乎所有答案都是C语言的,所以我希望有人能帮我解决我的问题,这就是: 我在vb.net中使用CodeDOM编译了一个exe文件,并在其资源中添加了两个dll文件,效果很好,您甚至可以注意到exe的大小在添加资源后有所增加,但是,当我像那样运行exe文件My.Resources.Touchless时,会出现这样的错误 “资源”不是“我的”的成员 我需要的是从编译后的exe文件中读取这些d

我在
stackoverflow
上看到了很多答案,但是没有一个答案能帮助我准确地完成我需要的东西,当我需要VB时,几乎所有答案都是C语言的,所以我希望有人能帮我解决我的问题,这就是:

我在vb.net中使用
CodeDOM
编译了一个
exe
文件,并在其资源中添加了两个
dll
文件,效果很好,您甚至可以注意到
exe
的大小在添加资源后有所增加,但是,当我像那样运行
exe
文件
My.Resources.Touchless
时,会出现这样的错误

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

我需要的是从编译后的
exe
文件中读取这些
dll
文件,然后使用
file.writealBytes()…
将它们提取出来。如果我没有尝试从资源中提取文件,而不是手动将它们复制到可执行路径,那么应用程序将工作得很好,因此,问题只是试图从资源中调用
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)
。。。我收到以下错误消息:

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


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
此代码检索正在执行的
程序集
并获取一个嵌入式资源名称数组。然后,它调用方法以获取作为流的命名资源。此流被复制到文件流

修改示例以满足您的需要

请注意,我在这个示例中没有包含任何错误检查/处理。任何处理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
尝试添加此类:

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)

我不知道这是否有效,但请尝试:
MyApplication.Resources
。不,不幸的是它没有。VisualIncent我可以将这个
CodeDOM
编译的
exe
文件添加到用VB IDE编译的普通
exe
文件的资源中,再加上
dll
文件,并在同一位置提取它们,它会起作用,但我认为这不是很顺利!请尝试
MyNamespace.My.Resources
,并向您展示如何准确访问文件的代码。非常感谢您的时间和帮助,我想我会坚持我的老方法…不幸的是,当我试图编译它时,它给了我一个错误消息:添加对
System.Core.dll
的引用,我们去掉了那个引用,但现在我们得到了一个新的错误消息:键入:
DynamicResources
不是
DynamiceResources
对,但现在它说
“touclesslib”不是“DynamicResources”的成员
,这是在尝试使用
File.writealBytes(Path.Combine(root,“touchleslib.dll”)、DynamicResources.touchleslib提取它们时发生的。
。谢谢,这没有任何编译问题,但如何提取文件。我使用了:File.Create(Application.ExecutablePath&“touchleslib.dll”,fs.ReadByte())…,但这不起作用,你能帮我吗?@MousaAlfhaily,请看我的编辑。另外,您认为
Application.ExecutablePath&“touchleslib.dll”
会产生什么效果?谢谢
Application.ExecutablePath&“\touchleslib.dll”
将为启动
exe
文件的路径生成一个字符串
+
要提取到该路径的资源的名称。