Using PowerShell to create Entity Framework DbContext - entity-framework

I'm trying to create powershell management scripts for my EF6 based website, but I'm struggling to create a DbContext to access my entities.
Following PowerShell App.Config, I'm doing the following to load my dll, set the config file for the current app domain and instantiate my DbContext.
Add-Type -AssemblyName System.Configuration
[appdomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "path.to.web.config")
[Reflection.Assembly]::LoadFrom("MyProject.Dll")
$ctx = New-Object MyProject.MyDbContext
$ctx
I'm able to load the dll, and can inspect that it finds the MyProject.MyDbContext class, and it seems to be able to create the object as well, but upon executing the last statement I get a TargetInvocationException
format-default : Exception has been thrown by the target of an invocation.
+ CategoryInfo : NotSpecified: (:) [format-default], TargetInvocationException
+ FullyQualifiedErrorId : System.Reflection.TargetInvocationException,Microsoft.PowerShell.Commands.FormatDefaultCommand
I've tried catching the TargetInvocationException, but it seems to escape my try-catch somehow.
Any ideas?

It turns out that PowerShell.exe uses .NET v2.0 by default. Following cmo999's answer (note that it's not the accepted answer on that question), it's possible to run powershell.exe under v4.0 by modifying powershell.exe.config.

Related

InvalidCastException when trying to obtain UserPrincipal.Current

I have a PowerShell script which checks the currently signed in user as part of its start-up process. I'm using .Net to do this by adding the assembly:
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$cUser = [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
For almost everyone this works fine and I get a UserPrincipal object that I can use elsewhere, however there are a couple of users who get the following error when running it:
Unable to cast object of type 'System.DirectoryServices.AccountManagement.GroupPrincipal' to type 'System.DirectoryServices.AccountManagement.UserPrincipal'. At line:2 char:1
+ [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException
This is on a standard Windows 10 20H2 install and doesn't matter if PowerShell is running elevated or not. I've never seen this call return anything other than a UserPrincipal before, so I would be grateful for any advice: is this something I can deal with in code, or is there some underlying issue with the machines that are returning this exception?
I don't know if this is what you're looking for:
$cUser = Get-ADUser $Env:Username -Properties *
This has the most important attributes that you can use for whatever you want later on. It provides as much attribute as the code you posted that didn't work for some of the user.

Error downloading files with DownloadFile in powershell 2

I have the need to download files under powershell 2.
Since Invoke-WebRequest is not supported in version 2, I try to use DownloadFile but I always get the same error and I don't know how to fix it.
PS C:\Users\user> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
:: : Exception setting "SecurityProtocol": "Cannot convert null to type "System.Net.SecurityProtocolType" due to invali
d enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values ar
e "Ssl3, Tls"."
At line:1 char:28
+ [Net.ServicePointManager]:: <<<< SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
PS C:\Users\user> $client = new-object System.Net.WebClient
PS C:\Users\user> $client.DownloadFile("https://web.com/test.txt", "C:\Users\user\Desktop\test.txt")
DownloadFile : Exception calling "DownloadFile" with "2" argument(s): "The underlying connection was closed: An unexpec
ted error occurred on a send."
At line:1 char:21
+ $client.DownloadFile <<<< ("https://web.com/test.txt", "C:\Users\user\Desktop\test.txt")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
What I can do?
If you are getting an error setting the TLS version, you may want to check which protocols are available:
[Net.SecurityProtocolType]::GetValues( 'Net.SecurityProtocolType' )
However, I don't know how the protocol availability will be affected by using such an old version. Moreover, I don't know how specific protocol settings on a given system affect the availability of protocols either at large or as returned by the above command.
In fact, I would point out the error itself only reflects SSL3 & Tls. On my system when I enter an invalid enumerator the error reports Ssl3,Tls,Tls11,Tls12,Tls13 as choices. While my system is configured to disable everything below Tls12 and has no settings defined for Tls13.
The best assumption I can make is .Net 2.0 which is used with PowerShell 2.0 cannot use Tls12 as it's not present in the enumerators and based on comparison with my system the enums aren't affected by explicit enabling/disabling of protocols.
In any case, I think you have to clear up the first error before you worry about the second. The second error may well be due to the TLS incompatibility. The easiest way to do this would be to upgrade PowerShell (along with the required .Net version). PowerShell 2.0 can coexist with Windows PowerShell 5.1 though you may have to launch with the -Version 2.0 parameter. Also, make sure the engine is installed as a Windows feature. DISCLAIMER: verify all that on your own.
I know the Windows PowerShell 2.0 Engine (PowerShell-V2) was available as a feature at least as late as Windows 2012 R2.
I would also point out that PowerShell 7.x (aka PowerShell Core) can be installed side by side with Windows PowerShell. Potentially this could sidestep the aforementioned complications, allowing you to do run the task at hand...

How to fix DLL LoaderExceptions in PowerShell

I'm trying to load a .dll of itext7, but if I use this
Add-Type -Path "D:\Eigene\Packages\itext7.7.1.5\lib\net40\itext.kernel.dll"
I get the following exception (translated from german):
Add-Type : Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
In Zeile:2 Zeichen:1
+ Add-Type -Path "D:\Eigene\Packages\itext7.7.1.5\lib\net40\itext.kerne ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
+ FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeCommand
When I use:
try { Add-Type -Path "D:\Eigene\Packages\itext7.7.1.5\lib\net40\itext.kernel.dll" }
catch { $_.Exception.LoaderExceptions }
It says (also translated from german):
The File or Assembly "BouncyCastle.Crypto, Version=1.8.1.0,
Culture=neutral, PublicKeyToken=0e99375e54769942" or a dependency of
it was not found. The system can not find the specified file.
How can I fix this?
EDIT:
I found a BouncyCastle dll on my system that it also downloaded when I installed the itext7 package but it also doesn't work, if I load "D:\Eigene\Packages\Portable.BouncyCastle.1.8.5\lib\net40\BouncyCastle.Crypto.dll" before i load the itext.kernel.dll.
Your assembly is looking for a different version than you have.
I'm not sure if you can do an assembly binding in powershell like you could with an application where you could bind an older assembly to a new one example:
https://learn.microsoft.com/en-us/dotnet/framework/deployment/configuring-assembly-binding-redirection
Your error is asking you to load the dll of version 1.8.1.0 with the public token of: PublicKeyToken=0e99375e54769942
Generally the assembly publisher isn't changing their public token although it is technically possible bouncy castle could so you likely don't need to specify that.
Anyway you need to find the older version (seems like you have 1.8.5). It is likely these are compatible, but best / safest bet is to use the same assembly the one you are loading needs.
You may find some help here if you need to do binding redirection to the newer assembly: Powershell - Assembly binding redirect NOT found in application configuration file

Exception creating client using AWS SDK

I am currently using the following sequence of commands in a Windows 7 PowerShell window.
Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\Net35\AWSSDK.dll"
$secretKeyID="ABCDEFGHIJKLMNOPQRS"
$secretAccessKeyID="LONGKEYBLAHBLAHBLAHBLAHBLABLAH"
$AWSclient=[Amazon.AWSClientFactory]::CreateAmazonS3Client($secretKeyID,$secretAccessKeyID)
However, I get this exception below. Please let me know what Im doing wrong. This is what I see most people using successfully.
Exception calling "CreateAmazonS3Client" with "2" argument(s): "No RegionEndpoint or ServiceURL configured"
At line:1 char:1
+ $oAWSclient=[Amazon.AWSClientFactory]::CreateAmazonS3Client($secretKeyID,$secret ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : AmazonClientException
One thing that I think is a problem is that my bucket is not checked for 'enable website hosting'. Does this need to be set to true? I just want to upload a file to the bucked via powershell script.
Duh... I realized that I need to use the AWS Powershell because it has all the settings built into it. Im not exactly sure how to properly refer to this version of powershell, but it is available after installing the AWS SDK.
Since the error specifically states that you're missing the RegionEndpoint or ServiceURL, you could also just include one of them. Since you're connecting to S3, all you need is to include the RegionEndpoint.
Add-Type -Path "C:\Program Files (x86)\AWS SDK for .NET\bin\Net35\AWSSDK.dll"
$secretKeyID="ABCDEFGHIJKLMNOPQRS"
$secretAccessKeyID="LONGKEYBLAHBLAHBLAHBLAHBLABLAH"
$client = [Amazon.AWSClientFactory]::CreateAmazonS3Client($secretKeyID, $secretAccessKeyID, [Amazon.RegionEndpoint]::USEast1)
(Replace USEast1 with the value configured with your S3 Bucket)

reference assembly in Powershell script

In Visual Studio I'm able to simply add a reference to an assembly, for example: Interop.ADODB.
How do I do this in powershell? The following is exploding
[Reflection.Assembly]::LoadWithPartialName("Interop.ADODB")
$conn = New-Object ADODB.Connection
And here is the error message
New-Object : Constructor not found. Cannot find an appropriate constructor for type ADODB.Connection.
At C:\Users\michaelr\Desktop\jet-project\PS\test.ps1:3 char:19
+ $conn = New-Object <<<< ADODB.Connection
+ CategoryInfo : ObjectNotFound: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand
I'm on Windows 7 x64.
Use this line instead:
$conn = New-Object -comobject ADODB.Connection
Powershell understand com object natively (well to the extent it's possible for objects that don't always have a lot of metadata) and does all the interop for you. You just need to tell powershell that it's a COM object. You don't need to reference the interop assemblies explicitly.
Having said that, depending on your task you might be better off using a native .net provider instead of ADODB.
You're looking for the Add-Type cmdlet, which lets you either compile .NET code into an in-memory assembly, or load an assembly from disk.
Check out the -AssemblyName parameter if you want to load an assembly from the GAC, or the -Path parameter if you know exactly where the DLL you want to load is.
The answer's right in front of you:
Cannot find an appropriate constructor for type ADODB.Connection
You need to pass the connection string to the constructor like this:
$c = new-object ADODB.connection "server=foo;user id=bar ..."
However, I don't understand why you want to use 1998-era ADODB in .NET when you can use System.Data instead. Check out this MSDN article on accessing databases with PowerShell:
http://technet.microsoft.com/en-us/magazine/hh855069.aspx