Embedding a dll in a VB.Net Project

Hi Experts
I need to embed a dll in a VB.Net Project

So Far I have add the dll in Properties/References and then made local copy false
I have added the dll to the project as an existing file - right click / add / existing file
I have made this option an Embedded Resource / Do Not Copy Local

I have entered the following code in ApplicationEvents.VB from the internet

I have tried many different references from the internet but still get the error file not found
Any help would be appreciated.  Many Thanks

Imports System.IO
Imports Microsoft.VisualBasic.ApplicationServices

Namespace My

Partial Friend Class MyApplication

Private Sub Form1_Startup(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf LoadDLLFromStream
 End Sub

Private Function LoadDLLFromStream(ByVal sender As Object, ByVal args As System.ResolveEventArgs) As System.Reflection.Assembly

            Dim resourceName As String = "ProjectName" & New AssemblyName(args.Name).Name & ".dll"
            Dim resources() As String = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames

            Using stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
                Dim assemblyData(CInt(stream.Length - 1)) As Byte
                stream.Read(assemblyData, 0, assemblyData.Length)
                Return System.Reflection.Assembly.Load(assemblyData)
            End Using
End Function

End Class
End Namespace

Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

This is how I do it in C# - http:/Q_28693131.html

That being said, here are the instructions recreated for VB.NET.

1. Create a new project.

2. Create a folder called Resources (this is where our embedded resources will go).


3. Add the resources you want. Be sure to include them in the project, set their 'Build Action' property to Embedded Resource and set their 'Copy to Output Directory' property to Do not copy.


4. Add the reference(s) and set the 'Copy Local' property for each one to False.


5. Add the EmbeddedAssembly class to your project.

Imports System.IO
Imports System.Reflection
Imports System.Security.Cryptography

''' <summary>Class EmbeddedAssembly.</summary>
Public Class EmbeddedAssembly
	''' <summary>The assembly dictionary</summary>
	Shared fAssemblyDictionary As Dictionary(Of String, Assembly) = Nothing

	''' <summary>Load Assembly, DLL from Embedded Resources into memory.</summary>
	''' <param name="ResourceString">A <see cref="String"/> value that represents the embedded resource string.</param>
	''' <param name="FileName">A <see cref="String"/> value that represents the file name of the resource.</param>
	''' <example>EmbeddedAssembly.Load("WindowsFormsApplication1.SomeTools.dll", "SomeTools.dll")</example>
	Public Shared Sub Load(ResourceString As String, FileName As String)
		Console.WriteLine("Attempting to load the following embedded resource {0} ({1}).", FileName, ResourceString)
		If fAssemblyDictionary Is Nothing Then
			fAssemblyDictionary = New Dictionary(Of String, Assembly)(StringComparer.OrdinalIgnoreCase)
		End If

		Dim fBuffer As Byte() = Nothing
		Dim fAssembly As Assembly = Nothing
		Dim fCurrentAssembly = Assembly.GetExecutingAssembly()

		For Each name As String In fCurrentAssembly.GetManifestResourceNames()
			Console.WriteLine("Embedded resource {0} of '{1}'.", name, fCurrentAssembly.GetName())

		Using fStream = fCurrentAssembly.GetManifestResourceStream(ResourceString)
			' Either the file does not exist or it is not mark as an embedded resource.
			If fStream Is Nothing Then
				Console.WriteLine("WARNING!!!  Embedded resource {0} ({1}) was not found in '{2}'.", FileName, ResourceString, fCurrentAssembly.GetName())
			End If

			Console.WriteLine("Found embedded resource {0} ({1}) in '{2}'.", FileName, ResourceString, fCurrentAssembly.GetName())
			' Get byte[] from the file from embedded resource
			fBuffer = New Byte(CInt(fStream.Length) - 1) {}
			fStream.Read(fBuffer, 0, CInt(fStream.Length))
				Console.WriteLine("Loading embedded resource {0} ({1}) from '{2}'.", FileName, ResourceString, fCurrentAssembly.GetName())
				fAssembly = Assembly.Load(fBuffer)
				' Add the assembly/dll into dictionary
				Console.WriteLine("Adding embedded resource {0} ({1}) to local dictionary '{2}'.", FileName, ResourceString, fCurrentAssembly.GetName())
				fAssemblyDictionary.Add(fAssembly.FullName, fAssembly)
				' Purposely do nothing.  An unmanaged dll or assembly cannot be loaded directly from byte[].  Let the process fall through for next part
				' Eat the exception 

			End Try
		End Using

		Dim fIsFileOk As Boolean = False
		Dim fTempFile As String = ""

		Using sha1 = New SHA1CryptoServiceProvider()
			' Get the hash value from embedded DLL/assembly
			Dim fHash As String = BitConverter.ToString(sha1.ComputeHash(fBuffer)).Replace("-", String.Empty)

			' Define the temporary storage location of the DLL/assembly
			fTempFile = String.Format("{0}{1}", Path.GetTempPath(), FileName)

			' Determines whether the DLL/assembly is existed or not
			If File.Exists(fTempFile) Then
				' Get the hash value of the existed file
				Dim fTempBuffer As Byte() = File.ReadAllBytes(fTempFile)
				Dim fTempHash As String = BitConverter.ToString(sha1.ComputeHash(fTempBuffer)).Replace("-", String.Empty)
				' Compare the existed DLL/assembly with the Embedded DLL/assembly
				fIsFileOk = If(fHash = fTempHash, True, False)
				fIsFileOk = False
			End If
		End Using

			' Create the file on disk
			If Not fIsFileOk Then
				File.WriteAllBytes(fTempFile, fBuffer)
			End If

			' Load it into memory
			Console.WriteLine("Loading resource {0} from the disk.", fTempFile)
			fAssembly = Assembly.LoadFile(fTempFile)

			' Add the loaded DLL/assembly into dictionary
			Console.WriteLine("Adding resource {0} to local dictionary '{1}'.", fTempFile, fCurrentAssembly.GetName())
			fAssemblyDictionary.Add(fAssembly.FullName, fAssembly)
		Catch ex As Exception
			Console.WriteLine("Error loading resource {0} ({1}).", FileName, ResourceString)
		End Try
	End Sub

	''' <summary>Retrieve specific loaded DLL/Assembly from memory</summary>
	''' <param name="AssemblyFullName">A <see cref="String"/> value that represents the name of the assembly to load.</param>
	''' <returns>An <see cref="Assembly"/> object that represents the assembly if it is located in memory, otherwise returns null.</returns>
	Public Shared Function [Get](AssemblyFullName As String) As Assembly
		Console.WriteLine("Attempting to retrieve resource '{0}' from local dictionary.", AssemblyFullName)
		If fAssemblyDictionary Is Nothing OrElse fAssemblyDictionary.Count = 0 Then
			Console.WriteLine("WARNING!!!  There are no resources loaded in the local dictionary.")
			Return Nothing
		End If

		If fAssemblyDictionary.ContainsKey(AssemblyFullName) Then
			Console.WriteLine("Found '{0}' in the local dictionary.", AssemblyFullName)
			Return fAssemblyDictionary(AssemblyFullName)
		End If
		Return Nothing
		' Don't throw Exception if the dictionary does not contain the requested assembly.
		' This is because the event of AssemblyResolve will be raised for every
		' Embedded Resources (such as pictures) of the projects.
		' Those resources wil not be loaded by this class and will not exist in dictionary.
	End Function
End Class

Open in new window

6. Before you require the resource you must load it somewhere. I usually do this before Main is called. For VB.NET I modified the Application.Designer.vb file (this is frowned upon by the designer and will get overwritten if you change any of your application settings).

Application.Designer.vb -
' <auto-generated>
'     This code was generated by a tool.
'     Runtime Version:4.0.30319.42000
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>

Option Strict On
Option Explicit On

Namespace My
    'NOTE: This file is auto-generated; do not modify it directly.  To make changes,
    ' or if you encounter build errors in this file, go to the Project Designer
    ' (go to Project Properties or double-click the My Project node in
    ' Solution Explorer), and make changes on the Application tab.
    Partial Friend Class MyApplication
        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _
        Public Sub New()
            Me.IsSingleInstance = false
            Me.EnableVisualStyles = true
            Me.SaveMySettingsOnExit = true
            Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses
			Console.WriteLine("Loading Embedded Resources into memory")
			EmbeddedAssembly.Load("EE_Q28704024.CommandLine.dll", "CommandLine.dll")
			AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnAssemblyResolve
		End Sub
        <Global.System.Diagnostics.DebuggerStepThroughAttribute()>  _
        Protected Overrides Sub OnCreateMainForm()
            Me.MainForm = Global.EE_Q28704024.Form1
        End Sub

		<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
		Protected Function OnAssemblyResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As System.Reflection.Assembly
			Dim result As System.Reflection.Assembly = Nothing
				result = EmbeddedAssembly.Get(e.Name)
			Catch ex As Exception
				Console.WriteLine("Cannot resolve assembly for - {0}", e.Name)
				result = Nothing
			End Try
			Return result
		End Function
	End Class
End Namespace

Open in new window

7. Then in my case I modified the Application Event for the Startup of the project.

Capture.JPGApplicationEvents.vb -
Namespace My

	' The following events are available for MyApplication:
	' Startup: Raised when the application starts, before the startup form is created.
	' Shutdown: Raised after all application forms are closed.  This event is not raised if the application terminates abnormally.
	' UnhandledException: Raised if the application encounters an unhandled exception.
	' StartupNextInstance: Raised when launching a single-instance application and the application is already active. 
	' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
	Partial Friend Class MyApplication
		Private Sub OnStartup(sender As Object, e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) Handles Me.Startup
			Dim [options] As New Options
			If CommandLine.Parser.Default.ParseArguments(e.CommandLine.ToArray(), [options]) Then
				Console.WriteLine("Processing {0}.", If(e.CommandLine.Count <> 1, String.Format("{0} command line arguments", e.CommandLine.Count), String.Format("{0} command line argument", e.CommandLine.Count)))

				If options.World Then Form1.TextBox1.Text = "Hello World!!!"

				If Not String.IsNullOrEmpty(options.Individual) Then Form1.TextBox1.Text = If(Not String.IsNullOrEmpty(Form1.TextBox1.Text), String.Format("{0}{1}Hello {2}!!!", Form1.TextBox1.Text, Environment.NewLine, options.Individual), String.Format("Hello {0}!!!", options.Individual))
				Console.WriteLine("There were no command line options to process.")
			End If
		End Sub
	End Class
End Namespace

Open in new window

A test project has been uploaded here - https://filedb.experts-exchange.com/incoming/ee-stuff/8428-EE_Q28704024.zip


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
By the way, a test run of my project produces the following results -Capture.JPG
As you can see, the CommandLine.dll is not in the output directory.

ILDASM also shows that it is, in fact, embedded in the assembly -Capture.JPG-saige-
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.