You cannot call a method on a null-valued expression? - powershell

I'm trying to take the input "name" and find the whitespace so that I can find the first and last letter of the first and last name entered. But it's telling me "You cannot call a method on a null-valued expression." Help?
$name = Read-Host "Please enter the zip of person $count"
$length = $name.Length
$name = $name.split(" ")
write-host $name[0]

You made a significant change to your post. It used to be:
$name = Read-Host "Please enter the name of person $count"
$length = $name.Length
$pos = $name.IndexOf('\s')
print $pos
Lets ignore the $length line since you do not use it. It looks like you are trying to split on the first white space using regular expressions. You are using .IndexOf() which if you examine the overloads will see it expects strings or a char. Not earth shattering but the point is it is looking for string literals and does not support regular expressions. Consider the following statements
PS C:\Users\Cameron> "John Smith".IndexOf('\s')
-1
PS C:\Users\Cameron> "John\sSmith".IndexOf('\s')
4
The first returned -1 since the string \s was not found. Then we put that string between John and Smith and we now get a positive return since the string literal was matched.
What you were possibly trying to do was use the -split which I base on your original question and the edit. -split supports regular expressions.
PS C:\Users\Cameron> $name = "John Smith"
PS C:\Users\Cameron> ($name -split '\s+')[0]
John
What the second line of code did was split the string $name on the group of white-space. We returned the first element which would be 'John'. The second, not shown since it should be obvious is 'Smith'. Neither elements have trailing or leading white-space ( based only on this example. Mileage will vary on other strings.)
Also, the command print is and alias for Out-Printer. Doubt you meant that command and were most likely looking for, like Dane Boulton suggested, Write-Host or Write-Output. Note: Look them up to understand an important difference. Former writes to console where the ladder writes to the output stream.
Lastly good guess would be that the error was caused by $name being null at the time $name.IndexOf('\s') was called. Easy to simulate as well.
PS C:\Users\Cameron> $something = $null
PS C:\Users\Cameron> $something.Method()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $something.Method()
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

im not sure which is causing you to get the null value error. But to get the first and last name just use this:
$name = "John Smith"
$name = $name.split(" ")
$name[0] #outputs John
$name[1] #outputs Smith
Also you want write-host or write-output not print

Related

New-ADUser and SAMAccountName limit

I've put together a script that creates accounts in AD and assigns a bunch of info including group membership based on input from a CSV. I use the .Substring method to create a temporary password using parts of the new hire's name. But when I try to set the SamAccountName using the .Substring method to grab the first 20 characters of the username with the same syntax as when I set the password, I'm treated to errors.
Within the same New-ADUser command, why does the below set the password as the first character of their FirstName followed by the first character of their LastName just like I would expect
-AccountPassword (convertto-securestring($Firstname.Substring(0,1)+$Lastname.Substring(0,1))
-AsPlainText -Force)
While the below does not set the SamAccountName as the first 20 characters of the Username? I get errors no matter how I've tried to do it.
-SamAccountName ($Username.Substring(0,20))
Error below:
Exception calling "Substring" with "2" argument(s): "Index and length
must refer to a location within the string.Parameter name: length"At
C:\Create_AD_Users.ps1:28 char:7+
New-ADUser `+ ~~~~~~~~~~~~ + CategoryInfo :
NotSpecified: (:) [], MethodInvocationException +
FullyQualifiedErrorId : ArgumentOutOfRangeException
here's a demo of what i meant by using regex to grab UP TO the limit instead of trying to grab ALL the limit.
what the code does ...
creates an array of strings to work with
just use your own when you get ready to do this for real.
sets the max number of chars to capture
iterates thru the collection of strings
shows the original string
uses regex to capture up to $MaxChars from the string
if you want details on the exact working of the regex pattern, please go to ...
regex101: build, test, and debug regex
== https://regex101.com/
the box in the upper right will explain the meaning of any regex pattern you put into the box in the upper center.
displays that result
draws a divider that is 20 chars long
the code ...
#region >>> make some strings to work on
# the below strings are 29, 30, 20, and 10 chars long
$InStuff = #'
Abcdefghi_Bcdefghij_Cdefghijk
123456789_123456789_123456789_
Qwertyuio_Asdfghjkl_
123456789_
'# -split [System.Environment]::NewLine
#endregion >>> make some strings to work on
$MaxChars = 17
foreach ($IS_Item in $InStuff)
{
$IS_Item
$IS_Item -replace "^(.{0,$MaxChars}).*$", '$1'
# yes, you can multiply strings [*grin*]
'=' * 20
}
output ...
Abcdefghi_Bcdefghij_Cdefghijk
Abcdefghi_Bcdefgh
====================
123456789_123456789_123456789_
123456789_1234567
====================
Qwertyuio_Asdfghjkl_
Qwertyuio_Asdfghj
====================
123456789_
123456789_
====================

How to extract a certain part of a string in powershell

I want to extract the last 4 digits before ".txt" from this string:
09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK
Those represent the time at which that log was created and I want to display it as 10:58. I read from a file that has multiple lines similar to the one displayed.
Get-Content file.txt | ForEach-Object {
$splitUp = $_ -split "_"
$SC=$splitUp[2] -split "_"
Write-Host $SC
$len = $SC.Length
$folder2 = $SC.Substring($len - 12, 42)
}
I tried separating the string by "_" and then counting the characters in the obtained string and tried separating by the "Substring" command, but I receive the following error.
Exception calling "Substring" with "2" argument(s): "StartIndex cannot
be less than zero. Parameter name: startIndex"
At line:6 char:5
+ $folder2 = $SC.Substring($len - 12, 42)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : ArgumentOutOfRangeException
You can use a regex "lookahead".
What you are searching for is a set of four digits followed by ".txt":
$string = "09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK"
$regex = "\d{4}(?=\.txt)"
[regex]::matches($string, $regex).value
There's probably a more elegant solution:
$String = '09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK'
$String -Match '.*(?=\.txt)' | Out-Null
$Match = $Matches[0][-4..-1] -Join ''
$Time = [DateTime]::ParseExact($Match, 'HHmm',[CultureInfo]::InvariantCulture)
$Time.ToShortTimeString()
Uses RegEx to get all of the string before the .txt
Uses the Array Index to get the characters from 4th to last to the last character and joins them together as a single string.
Casts the value as a DateTime object using ParseExact to interpret it as 24 hour time code
Outputs the Short Date value of that DateTime object.
Just do it with Substring and IndexOf:
$string="09/14/2017 12:00:27 - mtbill_post_201709141058.txt 7577_Delivered: OK"
$string.Substring($string.IndexOf('.txt')-4, 4)

powershell search function with regular expression

the text file content is:
In this script, we have the following variables:
$input_path to hold the path to the input file we want to parse
$output_file to hold the path to the file we want the results to be stored in
$regex to hold the regular expression pattern to be used when the strings are being matched.
The select-string cmdlet contains various parameters as follows:
-Path which takes as input the full path to the input file
-Pattern which takes as input the regular expression used in the matching process
AllMatches which searches for more than one match (without this parameter it would stop after the first match is found) and is piped to $.Matches and then $_.Value which represent using the current values of all the matches.
Code:
$replace_file=#{}
$replace_text_file_path="EMS_checksystem_script\replace.txt"
$replace_file= gc $replace_text_file_path
$result=0
$valr=read-host "please enter the key word"
for($i=0;$i -lt$file_context.length;$i++)
{
$result=$replace_file[$i] -match $valr
if( $result -eq 1)
{
$replace_file[$i]
}
}
Result:
key word: *pression
Bad argument to operator '-match': parsing "*pression" - Quantifier {x,y} following nothing..
At line:11 char:37
+ $result=$replace_file[$i] -match <<<< '*pression'
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadOperatorArgument
key word: pression*
key word: press*on
NO result
How can use the press*on and *pression keywords to search?
Read up on regex. You can test regex here > http://www.regexr.com/
Your keyword is wrong, use "." to match any character and "*" to match any number of the previous character.
PS C:\>'expression' -match ".*pression"
PS C:\>True

Why doesn't $hash.key syntax work inside the ExpandString method?

The following Powershell script demonstrates the issue:
$hash = #{'a' = 1; 'b' = 2}
Write-Host $hash['a'] # => 1
Write-Host $hash.a # => 1
# Two ways of printing using quoted strings.
Write-Host "$($hash['a'])" # => 1
Write-Host "$($hash.a)" # => 1
# And the same two ways Expanding a single-quoted string.
$ExecutionContext.InvokeCommand.ExpandString('$($hash[''a''])') # => 1
$ExecutionContext.InvokeCommand.ExpandString('$($hash.a)') # => Oh no!
Exception calling "ExpandString" with "1" argument(s): "Object reference not set to an instance of an object."
At line:1 char:1
+ $ExecutionContext.InvokeCommand.ExpandString('$($hash.a)')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NullReferenceException
Anyone know why the $hash.key syntax works everywhere but inside explicit expansion? Can this be fixed, or do I have to suck it up and live with the $hash[''key''] syntax?
I use this method, since this bug exists in v4 (not in v5)
function render() {
[CmdletBinding()]
param ( [parameter(ValueFromPipeline = $true)] [string] $str)
#buggy
#$ExecutionContext.InvokeCommand.ExpandString($str)
"#`"`n$str`n`"#" | iex
}
Usage for your example:
'$($hash.a)' | render
The ExpandString api is not exactly meant for use from PowerShell scripts, it was added more for C# code. It's still a bug that your example doesn't work (and I think it's been fixed in V4), but it does mean there is a workaround - one that I recommend for general use.
Double quoted strings effectively (but not literally) call ExpandString. So the following should be equivalent:
$ExecutionContext.InvokeCommand.ExpandString('$($hash.a)')
"$($hash.a)"
I was trying to store text that prompts the user in a text file. I wanted to be able to have variables in the text file that are expanded from my script.
My settings are stored in a PSCustomObject called $profile and so in my text I was trying to do something like:
Hello $($profile.First) $($profile.Last)!!!
and then from my script I was trying to do:
$profile=GetProfile #Function returns PSCustomObject
$temp=Get-Content -Path "myFile.txt"
$myText=Join-String $temp
$myText=$ExecutionContext.InvokeCommand.ExpandString($myText)
which of course left me with the error
Exception calling "ExpandString" with "1" argument(s): "Object
reference not set to an instance of an object."
Finally I figured out I only needed to to store the PSCustomObject values I want in regular old variables, change the text file to use those instead of the object.property version and everything worked nicely:
$profile=GetProfile #Function returns PSCustomObject
$First=$profile.First
$Last=$profile.Last
$temp=Get-Content -Path "myFile.txt"
$myText=Join-String $temp
$myText=$ExecutionContext.InvokeCommand.ExpandString($myText)
And in the text I changed to
Hello $First $Last!!!

replace exception in powershell

I'm a beginner in powershell and know C# pretty well. I have this command http://www.f2ko.de/programs.php?lang=en&pid=cmd that downloads stuff. I'm writing this script to download all the sgf go games from this url http://www.gogameworld.com/gophp/pg_samplegames.php, and was trying to write a powershell script to do it for me. So I wrote a script:
Get-Content test.txt|
ForEach-Object
{
if($_ -eq "=`"javascript:viewdemogame(`'*.sgf`')`" tit")
{
$filename = $_ -replace '=`"javascript:viewdemogame(`''
$filename = $filename -replace '`')`" tit'
&"(Path)/download.exe" ("http://www.gogameworld.com/webclient/qipu/" + $filename)
}
}
However, when I run the script, I keep getting this error:
Unexpected token '`'' in expression or statement.
At (PATH)\test.ps1:7 char:37
+ $filename = $filename -replace '`' <<<< )'
+ CategoryInfo : ParserError: (`':String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
I've looked at the script lots of times and still can't figure out whats wrong. Thanks.
Try this, read the content of the file as one string and then use the Regex.Matches to get all occurrences of the text contained in the parenthesis:
$content = Get-Content test.txt | Out-String
$baseUrl = 'http://www.gogameworld.com/webclient/qipu/'
[regex]::matches($content,"javascript:viewdemogame\('([^\']+)'\)") | Foreach-Object{
$url = '{0}{1}' -f $baseUrl,$_.Groups[1].Value
& "(Path)/download.exe" $url
}
here's an explanation of the regex pattern (created with RegexBuddy):
javascript:viewdemogame\('([^\']+)'\)
Match the characters “javascript:viewdemogame” literally «javascript:viewdemogame»
Match the character “(” literally «\(»
Match the character “'” literally «'»
Match the regular expression below and capture its match into backreference number 1 «([^\']+)»
Match any character that is NOT a ' character «[^\']+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match the character “'” literally «'»
Match the character “)” literally «\)»
Match the character “"” literally «"»
'{0}{1}' is used with the -f operator to create a string. {0} maps to the first value on the right hand side of the operator (e.g $baseUrl) and {1} is mapped to the second value. Under the hood, PowerShell is suing the .NET String.Format method. You can read more about it here: http://devcentral.f5.com/weblogs/Joe/archive/2008/12/19/powershell-abcs---f-is-for-format-operator.aspx
'')" tit'
The -replace operator takes 2 arguments, comma separated. The first is a regular expression that matches what you want replaced. The second is the string you want to relace that with. You appear to be missing the second argument.