System.IO.FileNotFoundException: System.Runtime
DllExport version
1.8.1
Environment
None
Ask the .NET DllExport project
I used BasicExport.ExtDotNetCoreLibrary4 as an example and modified Alg's code as shown above. This code requires the NBitcoin package.
public static class Class1
{
static Class1()
{
static Assembly _Load(string path)
{
if (!File.Exists(path)) return null;
Console.WriteLine("Load: " + path);
return Assembly.LoadFrom(path);
}
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
_Load(Path.Combine
(
Path.GetDirectoryName(typeof(Class1).Assembly.Location),
e.Name?[..e.Name.IndexOf(',')] + ".dll"
));
}
[DllExport("testMethod", CallingConvention = CallingConvention.StdCall)]
public static string testMethod()
{
return "Yippee!";
}
[DllExport("GenerateAddress", CallingConvention = CallingConvention.StdCall)]
public static string GenerateAddress()
{
try
{
var key = new Key();
var address = key.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main);
return address.ToString();
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
}
}
Then I got an exception when testing.
testcode:
static void Main(string[] args)
{
Console.WriteLine(testMethod2());
Console.WriteLine(GenerateAddress2());
}
[DllImport("ExtDotNetCoreLibrary4.dll", CallingConvention = CallingConvention.StdCall,EntryPoint = "testMethod")]
public extern static string testMethod2();
[DllImport("ExtDotNetCoreLibrary4.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GenerateAddress")]
public extern static string GenerateAddress2();
The console output was:
Yippee!
Unhandled exception. System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception. at testconsole.Program.GenerateAddress2() at testconsole.Program.Main(String[] args) in System.IO.FileNotFoundException: System.Runtime, Version=6.0.0.0, Culture=neutral
I’ve looked at #219, #167,#132, but I didn’t find a solution. I might have missed something.
DllExport configuration
Installed: True; 1.8.1.36569+c2d3cd1; invoked: 1.8.1
Project type: Cs
Storage: ProjectFiles
Compiler.Platform: Auto
Compiler.imageBase: 0x8000000
Compiler.imageBaseStep: 0x400000
Compiler.ordinalsBase: 1
Compiler.rSysObj: True
Compiler.ourILAsm: True
Compiler.customILAsm:
Compiler.genExpLib: False
Compiler.peCheck: PeIl, Pe32orPlus
Compiler.patches: None
Compiler.refreshObj: False
PreProc.Type: None
PreProc.Cmd:
PostProc.Type: None
PostProc.ProcEnv: $(SolutionPath);$(MSBuildThisFileFullPath)
PostProc.Cmd:
AssemblyExternDirectives:
TypeRefDirectives: System.Runtime.CompilerServices.DefaultInterpolatedStringHandler,,False,False,True;
TypeRefOptions: DefaultInterpolatedStringHandler
RefPackages:
SignAssembly(Debug):
PlatformTarget(Debug): x86
TargetFramework(Debug):
TargetFrameworks(Debug): net9.0;net8.0;netstandard2.1
TargetFrameworkVersion(Debug):
TargetFrameworkIdentifier(Debug):
RootNamespace(Debug):
AssemblyName(Debug):
DebugType(Debug):
Optimize(Debug):
DebugSymbols(Debug):
SignAssembly(Release):
PlatformTarget(Release): x86
TargetFramework(Release):
TargetFrameworks(Release): net9.0;net8.0;netstandard2.1
TargetFrameworkVersion(Release):
TargetFrameworkIdentifier(Release):
RootNamespace(Release):
AssemblyName(Release):
DebugType(Release):
Optimize(Release):
DebugSymbols(Release):
Identifier: 65D268EE-0B35-40C6-9D7C-0232BA10B163
Instance: C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe
Project path: F:\Examples-master\DllExport\BasicExport\ExtDotNetCoreLibrary4\ExtDotNetCoreLibrary4.csproj
Action: Configure
MgrArgs:
MetaLib: tools\raw\lib\net20\DllExport.dll
MetaCor: tools\raw\lib\netstd\DllExport.dll
Proxy:
StoragePath: .net.dllexport.targets
ddNS: com.github._3F.DllExport
ddNS max buffer: 500
UseCecil: True
intermediateFiles: False
timeout: 30000
Options: None
RootPath: F:\Examples-master\DllExport\BasicExport\
PkgPath: F:\Examples-master\DllExport\BasicExport\packages\\DllExport.1.8.1\
SlnFile:
SlnDir: F:\Examples-master\DllExport\BasicExport\
DxpTarget: tools\net.r_eg.DllExport.targets
MsgLevel: Debug
LockIfError:
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
I think the solution to this problem should be configuring Ref and Types? I'll look into how to set these up.
I’m still quite confused about the settings related to Ref and Types, since the wiki doesn’t provide any explanation about them. The configuration details for these two only appear in a few issues and in NetCoreRefAsset.
Hello,
I think the solution to this problem should be configuring Ref and Types?
Yes, in general the issue is closer to #250 Considering your attached configuration, update it something like:
-
Temporary delete NBitcoin package from the project. (I think future versions will do this automatically)
-
In Wizard, click on [Ref] tab:
- click [+Memory +Unsafe] button,
- +
NBitcoin | 9.0.0 | netstandard2.0 - +
Newtonsoft.Json | 13.0.3 | netstandard2.0 - +
System.Buffers | 4.6.0 | netstandard2.0
-
Apply.
Now your GenerateAddress() should work. I've checked using net8.0
If not, try to activate "Refreshing intermediate module (obj)" in main window.
Note again,
If your task does not require netcore targeting, the easiest way to use without complex reconfiguration like above is to simply use any modern netfx-based TFM and the latest version of the language to access modern syntactic sugar etc.
@chuxiaaaa
I’m still quite confused about the settings related to Ref and Types, since the wiki doesn’t provide any explanation about them. The configuration details for these two only appear in a few issues and in NetCoreRefAsset.
#168
Thank you very much for your help!
Sorry to bother you again. If I change the line inside the GenerateAddress method from
var address = key.PubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main);
to
var address = key.PubKey.GetAddress(ScriptPubKeyType.TaprootBIP86, Network.Main);
I get the following error:
This feature of taproot is not supported in .NET Framework
Even though my build target is net8.0, it seems to be detected as .NET Framework. So I downgraded from .NET 8.0 to .NET 6.0, but still got the same error.
This is NBitcoin’s definition of the environment.
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.1' Or '$(TargetFramework)' == 'net6.0'">
<DefineConstants>$(DefineConstants);NETCORE;HAS_SPAN;NO_BC</DefineConstants>
<RemoveBC>true</RemoveBC>
</PropertyGroup>
Then I modified my testMethod to
return RuntimeInformation.FrameworkDescription;
and surprisingly got the result: .NET Framework 4.8.9261.0
So, what should I do to make it actually run under .NET 8.0 or .NET 6.0?
I tried to change all the Ref dlls to versions compatible with netstandard2.1 or .NET 6.0, but I couldn't find versions of System.Memory and System.Buffers that are available for .NET 6.0 or netstandard2.1.
So I removed their references, but this caused the program to fail to run properly.
@chuxiaaaa
This feature of taproot is not supported in .NET Framework
This is a limitation from the NBitcoin itself, you can find it in the NBitcoin assembly for netstandard2.0
Then you need other way, for example, NBitcoin's assembly net6.0; merge it using [Pre-Processing] tab; then with .typref ([Types]) set up a working binding in the used NBitcoin hierarchy.
This is NBitcoin’s definition of the environment.
This is it, if their HAS_SPAN controls implementation at compile time for Span between TFMs, then rebinding is needed at least for Span and ReadOnlySpan respectively. For example:
[Types]
- +System.Span` | v | at | System.Memory
- +System.ReadOnlySpan` | v | at | System.Memory
- +System.ReadOnlyMemory` | v | at | System.Memory
- +System.Memory` | v | at | System.Memory
- +System.MemoryExtensions | _ | at | System.Memory
- ...
[Ref]
- [+Memory +Unsafe] button
that was tested exactly on ReadOnlySpan and Memory here for net6 up to net9.
Same with other types used in NBitcoin. Yes, I mentioned these complexities in https://github.com/3F/DllExport/issues/219#issuecomment-2629527504 For DllExport v1.x only manual binding with .typref ([Types] tab), and/or a mix of modules, or netfx/netstandard2.0 + LangVersion=latest
If you need it urgently or you don't want to check every used type to get a working configuration (until v2.x), then I recommend alternatives like DNNE, or UnmanagedCallersOnly, or even your own clr host etc.
This feature of taproot is not supported in .NET Framework
This is a limitation from the NBitcoin itself, you can find it in the NBitcoin assembly for netstandard2.0
Then you need other way, for example, NBitcoin's assembly net6.0; merge it using [Pre-Processing] tab; then with .typref ([Types]) set up a working binding in the used NBitcoin hierarchy.
This is NBitcoin’s definition of the environment.
This is it, if their HAS_SPAN controls implementation at compile time for Span between TFMs, then rebinding is needed at least for Span and ReadOnlySpan respectively. For example:
[Types]
- +System.Span` | v | at | System.Memory
- +System.ReadOnlySpan` | v | at | System.Memory
- +System.ReadOnlyMemory` | v | at | System.Memory
- +System.Memory` | v | at | System.Memory
- +System.MemoryExtensions | _ | at | System.Memory
- ...
[Ref]
- [+Memory +Unsafe] button
that was tested exactly on ReadOnlySpan and Memory here for net6 up to net9.
Same with other types used in NBitcoin. Yes, I mentioned these complexities in #219 (comment) For DllExport v1.x only manual binding with .typref ([Types] tab), and/or a mix of modules, or netfx/netstandard2.0 + LangVersion=latest
If you need it urgently or you don't want to check every used type to get a working configuration (until v2.x), then I recommend alternatives like DNNE, or UnmanagedCallersOnly, or even your own clr host etc.
Thank you for your reply. From what I see, NBitcoin determines the HAS_SPAN condition based on the TargetFramework.
In my DLL, the value I get from RuntimeInformation.FrameworkDescription is .NET Framework 4.8.9261.0.
I feel like this is what’s causing the issue!
I’m using translation software, so please forgive me if there are any inaccuracies in my wording!
This feature of taproot is not supported in .NET Framework
This is a limitation from the NBitcoin itself, you can find it in the NBitcoin assembly for netstandard2.0
Then you need other way, for example, NBitcoin's assembly net6.0; merge it using [Pre-Processing] tab; then with .typref ([Types]) set up a working binding in the used NBitcoin hierarchy.
This is NBitcoin’s definition of the environment.
This is it, if their HAS_SPAN controls implementation at compile time for Span between TFMs, then rebinding is needed at least for Span and ReadOnlySpan respectively. For example:
[Types]
- +System.Span` | v | at | System.Memory
- +System.ReadOnlySpan` | v | at | System.Memory
- +System.ReadOnlyMemory` | v | at | System.Memory
- +System.Memory` | v | at | System.Memory
- +System.MemoryExtensions | _ | at | System.Memory
- ...
[Ref]
- [+Memory +Unsafe] button
that was tested exactly on ReadOnlySpan and Memory here for net6 up to net9.
Same with other types used in NBitcoin. Yes, I mentioned these complexities in #219 (comment) For DllExport v1.x only manual binding with .typref ([Types] tab), and/or a mix of modules, or netfx/netstandard2.0 + LangVersion=latest
If you need it urgently or you don't want to check every used type to get a working configuration (until v2.x), then I recommend alternatives like DNNE, or UnmanagedCallersOnly, or even your own clr host etc.
DllExport configuration
Installed: True; 1.8.1.36569+c2d3cd1; invoked: 1.8.1
Project type: Cs
Storage: ProjectFiles
Compiler.Platform: x86
Compiler.imageBase:
Compiler.imageBaseStep:
Compiler.ordinalsBase: 1
Compiler.rSysObj: True
Compiler.ourILAsm: True
Compiler.customILAsm:
Compiler.genExpLib: False
Compiler.peCheck: PeIl, Pe32orPlus
Compiler.patches: None
Compiler.refreshObj: False
PreProc.Type: ILMerge, DebugInfo, IgnoreErr, Lib
PreProc.Cmd:
PostProc.Type: None
PostProc.ProcEnv: $(SolutionPath);$(MSBuildThisFileFullPath)
PostProc.Cmd:
AssemblyExternDirectives:
TypeRefDirectives: System.Span`,System.Memory,True,False,False;System.ReadOnlySpan`,System.Memory,True,False,False;System.ReadOnlyMemory`,System.Memory,True,False,False;System.Memory`,System.Memory,True,False,False;System.MemoryExtensions,System.Memory,False,False,False;
TypeRefOptions: None
RefPackages: System.Runtime.CompilerServices.Unsafe,6.1.0,netstandard2.0;NBitcoin,9.0.0,net6.0;Newtonsoft.Json,13.0.3,netstandard2.0;System.Buffers,4.6.0,netstandard2.0;System.Memory,4.6.0,netstandard2.0;
SignAssembly(Debug):
PlatformTarget(Debug): x86
TargetFramework(Debug): net8.0
TargetFrameworks(Debug):
TargetFrameworkVersion(Debug):
TargetFrameworkIdentifier(Debug):
RootNamespace(Debug):
AssemblyName(Debug):
DebugType(Debug):
Optimize(Debug):
DebugSymbols(Debug):
SignAssembly(Release):
PlatformTarget(Release): x86
TargetFramework(Release): net8.0
TargetFrameworks(Release):
TargetFrameworkVersion(Release):
TargetFrameworkIdentifier(Release):
RootNamespace(Release):
AssemblyName(Release):
DebugType(Release):
Optimize(Release):
DebugSymbols(Release):
Identifier: 6D5DBF95-CFD1-4AB7-B550-03E5D749BE1C
Instance: C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe
Project path: F:\core (1)\core\core\core.csproj
Action: Configure
MgrArgs:
MetaLib: tools\raw\lib\net20\DllExport.dll
MetaCor: tools\raw\lib\netstd\DllExport.dll
Proxy:
StoragePath: .net.dllexport.targets
ddNS: core
ddNS max buffer: 500
UseCecil: True
intermediateFiles: False
timeout: 30000
Options: None
RootPath: F:\core (1)\core\
PkgPath: F:\core (1)\core\packages\\DllExport.1.8.1\
SlnFile:
SlnDir: F:\core (1)\core\
DxpTarget: tools\net.r_eg.DllExport.targets
MsgLevel: Debug
LockIfError:
I used the example you provided, and now I’m getting the following exception:
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. Method not found. (Exception from HRESULT: 0x80131513) ---> System.MissingMethodException: Method not found: 'System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)'.
Did I miss something?
In my DLL, the value I get from RuntimeInformation.FrameworkDescription is .NET Framework 4.8.9261.0
RuntimeInformation may contain different information due to actual mixes and rebasing feature. But I meant exactly this: https://github.com/MetacoSA/NBitcoin/blob/80fd7d9c9411872d8c7ebc4fc70412ba2dd90cf6/NBitcoin/PubKey.cs#L309-L313
I’m using translation software, so please forgive me if there are any inaccuracies in my wording!
no problem at all. I'm also not a native speaker either to spot typos or incorrect sentences for both of us :)
Did I miss something?
Remove everyting from [Ref]; NBitcoin should be merged at [Pre-Processing], use ILRepack. According to Span, you need add [+Memory +Unsafe] in [Ref] and map [Types] as above. Other types must be reviewed individually, unfortunately, as I mentioned earlier.
By the way! You're trying to use .NET (testconsole in your example) together with .NET (NBitcoin) via P/Invoke (DllExport). Is this just for testing? I mean, are you sure DllExport is needed in your case? Because you can reference it directly by using Reference or ProjectReference or PackageReference in project file. Moreover, modern dotnet supports AssemblyLoadContext to be able to unload all assemblies loaded in this context at runtime and so on.
just to be sure
By the way! You're trying to use .NET (testconsole in your example) together with .NET (NBitcoin) via P/Invoke (DllExport). Is this just for testing? I mean, are you sure DllExport is needed in your case? Because you can reference it directly by using Reference or ProjectReference or PackageReference in project file. Moreover, modern dotnet supports AssemblyLoadContext to be able to unload all assemblies loaded in this context at runtime and so on.
Yes, using testconsole is just for testing. Thanks for your help, I’ll try again!
I tested many cases, but none of them worked. When I use ILRepack, if the merged NBitcoin is targeting netstandard2.0, it throws:
Unhandled Exception: System.TypeInitializationException: The type initializer for 'NBitcoin.Key' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NBitcoin.uint256' threw an exception. ---> System.TypeInitializationException: The type initializer for 'NBitcoin.DataEncoders.HexEncoder' threw an exception. ---> System.TypeLoadException: Could not load type 'System.Linq.Enumerable' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
at NBitcoin.DataEncoders.HexEncoder..cctor()
--- End of inner exception stack trace ---
at NBitcoin.DataEncoders.HexEncoder..ctor()
at NBitcoin.uint256..cctor()
--- End of inner exception stack trace ---
at NBitcoin.uint256.Parse(String hex)
at NBitcoin.Key..cctor()
--- End of inner exception stack trace ---
at NBitcoin.Key.Finalize()
If it’s .NET 6.0, then I get a different exception:
Error: The type initializer for 'NBitcoin.Key' threw an exception.
Unhandled Exception: System.TypeInitializationException: The type initializer for 'NBitcoin.Key' threw an exception. ---> System.MissingMethodException: Method not found: 'Void System.Array.Reverse(!!0[])'.
at NBitcoin.uint256..ctor(String str)
at NBitcoin.uint256.Parse(String hex)
at NBitcoin.Key..cctor()
--- End of inner exception stack trace ---
at NBitcoin.Key.Finalize()
Here’s a screenshot of my Pre-processing page settings:
I also tried adding other NuGet packages into Pre-processing, such as Newtonsoft.Json, System.Buffers, System.Memory, etc., but it didn’t change the result — the error remains the same.
DllExport configuration
Installed: True; 1.8.1.36569+c2d3cd1; invoked: 1.8.1
Project type: Cs
Storage: ProjectFiles
Compiler.Platform: x86
Compiler.imageBase:
Compiler.imageBaseStep:
Compiler.ordinalsBase: 1
Compiler.rSysObj: True
Compiler.ourILAsm: True
Compiler.customILAsm:
Compiler.genExpLib: False
Compiler.peCheck: PeIl, Pe32orPlus
Compiler.patches: None
Compiler.refreshObj: False
PreProc.Type: DebugInfo, IgnoreErr, ILRepack, MergeRefPkg, Lib
PreProc.Cmd: C:\Users\91021\.nuget\packages\nbitcoin\9.0.0\lib\net6.0\NBitcoin.dll
PostProc.Type: None
PostProc.ProcEnv: $(SolutionPath);$(MSBuildThisFileFullPath)
PostProc.Cmd:
AssemblyExternDirectives:
TypeRefDirectives: System.Span`,System.Memory,True,False,False;System.ReadOnlySpan`,System.Memory,True,False,False;System.ReadOnlyMemory`,System.Memory,True,False,False;System.Memory`,System.Memory,True,False,False;System.MemoryExtensions,System.Memory,False,False,False;
TypeRefOptions: None
RefPackages: System.Memory,4.6.0,netstandard2.0;System.Runtime.CompilerServices.Unsafe,6.1.0,netstandard2.0;
SignAssembly(Debug):
PlatformTarget(Debug): x86
TargetFramework(Debug): net8.0
TargetFrameworks(Debug):
TargetFrameworkVersion(Debug):
TargetFrameworkIdentifier(Debug):
RootNamespace(Debug):
AssemblyName(Debug):
DebugType(Debug):
Optimize(Debug):
DebugSymbols(Debug):
SignAssembly(Release):
PlatformTarget(Release): x86
TargetFramework(Release): net8.0
TargetFrameworks(Release):
TargetFrameworkVersion(Release):
TargetFrameworkIdentifier(Release):
RootNamespace(Release):
AssemblyName(Release):
DebugType(Release):
Optimize(Release):
DebugSymbols(Release):
Identifier: 6D5DBF95-CFD1-4AB7-B550-03E5D749BE1C
Instance: C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\amd64\MSBuild.exe
Project path: F:\core (1)\core\core\core.csproj
Action: Configure
MgrArgs:
MetaLib: tools\raw\lib\net20\DllExport.dll
MetaCor: tools\raw\lib\netstd\DllExport.dll
Proxy:
StoragePath: .net.dllexport.targets
ddNS: core
ddNS max buffer: 500
UseCecil: True
intermediateFiles: False
timeout: 30000
Options: None
RootPath: F:\core (1)\core\
PkgPath: F:\core (1)\core\packages\\DllExport.1.8.1\
SlnFile:
SlnDir: F:\core (1)\core\
DxpTarget: tools\net.r_eg.DllExport.targets
MsgLevel: Debug
LockIfError:
Maybe I still haven’t configured something correctly?
@chuxiaaaa
Maybe I still haven’t configured something correctly?
Your list in [Types] is not completed as was noted:
Other types must be reviewed individually ...
Above is my example from real tests for Span using net6-net9 but this is not complete list for NBitcoin. I haven't inspected it in detail, otherwise I would send the full configuration.
I'm not sure when I'll switch back to the DllExport project again (in fact I have more urgent tasks for the upcoming VS2026 like https://github.com/3F/vsSolutionBuildEvent/issues/83 etc), but [Types]/[Pre-Proc]/[Ref] obviously requires a time for each project to be right configured.
As I mentioned,
If you need it urgently or you don't want to check every used type to get a working configuration (until v2.x), then I recommend alternatives like DNNE, or UnmanagedCallersOnly, or even your own clr host etc.
I apologize for the inconvenience.
@3F I understand. I’ll do some research on my own. Thanks again for your help, and I wish you success in your work.