英文:
Problems using Microsoft.Data.SqlClient in custom c# Powershell CmdLet
问题
我在尝试使用C#(.NET Framework 4.7.2)编写自己的CmdLet时遇到了版本冲突的问题,使用了Microsoft.Data.SqlCLient
库 - 仅这几行代码总是导致一些错误,因为SqlClient
想要加载System.Memory
版本4.0.1.1 - 我需要这个dll用于其他NuGet包,并且已经更新到了最新版本 - 我找不到如何阻止SqlClient
使用旧版本System.Memory
的解决方法
这是我总是收到的错误:
> 无法加载文件或程序集'System.Memory,Version=4.0.1.1,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51'或其依赖项之一。系统找不到指定的文件。
对这个问题有什么帮助吗?我尝试了很多不同的方法(如app.config
设置),但似乎都不起作用。
英文:
I run into a version conflict when trying to write my own CmdLet in C# (.NET Framework 4.7.2) using Microsoft.Data.SqlCLient
- just these few lines of code are always resulting in some errors because SqlClient
wants to load System.Memory
version 4.0.1.1 - I need this dll for other nuget packages and have updated to latest version - I found no solution how to prevent SqlClient
to use the old version of System.Memory
public class CmdLetEnvironment
{
public static bool Connected = false;
[System.Management.Automation.Cmdlet(System.Management.Automation.VerbsCommunications.Connect, "RDTest")]
public class RDEnvironmentConnectCommand : System.Management.Automation.PSCmdlet
{
protected override void ProcessRecord()
{
try
{
SqlConnection conn = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=TestLocalOMA1;Integrated Security=True;Encrypt=False");
conn.Open();
}
catch(Exception ex)
{
throw ex.InnerException;
}
}
}
}
This is the error I always get:
> Could not load file or assembly 'System.Memory, Version=4.0.1.1, Culture=neutral,
PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.
Any help on this issue? I have tried so many different things (like app.config
settings) but nothing seems to work
答案1
得分: 1
我找到了解决方法 - 由于PowerShell以不同的方式加载模块,而不是普通的.NET应用程序,您需要覆盖程序集加载。
在类中添加构造函数并覆盖AssemblyResolve以修复它 - 然后您只需要确保所有的dll都位于与您的CmdLet dll相同的目录中。
[System.Management.Automation.Cmdlet(System.Management.Automation.VerbsCommunications.Connect, "RDTest")]
public class RDEnvironmentConnectCommand : System.Management.Automation.PSCmdlet
{
public RDEnvironmentConnectCommand()
{
var domain = AppDomain.CurrentDomain;
domain.AssemblyResolve += LoadAssembly;
}
private Assembly LoadAssembly(object sender, ResolveEventArgs args)
{
Assembly result = null;
// 获取当前dll的完整路径
FileInfo info = new FileInfo(Assembly.GetExecutingAssembly().Location);
// 获取执行.exe文件的文件夹
var folderPath = info.Directory.FullName;
// 构建加载程序集的潜在完整路径
var assemblyName = args.Name.Split(new string[] { "," }, StringSplitOptions.None)[0];
var assemblyExtension = "dll";
var assemblyPath = Path.Combine(folderPath, string.Format("{0}.{1}", assemblyName, assemblyExtension));
if (File.Exists(assemblyPath))
{
// 使用我们的自定义路径加载所需的程序集
result = Assembly.LoadFrom(assemblyPath);
}
else
{
// 保留默认加载
return args.RequestingAssembly;
}
return result;
}
protected override void ProcessRecord()
{
try
{
SqlConnection conn = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=TestLocalOMA1;Integrated Security=True;Encrypt=False");
conn.Open();
}
catch (Exception ex)
{
throw ex.InnerException;
}
}
}
我希望这能帮助其他遇到相同问题的人们
英文:
I found the solution for it - as Powershell is loading modules in different way then normal .NET application you need to override the assembly loading.
Add a constructor to the class and override AssemblyResolve to fix it - then you only need to ensure that all dll's are located in same directory then your CmdLet dll
[System.Management.Automation.Cmdlet(System.Management.Automation.VerbsCommunications.Connect, "RDTest")]
public class RDEnvironmentConnectCommand : System.Management.Automation.PSCmdlet
{
public RDEnvironmentConnectCommand()
{
var domain = AppDomain.CurrentDomain;
domain.AssemblyResolve += LoadAssembly;
}
private Assembly LoadAssembly(object sender, ResolveEventArgs args)
{
Assembly result = null;
//Get current dll fullpath
FileInfo info = new FileInfo(Assembly.GetExecutingAssembly().Location);
//Get folder of the executing .exe
var folderPath = info.Directory.FullName;
//Build potential fullpath to the loading assembly
var assemblyName = args.Name.Split(new string[] { "," }, StringSplitOptions.None)[0];
var assemblyExtension = "dll";
var assemblyPath = Path.Combine(folderPath, string.Format("{0}.{1}", assemblyName, assemblyExtension));
if (File.Exists(assemblyPath))
{
//Load the required assembly using our custom path
result = Assembly.LoadFrom(assemblyPath);
}
else
{
//Keep default loading
return args.RequestingAssembly;
}
return result;
}
protected override void ProcessRecord()
{
try
{
SqlConnection conn = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Initial Catalog=TestLocalOMA1;Integrated Security=True;Encrypt=False");
conn.Open();
}
catch(Exception ex)
{
throw ex.InnerException;
}
}
}
I hope that could help other people running into the same issue
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论