System.DayOfWeek does not contain op_Addition - powershell

I have a method that returns last Saturday's Date, and it used to work on the old place I ran it, but I moved it to a new location to run it and it's not working. I'm not sure if this version of powerShell is different and that's the issue. It's saying PSVersion is 4 in the new location. The old location had PSVersion of 5.1.
This is my method, and when I check $newdate, it is empty after this runs and during run.
function GetLastSaturdayDate()
{
$date = Get-Date
$newdate = $date.AddDays(-($date.DayOfWeek+1)%7)
return $newdate
}
When I run the commands at the ps commandline, it says the following. I don't see this error message when I'm just running the script:
Method invocation failed because [System.DayOfWeek] does not contain a method named 'op_Addition'.
At line:1 char:1
+ $newda = $date.AddDays(-($date.DayOfWeek+1)%7)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any ideas how to get date addition to work in the older powershell version? Maybe I need to include or use something like math?

Because your DayOfWeek member is an enumeration of type System.DayOfWeek, powershell is trying to use the System.Enum type to perform addition, but that type does not support addition unless it has a Flags attribute. The way to remediate this is by flipping your operands so the DayOfWeek gets coerced to System.Int32 instead:
1 + $date.DayOfWeek
Alternatively (for style), typecast it yourself:
[int]$date.DayOfWeek+1

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.

In Powershell: ToLower() works, in VSC/Powershell not?

I have win10 Pro and Powershell 5.1
On the other hand VSC(1.54.1) with the powershell extention (ms-vscode-powershell, v2021.2.2).
The command
$day = $day.ToLower()
on the Powershell prompt works fine
But in VSC it says:
+ $dayName = $dayName.ToLower()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
MethodNotFound???
Any help?
Thanks
$dayName.ToString().ToLower() should do what you expect here (according to your comment).
.ToLower() is a string method and you are trying to use it on System.DayOfWeek, which doesn't have that method.
In order to keep track of your variables and just what they are, running $myVariable.GetType().FullName can be very handy - I use it all the time.
In your example, running
$day.GetType().FullName
$dayName.GetType().FullName
would probably result in something like
PS C:\> $day.GetType().FullName
System.String
PS C:\> $dayName.GetType().FullName
System.DayOfWeek

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...

Accessing non-existent property of a hashtable behaves differently in and out of the module

In a PowerShell script or a simple one-file psm1 module accessing a non-existent property of a hashtable returns $null
$hashtable = #{}
$hashtable.NonExistentKey -eq $null # returns true
But when this code is a part of a proper module with a psd1 manifest the same code throws an exception
The property 'NonExistentKey' cannot be found on this object. Verify that the property exists.
Maybe someone knows what's the reason for this behavior and if it can be changed?
UPD: I know that ContainsKey is the proper way, but it concerns executing legacy code and different behavior in general.
UPD2: Set-StrictMode was indeed the case. Thanks, everyone!
As stated by #Jeroen Mostert above, strict mode might be active.
PowerShell session with active strict mode:
> Set-StrictMode -Version 2.0
> $d = #{}
> $d.SomeNotExistingKey
The property 'SomeNotExistingKey' cannot be found on this object. Verify that the property exists.
At line:1 char:1
+ $d.SomeNotExistingKey
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
PowerShell session WITHOUT active strict mode:
> $d = #{}
> $d.SomeNotExistingKey
From MSDN:
... When strict mode is on, Windows PowerShell generates a terminating error when the content of an expression, script, or script block violates basic best-practice coding rules.
Hope that helps

Unable to do type verification on a runspace

I am using Pester to do some unit testing on a module I am creating and I'm having a bit of trouble with one of my functions that is supposed to return a runspace object. When I create a runspace object and do a .GetType() I see the name listed as LocalRunspace with a fullname of System.Management.Automation.Runspaces.LocalRunspace however when I run$Runspace -is [LocalRunspace] or $Runspace -is [System.Management.Automation.Runspaces.LocalRunspace] I get the error message below
Unable to find type [System.Management.Automation.Runspaces.LocalRunspace]. Make sure that the assembly that contains this type is loaded.
At line:1 char:1
+ $ps.Runspace -is [System.Management.Automation.Runspaces.LocalRunspace]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Manageme...s.LocalRunspace:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
Just trying to figure out what type I should be referencing in order to create the proper validation check. I know I could fall back on doing comparison to the results of the .GetType() but I'd really rather use the normal Pester convention of Should BeOfType