error powershell c# visual studio - c#

I have got a simple class libary project in visual studio:
using System;
using System.Linq;
using System.Management.Automation;
namespace EdoX_auslesen_xml
{
[Cmdlet(VerbsCommon.Get, "DemoNames")]
public class Get_DemoNames : Cmdlet
{
[Parameter(Mandatory = false)]
public string Prefix;
protected override void ProcessRecord()
{
var names = new string[] { "Chris", "Charlie", "Anne" };
if (string.IsNullOrEmpty(this.Prefix))
{
this.WriteObject(names, true);
}
else
{
var prefixed_names = names.Select(n => this.Prefix + n);
this.WriteObject(prefixed_names, true);
}
}
}
}
When I open PowerShell an try to "Get-DemoNames" an error occurs:
in English:
Get-DemoNames: the file or assebly "System.Runtime, Version=4.2.0.0. Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" or a dependency of it was not found. The system cannot find the given file.
In line:1 sign:1
+ Get- DemoNames...

I think you need to add a reference to System.Runtime.
View this StackOverflow question.

Related

Custom AssemblyLoadContext failing to load Microsoft.AspNetCore.Components

Edit: I have uploaded the source code for the issue to GitHub if you would like to download: https://github.com/bryanenroute/assemblyloadcontext-issue
I have a .NET Core 3.0 console application that references a .NET Standard 2.0 class library with a single interface (IModule). I also have a ASP.NET Core 3.0 application that references the same .NET Standard 2.0 class library and implements the interface (Module : IModule).
I am trying to load the ASP.NET Core assembly from the .NET Core console application using a custom AssemblyLoadContext and a common class library interface (IModule)... a simple plugin system.
Unfortunately, the ASP.NET Core module/plugin fails in the ALC override function for Load(AssemblyName) with the following exception:
Could not load file or assembly 'Microsoft.AspNetCore.Components, Version=3.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
When I try with a different project type (e.g. .NET Core Console Application or .NET Standard 2.0 Class Library), the module/plugin loads as intended.
Here's the Console app code:
using NetStandardCommon;
using System;
using System.IO;
namespace NetCoreConsoleApp
{
class Program
{
static void Main(string[] args)
{
LoadNetCoreModule();
LoadAspNetCoreModule();
}
static void LoadNetCoreModule()
{
//Works!
FileInfo asm = new FileInfo(#"..\..\..\..\NetCoreModule\bin\debug\netcoreapp3.0\NetCoreModule.dll");
var moduleDirectory = asm.DirectoryName;
ModuleAssemblyLoadContext context = new ModuleAssemblyLoadContext(asm.Name, moduleDirectory, typeof(IModule));
context.Scan();
foreach (var module in context.GetImplementations<IModule>())
{
module.Start();
}
}
static void LoadAspNetCoreModule()
{
//Fails!
FileInfo asm = new FileInfo(#"..\..\..\..\AspNetCoreApp\bin\debug\netcoreapp3.0\AspNetCoreApp.dll");
var moduleDirectory = asm.DirectoryName;
ModuleAssemblyLoadContext context = new ModuleAssemblyLoadContext(asm.Name, moduleDirectory, typeof(IModule));
context.Scan();
foreach (var module in context.GetImplementations<IModule>())
{
module.Start();
}
}
}
}
Here's the ModuleAssemblyLoadContext code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using System.Linq;
namespace NetCoreConsoleApp
{
public class ModuleAssemblyLoadContext : AssemblyLoadContext
{
private List<Assembly> _loaded;
private Dictionary<string, Assembly> _shared;
private string _path;
private AssemblyDependencyResolver _resolver;
public ModuleAssemblyLoadContext(string name, string path, params Type[] sharedTypes) : base(name)
{
_path = path;
_resolver = new AssemblyDependencyResolver(_path);
_loaded = new List<Assembly>();
_shared = new Dictionary<string, Assembly>();
if (sharedTypes != null)
{
foreach (Type sharedType in sharedTypes)
{
_shared[Path.GetFileName(sharedType.Assembly.Location)] = sharedType.Assembly;
}
}
}
public void Scan()
{
foreach (string dll in Directory.EnumerateFiles(_path, "*.dll"))
{
var file = Path.GetFileName(dll);
if (_shared.ContainsKey(file))
{
continue;
}
var asm = this.LoadFromAssemblyPath(dll);
_loaded.Add(asm);
}
}
public IEnumerable<T> GetImplementations<T>()
{
return _loaded
.SelectMany(a => a.GetTypes())
.Where(t => typeof(T).IsAssignableFrom(t))
.Select(t => Activator.CreateInstance(t))
.Cast<T>();
}
protected override Assembly Load(AssemblyName assemblyName)
{
string filename = $"{assemblyName.Name}.dll";
if (_shared.ContainsKey(filename))
{
return _shared[filename];
}
string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
if (libraryPath != null)
{
return LoadUnmanagedDllFromPath(libraryPath);
}
return IntPtr.Zero;
}
}
}
I tried modifying the ALC Load function to load the assemblies directly from the shared folder (C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App\3.0.0) which lets the execution continue a bit farther, but it ultimately fails with the following exception:
An attempt was made to load a program with an incorrect format. (0x8007000B)
Here's the revised Load function:
protected override Assembly Load(AssemblyName assemblyName)
{
string filename = $"{assemblyName.Name}.dll";
if (_shared.ContainsKey(filename))
{
return _shared[filename];
}
try
{
if (File.Exists(#"C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App\3.0.0\" + filename))
{
return Assembly.LoadFrom(#"C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App\3.0.0\" + filename);
}
}
catch (Exception ex)
{
//Message displayed is 'An attempt was made to load a program with an incorrect format. (0x8007000B)'
Console.WriteLine(ex.Message);
}
return Assembly.Load(assemblyName);
}
I'm excited about the possibilities of loading/unloading assemblies for a .net Core plugin system, but I'm struggling to get over this hurdle. What am I missing?
I had this issue about a month ago with loading a Assembly to my SQL server. Are you using virtual drives to store your Assembly? I found out that our share drive actual drive path was a E drive and not a P drive which is what is mapped on my computer. I was virtually connected to it, so I had to give the real Drive path which started with E instead of P. Also, your program might be mapping it to the wrong drive as well. I would check that, and if that doesn't help I have about 3-4 more things to try as far as this particular issue in concerned.
I believe the library might also need to be built with the target framework set to .NetCore 3.0 (netcoreapp3.0).

Unable to load NuGet dll with platform specific dlls in netcoreapp

I am unable to load System.Data.Client dll from it's nuget package using the ICompilationAssemblyResolver I have available in a netcoreapp. The bulk of the Assembly resolving is borrowed from here, and works great for the most part. It looks like so:
internal sealed class AssemblyResolver : IDisposable
{
private readonly ICompilationAssemblyResolver assemblyResolver;
private readonly DependencyContext dependencyContext;
private readonly AssemblyLoadContext loadContext;
public AssemblyResolver(string path)
{
this.Assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
this.dependencyContext = DependencyContext.Load(this.Assembly);
this.assemblyResolver = new CompositeCompilationAssemblyResolver(new ICompilationAssemblyResolver[]
{
new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(path)),
new ReferenceAssemblyPathResolver(),
new PackageCompilationAssemblyResolver()
});
this.loadContext = AssemblyLoadContext.GetLoadContext(this.Assembly);
this.loadContext.Resolving += OnResolving;
}
public Assembly Assembly { get; }
public void Dispose()
{
this.loadContext.Resolving -= this.OnResolving;
}
private Assembly OnResolving(AssemblyLoadContext context, AssemblyName name)
{
bool NamesMatch(RuntimeLibrary runtime)
{
return string.Equals(runtime.Name, name.Name, StringComparison.OrdinalIgnoreCase);
}
RuntimeLibrary library =
this.dependencyContext.RuntimeLibraries.FirstOrDefault(NamesMatch);
if (library != null)
{
var wrapper = new CompilationLibrary(
library.Type,
library.Name,
library.Version,
library.Hash,
library.RuntimeAssemblyGroups.SelectMany(g => g.AssetPaths),
library.Dependencies,
library.Serviceable);
var assemblies = new List<string>();
this.assemblyResolver.TryResolveAssemblyPaths(wrapper, assemblies);
if (assemblies.Count > 0)
{
return this.loadContext.LoadFromAssemblyPath(assemblies[0]);
}
}
return null;
}
}
However I am unable to load a dll that references System.Data.Client # 4.3.1 as at runtime I get the error message:
Exception has occurred: CLR/System.IO.FileNotFoundException
An unhandled exception of type 'System.IO.FileNotFoundException'
occurred in System.Private.CoreLib.ni.dll: 'Could not load file or
assembly 'System.Data.SqlClient, Version=4.1.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.'
I am not sure why it is trying to load 4.1.0 when I have specified 4.3.0 but I think that is a bit of a red herring. I suspect that the PackageCompilationAssemblyResolver only looks under the lib folder, and the package in question does not have one for netstandard. It does however have one for specific runtimes:
Armed with this information I have created an incredibly crude AssemblyLoader that looks under the runtimes folder for a nuget package and I am able to load the dll and run my program as I expect.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
namespace Loader
{
public class CrudeCompilationAssemblyResolver : ICompilationAssemblyResolver
{
private readonly string[] _nugetPackageDirectories;
public CrudeCompilationAssemblyResolver()
{
var basePath = Environment.GetEnvironmentVariable("HOME");
var defaultPath = Path.Combine(basePath, ".nuget", "packages");
_nugetPackageDirectories = new [] { defaultPath };
}
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (_nugetPackageDirectories == null || _nugetPackageDirectories.Length == 0 || !string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
return false;
}
foreach (var directory in _nugetPackageDirectories)
{
string packagePath;
var fullPath = Path.Combine(directory, library.Name, library.Version, "runtimes", "unix", "lib", "netstandard1.3", $"{library.Name}.dll");
if (File.Exists(fullPath))
{
assemblies.AddRange(new[] { fullPath });
return true;
}
}
return false;
}
}
}
My question is: Is there a better/officially sanctioned way of loading this troublesome assembly from a nuget package? Or do I need to make my crude loader a lot less crude?
Full repo is here: CustomAssemblyResolver

Referencing a PCL library with Roslyn results in .NET version issues

I'm trying to use Roslyn to execute a block of code that references a PCL library. Both my console application and the PCL library are targeted to .NET 4.5
The syntax tree executes a method in the referenced library that constructs a library class. There should be no .NET 4.0 references.
(5,27): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Has anyone had issues with PCL and Roslyn, or got it to work before?
MyCompanyApplication:Program.cs
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System;
using System.IO;
using System.Reflection;
namespace MyCompanyApplication
{
class Program
{
static void Main(string[] args)
{
EmitResult Result;
var Options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
CSharpCompilation Compilation = CSharpCompilation.Create(
assemblyName: Path.GetRandomFileName(),
syntaxTrees: new[] { CSharpSyntaxTree.ParseText(
#"class Test
{
public void Run(MyCompanyLibrary.Class Class)
{
var Label = Class.NewLabel();
}
}") },
references: new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(MyCompanyLibrary.Class).Assembly.Location),
},
options: Options);
Assembly Assembly = null;
using (var Stream = new MemoryStream())
{
Result = Compilation.Emit(Stream);
if (Result.Success)
Assembly = Assembly.Load(Stream.GetBuffer());
}
if (Result.Success)
{
var TestType = Assembly.GetType("Test");
var Instance = TestType.GetConstructor(new Type[0]).Invoke(new object[0]);
var RunMethod = TestType.GetMethod("Run");
RunMethod.Invoke(Instance, new object[] { new MyCompanyLibrary.Class() });
}
else
{
Console.WriteLine("Test (PCL) failed");
Console.ReadLine();
}
}
}
}
class Test
{
public void Run(MyCompanyLibrary.Class Class)
{
var Label = Class.NewLabel();
}
}
MyCompanyLibrary:Class.cs
namespace MyCompanyLibrary
{
public class Class
{
public Class()
{
}
public Label NewLabel()
{
return new Label(this);
}
}
public class Label
{
internal Label(Class Class)
{
this.Class = Class;
}
private Class Class;
}
}
You are adding a reference to object from your "MyCompanyApplication", which is not a portable class library.
Change this:
MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
to this:
MetadataReference.CreateFromFile(#"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile7\System.Runtime.dll")

C# dll using issue

I am having an issue with compiling a C# dll from a piece of code I wrote. it compiles just fine with no errors, but when I try to include it to a visual studio 2010 C# application the namespace does not show up while trying to call it from the "using" command.
Here is the code of the .dll file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PAD_SCRIPT;
using System.Threading;
namespace PARKER_SCRIPT
{
class PScript
{
//LOAD_REF
private void loadCustomScripts()
{
}
//END_REF
PADScript p = new PADScript();
private void loadScripts()
{
}
public PScript()
{
}
public void runFile(string file)
{
if (file.ToLower().Contains(".pb"))
{
//file = file.Replace(".pb", "");
p.executeLuaWithThread(file);
Console.ReadLine();
}
else
{
Console.WriteLine("ERROR 1: must be .pb file");
Console.ReadLine();
}
}
Core cp = new Core();
public PADScript loadScipt(PADScript l)
{
loadScripts();
loadCustomScripts();
l.addLuaCommand("runFile", this);
return l;
}
//this will be dynamically be updated when custom cs code gets added
private string[] getPatchNotes()
{
string[] info = null;
try
{
info = System.IO.File.ReadAllLines("info\\patch_notes.txt");
return info;
}
catch (Exception i)
{
Console.WriteLine(i.Message);
return info;
}
}
private string getVersion()
{
string info = null;
try
{
info = System.IO.File.ReadAllLines("info\\version.txt")[0];
return info;
}
catch (Exception i)
{
Console.WriteLine(i.Message);
return info;
}
}
}
}
I don't think the functions in the .dll file is an issue, but by compiling it on the command line I think I am missing a key parameter or something. I know when I compile it in visual studio it works just fine implementing it to a new project. Thank you in advance.
edit: here is the command line I did:
C:\WINDOWS\Microsoft.Net\Framework\v4.0.30319\csc.exe /out:Release\ParkerScript.dll /target:library /platform:x86 /reference:core\LuaInterface.dll /reference:core\System.Speech.dll /reference:core\PAD_SCRIPT.dll /reference:core\lua51.dll core\Program_lib.cs core\AssemblyInfo.cs core\lib\*.cs
The class definition is internal, which will not show up when you reference it.
Define your class like this:
namespace PARKER_SCRIPT
{
public class PScript
{
//Code goes here...
}
}

Compiled class in compiling file

I have a promblem with run-time compiled classes. I have something like this 2 classes:
first class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Program.Bullet {
public class Class1{
private int i;
public Class1(int j){
i=j;
}
}
}
and second class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Program.Bullet;
namespace Program.Object {
public class Class2{
public Class2(){
Class1 c1 = new Class1(5);
}
}
}
This two classes I would like to compile in run-time and use them in my project. So I have function to compile it (XmlNode has data about fullPath etc):
private ModuleBuilder moduleBuilder;
private List<string> isCompiled;
private void Compile(XmlNode compileingClasses) {
foreach (XmlNode compileingClass in compileingClasses) {
string fullPath = compileingClass.Attributes["path"].InnerText;
string type = compileingClass.Attributes["name"].InnerText; ;
if (!isCompiled.Contains(type)) {
isCompiled.Add(type);
var syntaxTree = SyntaxTree.ParseFile("../../File1/File2/" + fullPath);
var comp = Compilation.Create("Test.dll"
, syntaxTrees: new[] { syntaxTree }
, references: metadataRef
, options: comilationOption
);
// Runtime compilation and check errors
var result = comp.Emit(moduleBuilder);
if (!result.Success) {
foreach (var d in result.Diagnostics) {
Console.WriteLine(d);
}
throw new XmlLoadException("Class not found " + fullPath);
}
}
}
}
Is it possible to get the reference on Class1 to Class2?
Edit: Better question
Is it possible to create MetadataReference on compiled Class1?
Something like:
string fullName = bullet.Attributes["fullName"].InnerText;
var o = moduleBuilder.GetType(fullName);
metadataRef.Add(new MetadataFileReference(o.Assembly.Location));
This throw NotSupportedException
You're trying to reference the assembly which is currently being built and I don't think Roslyn can do that.
What you can do instead is to create a single Compilation from all your classes (probably having a separate SyntaxTree for each class). If you do that, you won't need any references.

Categories