简体   繁体   中英

Loading .NET assembly dependencies not working

I have been searching for a solution for a couple of days. None of the answers work in my case which is to reference (load?) assemblies .NET into app domain from PowerShell session.

I load references first (that are required to be referenced by the aforementioned DLL to be working [Reflection.Assembly]::LoadFile() or [Reflection.Assembly]::LoadFrom() ) then I load my .NET DLL by calling Add-Type .

Unfortunately that is not working so I cannot create a few instances from that DLL. I am getting the same errors when I use DLL without references attached in a normal C# project but as soon as I reference the other assemblies and recompile it works without errors (I can confirm it is because of referenced assemblies as I checked that in LinqPad as well).

PowerShell:

[System.Reflection.Assembly]::LoadFile((Get-Item -Path ".\System.Data.SQLite.dll" ).FullName)
Add-Type -Path (Get-Item -Path ".\Connector.dll" ).FullName -ReferencedAssemblies (Get-Item -Path ".\System.Data.SQLite.dll" ).FullName -PassThru | Out-Null
$certMGT = New-Object Connector

third line of that PowerShell script throws:

New-Object : Exception calling ".ctor" with "0" argument(s): "Failed to find or load the registered .Net Framework Data Provider."
At C:\Repos\Connector\bin\Installer.ps1:306 char:20
+         $certMGT = New-Object Connector
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodInvocationException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

PSMessageDetails      : 
Exception             : System.Management.Automation.MethodInvocationException: Exception calling ".ctor" with "0" argument(s): "Failed to find or load the registered .Net Framework
                         Data Provider." ---> System.Configuration.ConfigurationErrorsException: Failed to find or load the registered .Net Framework Data Provider.
                           at System.Data.Common.DbProviderFactories.GetFactory(DataRow providerRow)
                           at System.Data.EntityClient.EntityConnection.GetFactory(String providerString)
                           at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString)
                           at System.Data.Objects.ObjectContext..ctor(String connectionString, String defaultContainerName)
                           at Connector.Entity.ConnectorDBEntities..ctor(String connectionString)
                           at Connector.DBManager..ctor()
                           at Connector.DAL.ConfigurationDAL..ctor()
                           at Connector.ConnectorConfig..ctor()
                           at Connector.ConnectorCertMGT..ctor()
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArgumen
                        ts)
                           at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
                           at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)
TargetObject          : 
CategoryInfo          : InvalidOperation: (:) [New-Object], MethodInvocationException
FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo

LinqPad query (C# Program; references Connector.dll) - this works fine

void Main()
{
    Assembly.LoadFile(@"C:\Repos\Connector\bin\System.Data.SQLite.dll");
    Connector connector = new Connector();//this also throws exactly the same error if I do not LoadFile as in above line
}

Step 1 Compile Connector.dll - presumably you already have that done

$SQLitePath = convert-path '.\res\sqlite-netFx46-binary-bundle-x64-2015-1.0.114.0\System.Data.SQLite.dll'
add-type -path $SQLitePath

$null = new-item '.\Connector.cs' -value @'
using System;
using System.Data.SQLite;

namespace Powershell.Examples{
public class Connector : System.IDisposable {
   SQLiteConnection con;

   public Connector(){}
   
   public void connect(string Path){
      con = new SQLiteConnection();
      con.ConnectionString = "Data Source=" + Path;
      con.Open();
   }
   
   public void close(){
      if(con.State == System.Data.ConnectionState.Open)
         con.Close();
   }

   bool _disposed = false;
   public void Dispose(){
      Dispose(disposing: true);
      GC.SuppressFinalize(this);
   }
   protected virtual void Dispose(bool disposing){
      if(_disposed) return;
      if(disposing){
         // free managed objects here
         con.Dispose();
      }
      // freee unmanaged objects here
      
      _disposed = true;
   }
   ~Connector(){ Dispose(disposing:false); }
}}
'@
$pams = @{
   TypeDefinition = get-content '.\Connector.cs' -raw
   OutputAssembly = '.\Connector.dll'
   OutputType     = 'Library'
   ReferencedAssemblies = @($SQLitePath,'System.Data')
}
$null = add-type @pams -PassThru

Step 2 Use it in Powershell

PS C:\Working\Folder> $SQLitePath = convert-path '.\res\sqlite-netFx46-binary-bundle-x64-2015-1.0.114.0\System.Data.SQLite.dll'
PS C:\Working\Folder> add-type -Path $SQLitePath
PS C:\Working\Folder> add-type -Path (convert-path '.\Connector.dll') -ReferencedAssemblies $SQLitePath

PS C:\Working\Folder> $obj = [Powershell.Examples.Connector]::new()
PS C:\Working\Folder> $obj.connect((Convert-Path .)+'\MyData.db')
PS C:\Working\Folder> $obj.close()
PS C:\Working\Folder> $obj.Dispose()
PS C:\Working\Folder> rv obj

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM