Bottom Line Up Front
Is it possible to create a self-contained .NET 6 executable written in C# with a dependency on a C++ library?
Summary
I have created self-contained .NET 6 executable. When it runs, it crashes with a c0000005 (access violation) error.
The program starts without any problem. The crash appears to happen the moment that it needs to create an object that is supplied by a dependency that consists of C# wrappers of some C++ code.
I cannot find any documentation to verify my suspicions, but does .NET 6 not support creating self-contained executables with C++ dependencies? Or perhaps there is something special I need to do to make self-contained .exes work with C++-based dependencies?
By the way, the program runs just fine if I run the non–self-contained version of the .exe.
Some More Detail
The dependency that is giving me trouble is Pelco's VxSdk.NET. It only supports 64-bit assemblies/executables, so I am only building a 64-bit version of the .exe. Perhaps it's not a problem with C++-based libraries in general, just with this one in particular?
Code Sample
Here is a quick code sample to illustrate:
using VxSdkNet;
Console.WriteLine("Everything is fine here\n\n");
Console.Out.Flush();
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("If this is a self-contained .exe ...");
Console.WriteLine("... the line after the await crashes with a c0000005 (access violation)\n\n");
Console.Out.Flush();
await Task.Delay(TimeSpan.FromSeconds(1));
using var videoXpert = Connect();
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("If this is NOT a self-contained .exe ...");
Console.WriteLine("... we get here just fine");
static VXSystem Connect()
{
const string ip = ...;
const int port = ...;
const bool useSSL = ...;
const string licenseKey = ...;
const string username = ...;
const string password = ...;
var videoXpert = new VXSystem(ip, port, useSSL, licenseKey);
var result = videoXpert.Login(username, password);
return videoXpert;
}
Output
Here is the output from the self-contained .exe:
Everything is fine here
If this is a self-contained .exe ...
... the line after the await crashes with a c0000005 (access violation)
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
at <Module>._getFiberPtrId()
--------------------------------
at <Module>.<CrtImplementationDetails>.LanguageSupport._Initialize(<CrtImplementationDetails>.LanguageSupport*)
at <Module>.<CrtImplementationDetails>.LanguageSupport.Initialize(<CrtImplementationDetails>.LanguageSupport*)
at <Module>..cctor()
at Program.<<Main>$>g__Connect|0_0()
at Program+<<Main>$>d__0.MoveNext()
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Program+<<Main>$>d__0, Pelco.Sample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ExecutionContextCallback(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Program+<<Main>$>d__0, Pelco.Sample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext(System.Threading.Thread)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Program+<<Main>$>d__0, Pelco.Sample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Runtime.CompilerServices.IAsyncStateMachineBox, Boolean)
at System.Threading.Tasks.Task.RunContinuations(System.Object)
at System.Threading.Tasks.Task.FinishContinuations()
at System.Threading.Tasks.Task.TrySetResult()
at System.Threading.Tasks.Task+DelayPromise.CompleteTimedOut()
at System.Threading.Tasks.Task+DelayPromise.TimerCallback(System.Object)
at System.Threading.TimerQueueTimer.CallCallback(Boolean)
at System.Threading.TimerQueueTimer.Fire(Boolean)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback(Int32)
at System.Threading.UnmanagedThreadPoolWorkItem.System.Threading.IThreadPoolWorkItem.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()
at System.Threading.Thread.StartCallback()