Dynamically running an Assembly in a separate process (with your tail between your legs)
I'm currently building an application updater tool which needs to receive an arbitrary list of assemblies, calculate which one is the bootstrapper and exectute it. I had it in my head that I would need to create an AppDomain and then use reflection to load and Invoke the entry point of the bootstrap application - so I spent until the wee hours trying to get all kinds of Reflective incantations to work. I could get Assembly.Load to work quite simply:
Dim target As System.Reflection.Assembly = [Assembly].LoadFrom(mStartupFile) Dim entryPoint As MethodInfo = target.EntryPoint If Not entryPoint Is Nothing Then entryPoint.Invoke(Nothing, Nothing) End If
However, because that will load assemblies into the same AppDomain I wanted to steer away from that and instead create standalone AppDomain's into which I could load the assemblies. It didn't seem to matter how hard I tried I just could not get it to work; this was about as close as I got:
Dim setup As New AppDomainSetup setup.ApplicationBase = mBaseDirectory setup.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory setup.ApplicationName = "tmpDomain" Dim domain As AppDomain = AppDomain.CreateDomain("myBootstrapper", Nothing, setup) Dim target As System.Reflection.Assembly = domain.Load(GetBytes(mStartupFile)) Dim entryPoint As MethodInfo = target.EntryPoint If Not entryPoint Is Nothing Then entryPoint.Invoke(Nothing, Nothing) End If
Anyways, at about 2:00am I trudged off to bed - defeated! I then tossed and turned for the next half-an-hour or so wondering why this was so hard to do. By the time I awoke I had a new plan which was much simpler than using all of that tricky reflection code... use the Process class! Here is my new working code which loads my bootstrapper exe and receives StdOut messages from it:
Dim myProcess As New Process myProcess.StartInfo.FileName = mStartupFile myProcess.StartInfo.UseShellExecute = False myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden myProcess.StartInfo.RedirectStandardOutput = True myProcess.Start() Me.txtWork.Text = myProcess.StandardOutput.ReadToEnd() myProcess.WaitForExit()
So now I'm not really sure why I thought that I needed that reflection stuff at all :-)
Recommended Reading:
How can I run another application or batch file from my Visual Basic .NET code?
Plug-in Framework (Part1): Marking Types for Consumption