I’m currently working on a simple debugger in VB.NET. I’m using mdbg assemblies to manage all the magic stuff happening between debugger and debuggee. I wrote following code in VB.NET just to handle process execution:
Imports System Imports System.Reflection Imports Microsoft.Samples.Debugging.MdbgEngine Public Class vdbg Public Shared Sub Main(ByVal args() As String) Dim debugger = New MDbgEngine() debugger.Options.CreateProcessWithNewConsole = True debugger.Options.StopOnModuleLoad = True Dim process = debugger.CreateProcess(args(0), "", DebugModeFlag.Debug, Nothing) While process.IsAlive process.Go().WaitOne() End While End Sub End Class
and compiled it:
vbc /r:mdbgeng.dll /vbruntime- /debug+ /debug:full /t:exe vdbg.vb
As you can see this code is rather straightforward. New console window is opened for a “debuggee” and after debuggee finishes its execution both processes should finish. What happened was a big surprise to me. The new console window was opened and then both processes hanged. I wrote an equivalent in C# and it worked as expected. So the only thing that rested was to analyze the generated IL for both versions:
ildasm /item=vdbg::Main /out=vdbg.il vdbg.exe
I highlighted the controversial line of IL below:
.class public auto ansi vdbg extends [mscorlib]System.Object { .method public static void Main(string[] args) cil managed { .entrypoint .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) // Code size 86 (0x56) .maxstack 5
It appears that the VB compiler by default puts STAThreadAttribute above the Main method unless you don’t choose a different COM threading model. The C# compiler is not so eager in changing your code :). Be aware of that fact when writing multithreaded application. In my application adding the highlighted line resolved all problems:
... Public Class vdbg <MTAThread()> _ Public Shared Sub Main(ByVal args() As String) ...