PowerShell error 'can't call null-value expresssion' [duplicate] - powershell

I am simply trying to create a powershell script which calculates the md5 sum of an executable (a file).
My .ps1 script:
$answer = Read-Host "File name and extension (ie; file.exe)"
$someFilePath = "C:\Users\xxx\Downloads\$answer"
If (Test-Path $someFilePath){
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
$hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
$hash
$stream.Close()
}
Else{
Write-Host "Sorry, file $answer doesn't seem to exist."
}
Upon running my script I receive the following error:
You cannot call a method on a null-valued expression.
At C:\Users\xxx\Downloads\md5sum.ps1:6 char:29
+ $hash = [System.BitConverter]::ToString($md5.Compute ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
To my understanding, this error means the script is attempting to do something, but another part of the script does not have any information to permit the first part of the script to work properly. In this case, $hash.
Get-ExecutionPolicy outputs Unrestricted.
What is causing this error?
What exactly is my null valued expression?
Any help is appreciated. I apologize if this is trivial and will continue my research.
References:
http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/27/troubleshoot-the-invokemethodonnull-error-with-powershell.aspx
How to get an MD5 checksum in PowerShell

The simple answer for this one is that you have an undeclared (null) variable. In this case it is $md5. From the comment you put this needed to be declared elsewhere in your code
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
The error was because you are trying to execute a method that does not exist.
PS C:\Users\Matt> $md5 | gm
TypeName: System.Security.Cryptography.MD5CryptoServiceProvider
Name MemberType Definition
---- ---------- ----------
Clear Method void Clear()
ComputeHash Method byte[] ComputeHash(System.IO.Stream inputStream), byte[] ComputeHash(byte[] buffer), byte[] ComputeHash(byte[] buffer, int offset, ...
The .ComputeHash() of $md5.ComputeHash() was the null valued expression. Typing in gibberish would create the same effect.
PS C:\Users\Matt> $bagel.MakeMeABagel()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $bagel.MakeMeABagel()
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
PowerShell by default allows this to happen as defined its StrictMode
When Set-StrictMode is off, uninitialized variables (Version 1) are assumed to have a value of 0 (zero) or $Null, depending on type. References to non-existent properties return $Null, and the results of function syntax that is not valid vary with the error. Unnamed variables are not permitted.

Related

$Var.ToUpper() throwing "You cannot call a method on a null-valued expression."

Everyone.
I'm not sure why this is happening, but in my PowerShell script I am converting a string (server name entered by the end user) to uppercase. My trouble is that when I run my script it throws the error "You cannot call a method on a null-valued expression." on the open/close parentheses of the *.ToUpper(). As far as I know using ToUpper it in this case should just shift the case.
Here's an example:
$Server = $Server.ToUpper()
And the output:
You cannot call a method on a null-valued expression.
At C:\TEMP\Servers.ps1:705 char:2
+ $Server = $Server.ToUpper()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Now, I have tried to just convert to uppercase on whatever action I am calling, for instance:
$GP = Get-printer -ComputerName $Server.ToUpper()
The above also fails on the "()".
But it doesn't seem to be happening all the time. I am converting in numerous places and it's working as expected, but sporadically in the script it's throwing errors.
I've tried $Server = $Server.ToUpper() and $Server = $Server.ToUpper -- and I get mixed results of success and errors.
I'm betting I'm missing something small with this. Any advice on how to resolve?
Thanks,
Dale

How to pass a custom enum to a function in powershell

When defining a function, how can you reference a custom enum?
Here's what I'm trying:
Add-Type -TypeDefinition #"
namespace JB
{
public enum InternetZones
{
Computer
,LocalIntranet
,TrustedSites
,Internet
,RestrictedSites
}
}
"# -Language CSharpVersion3
function Get-InternetZoneLogonMode
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[JB.InterfaceZones]$zone
)
[string]$regpath = ("HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\{0}" -f [int]$zone)
$regpath
#...
#Get-PropertyValue
}
Get-InternetZoneLogonMode -zone [JB.InternetZones]::TrustedSites
But this gives the error:
Get-ZoneLogonMode : Unable to find type [JB.InterfaceZones]. Make sure that the assembly that contains this type is loaded.
At line:29 char:1
+ Get-ZoneLogonMode -zone [JB.InternetZones]::TrustedSites
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (JB.InterfaceZones:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
NB: I'm aware I could use ValidateSet for similar functionality; however that has the disadvantage of only having a name value; as opposed to allowing me to program using friendly names which are then mapped to ints in the background (I could write code for that; but enum seems more appropriate if possible).
I'm using Powershell v4, but ideally I'd like a PowerShell v2 compatible solution as most users are on that version by default.
Update
I've corrected the typo (thanks PetSerAl; well spotted).
[JB.InterfaceZones]$zone now changed to [JB.InternetZones]$zone.
Now I'm seeing error:
Get-InternetZoneLogonMode : Cannot process argument transformation on parameter 'zone'. Cannot convert value "[JB.InternetZones]::TrustedSites" to type
"JB.InternetZones". Error: "Unable to match the identifier name [JB.InternetZones]::TrustedSites to a valid enumerator name. Specify one of the following
enumerator names and try again: Computer, LocalIntranet, TrustedSites, Internet, RestrictedSites"
At line:80 char:33
+ Get-InternetZoneLogonMode -zone [JB.InternetZones]::TrustedSites
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-InternetZoneLogonMode], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-InternetZoneLogonMode
The ISE gave this one away to me but your attempted syntax was not completely incorrect. I was able to do this and get it to work.
Get-InternetZoneLogonMode -Zone ([JB.InternetZones]::TrustedSites)
Again, If you look at the highlighting you will see how I came to that conclusion.
Per comments by PetSerAl & CB:
Corrected typo in function definition
from [JB.InterfaceZones]$zone
to [JB.InternetZones]$zone
Changed function call
from Get-InternetZoneLogonMode -zone [JB.InternetZones]::TrustedSites
to Get-InternetZoneLogonMode -zone TrustedSites

Unable to Run [System.__ComObject].InvokeMember within PowerShell Function

I've been trying to write a program to access properties and methods of a 3rd party OLE DLL.
Below code runs fine.
[System.__ComObject].InvokeMember("AppName", [System.Reflection.BindingFlags]::GetProperty, $null, $appObj, $null)
As the invocation is going to be repetitive, I want to call a wrapper like below.
function Get-Property {
param(
$objOLE,
[String] $propertyName
)
[System.__ComObject].InvokeMember($propertyName,[System.Reflection.BindingFlags]::GetProperty,$null,$objOLE,$null)
}
When the script runs
Get-Property($appObj, "AppName")
I got this error:
Exception calling "InvokeMember" with "5" argument(s): "Method 'System.__ComObject.ToString' not found."
At F:\Scripts\test.ps1:21 char:36
+ [System.__ComObject].InvokeMember <<<< ($propertyName,[System.Reflection.BindingFlags]::GetProperty,$null,$objOLE,$null)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
This is confusing. Anybody has an insight? Thank you in advance.
Remember your function is a PowerShell function/command and not a .NET method i.e. don't use parens and don't comma separate args:
Get-Property $appObj AppName
The way you had it, your function gets one argument that is an array with two elements.

powershell function parameter types

have the following function:
function appendToSB([System.Text.StringBuilder]$sb,
[string]$value){
[void]$sb.append($value)
$sb
}
$sb = new-object -typename system.text.stringbuilder
$sb = appendToSb($sb, "1,")
$sb.tostring() | out-host
i want to build string using StringBuilder using my function for that, but i receive the following error:
appendToSB : Cannot process argument transformation on parameter 'sb'.
Cannot convert the "System.Object[]" value of ty pe "System.Object[]"
to type "System.Text.StringBuilder". At E:\powershell\test.ps1:8
char:11
+ appendToSb([system.text.stringbuilder]$sb, "1,")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [appendToSB], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,appendToSB
does anybody can explain how function/function parameter/return values works in powershell?
Classic PowerShell issue. You don't use parens or comma separated args when calling commands or functions e.g.:
appendToSb $sb "1,"
You only use that syntax when calling .NET methods. If you use Set-StrictMode -Version 2 it will catch this sort of issue. What you passed ($sb, "1,") is how you would pass an array to a single parameter. Technically the parens aren't needed but don't change the value i.e. you could pass an array like this as well $sb, ",".

Weird PowerShell Exec Output Capture Behavior

I'm writing a simple PowerShell script that handles the output of mkvinfo. It captures the output of mkvinfo, stores in a variable $s and does some post-processing on $s. The strange part is while $s has content, I can't extract a substring from it.
The error message I'm getting was:
Exception calling "Substring" with "1" argument(s): "startIndex cannot be larger than length of string.
Parameter name: startIndex"
This is a sample code:
$filePath = $folder + $file.name
$mkvinfoExe = "C:\mkvinfo.exe"
$s = & $mkvinfoExe $filePath
$s | out-host
$s.Substring($s.Length-1) | out-host
Are you sure $s is a string and not an array? If it is an array, $s.Length will be the number of elements in the array and you could get the error that you are getting.
For example:
PS > $str = #("this", "is", "a")
PS > $str.SubString($str.Length - 1)
Exception calling "Substring" with "1" argument(s): "startIndex cannot be larger than length of string.
Parameter name: startIndex"
At line:1 char:1
+ $str.SubString($str.Length - 1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
Just found out because mkvinfo outputs multiple lines, $s is actually a String array (or List?). Switching to $s[0].Substring($s[0].Length-1) solves it.