我在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)
...我收到以下错误消息:
“资源”不是“我的”的成员。
答案 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)