Can't rename item in powershell because it's null - windows

qqq.exe exists.
$DB is correct, I use it other times just fine.
$DB = Get-Content C:\Users\asd\Desktop\Farm\AccountList.txt
foreach ($x in $DB){
Rename-Item C:\Users\asd\Desktop\Farm\$x\qqq.exe $x.exe
}
Rename-Item : Cannot bind argument to parameter 'NewName' because it is null.
At C:\Users\asd\Desktop\Farm\test2.ps1:3 char:57
+ Rename-Item C:\Users\asd\Desktop\Farm\$x\qqq.exe $x.exe
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [Rename-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RenameItemCommand

When the powershell parser sees an argument starting with a $, it treats it as an expression, meaning that it will try to evaluate it as code.
Since the string $x doesn't have a property named exe, the expression results in $null and Rename-Item throws the error you see.
If you use a double-quoted string instead, the parser will stop evaluating $x after the dot:
Rename-Item C:\Users\asd\Desktop\Farm\$x\qqq.exe "$x.exe"
From Get-Help about_Parsing:
When processing a command, the Windows PowerShell parser operates
in expression mode or in argument mode:
- In expression mode, character string values must be contained in
quotation marks. Numbers not enclosed in quotation marks are treated
as numerical values (rather than as a series of characters).
- In argument mode, each value is treated as an expandable string
unless it begins with one of the following special characters: dollar
sign ($), at sign (#), single quotation mark ('), double quotation
mark ("), or an opening parenthesis (().

Related

Powershell - Can't unlock BitLocker as 256 characters long password contains special characters with single double quotes

Here's the background and I have no clue beyond this so tell me how to move ahead from this!
PS C:\> $SecureString = ConvertTo-SecureString "fjuksAS1337" -AsPlainText -Force
PS C:\> Unlock-BitLocker -MountPoint "E:" -Password $SecureString
My password here is:
cF;TA" X%jl"\G{d}rcVzNI=Inps#|P,o{~"k<+#?bm)PjQf^\c8EB! (cL.ZyA.v/yYQ#,!#gN'%"VwlNFs)(h\1Uf#cFdr7BU%zDA;&2R_3w3C3td-Nm,^VFE$cF>N{ol0Y~qR2i`Vm%Q#ckh0]#ZE!ijnirg5k?bj\L;88wBhg8QqO^/T64D#O6Q'H"")/I5(d4v7RC`jH=JH+,Zy*TY4MEf~.b7?;';zLEmB>F^S7aBrUfnN&(Vuhjw}Z3w5
As you see it has multiple single and double quotes which breaks the SecureString command output getting nowhere.
I need to use this password in order to unlock BitLocker drive as the UI throws wrong password error and recovery password of 48 digits is unfortunately lost!
Please help as I am having no idea here at all!
Use a single-quoted here-string.
Anything you put in there won't be escaped in any way.
Example
$PlainTextPassword = #'
cF;TA" X%jl"\G{d}rcVzNI=Inps#|P,o{~"k<+#?bm)PjQf^\c8EB! (cL.ZyA.v/yYQ#,!#gN'%"VwlNFs)(h\1Uf#cFdr7BU%zDA;&2R_3w3C3td-Nm,^VFE$cF>N{ol0Y~qR2i`Vm%Q#ckh0]#ZE!ijnirg5k?bj\L;88wBhg8QqO^/T64D#O6Q'H"")/I5(d4v7RC`jH=JH+,Zy*TY4MEf~.b7?;';zLEmB>F^S7aBrUfnN&(Vuhjw}Z3w5
'#
$SecureString = ConvertTo-SecureString $PlainTextPassword -AsPlainText -Force
For a quick reference:
# verbatim string. Nothing get processed. Single-quotes within the string need to
# be doubled down.
$sq = 'Hello '' world.'
# Expandable string. Stuff that can be expanded will be.
# Double-quotes within the string need to be doubled down or preceded by a backtick `
$dq = "Hello `" "" world"
# verbatim here string. single-quotes within the string do not need to be escaped
# This is the way to go for multiline strings
$sqh = #'
Hello ' World
'#
# Expandable here string. Double quotes within the string do not need to be escaped.
# This is the way to go for multiline strings
$dqh = #"
Hello " World
"#
Reference
About_Quoting_Rules

Windows Powershell script to find and replace a string after a particular string

I am currently working to convert AS3 class to JavaScript using Powershell script.
Below is the sample code needs to be converted.
package somePackageName
{
class someClassName
{
// other codes
}
}
I need the entire package block to be removed and "class someClassName{" should be converted to "function someClassName(){".
The "someClassName" can be any string.
And I need the output like this.
function someClassName()
{
}
This is what I tried.
$l1 = Get-Content $dest | Where-Object {$_ -like 'class'}
$arr = $l1 -split ' '
$n1 = "function "+ $arr[1] + "() " +$arr[2]
(Get-Content $dest) -creplace $l1, $n1 | Set-Content $dest
I can able to achieve what I intended if the opening brace is in same line as the package declaration line. As Powershell checks line by line, I am stuck if the opening brace present in next line.
Regex based solution
Depending on your willingness to post process this or accept leading spaces you could use this regex to remove the block outside of the class and replace with a function declaration. This is messier than it needs to be but safer since we cannot guess what // other codes is. You could just match the whole class block outright but if there are other curly braces in there it would muddy the regex.
PS M:\> (Get-Content -Raw $dest) -replace "(?sm).*?class (\w+)(.*)}",'function $1()$2'
function someClassName()
{
// other codes
}
See Regex101 for more detail on what the regex is doing.
Basically dump everything until the word class (first time). Then keep everything until the last closing brace
Note the leading space in the greater portion. This is honoring the existing space. To account for this we need to calculate the indentation. Simply removing all leading space would break existing indentation in the class/function.
So a solution like this might be preferred:
# Read in the file as a single string
$raw = (Get-Content -Raw $dest)
# Using the line that has the class declaration measure the number of spaces in front of it.
[void]($raw -match "(?m)^(\s+)class")
$leadingSpacesToRemove = $Matches[1].Length
# Remove the package block. Also remove a certain amount of leading space.
$raw -replace "(?sm).*?class (\w+)(.*)}",'function $1()$2' -replace "(?m)^\s{$leadingSpacesToRemove}"
Less regex
Seems filtering the lines with no leading spaces is an easy way to narrow down to what you want.
Get-Content $dest | Where-Object{$_.StartsWith(" ")}
From there we still need to replace the "class" and deal with the leading spaces. For those we are going to use similar solutions to what I showed above.
# Read in the file as a single string. Skipping the package wrapper since it has no leading spaces.
$classBlock = Get-Content $dest | Where-Object{$_.StartsWith(" ")}
# Get the class name and the number of leading spaces.
$classBlock[0] -match "^(\s+)class (\w+)" | Out-Null
$leadingSpacesToRemove = $matches[1].Length
$className = $matches[2]
# Output the new declaration and the trimmed block.
# Using an array to start so that piping output will be in one pipe
#("function $className()") + ($classBlock | Select -Skip 1) -replace "^\s{$leadingSpacesToRemove}"
Both solutions try to account for your exact specifications and account for the presence of weird stuff inside the class block.
I'd suggest using regex:
#class myclass -> function myclass()
#(Get-Content $dest) -creplace 'class\s(.+)', 'function $1()' |
Set-Content $dest
This will capture the class declaration and replace it with a backreference to the class name capture.

Execute cmdlet through variable?

I want to use an if \ else statement to determine which cmdlet to run while keeping the same params for both commands:
For example I have this call:
New-AzureRmResourceGroupDeployment `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
But I want to use a variable to determine the verb:
$myVerb = if ($booleanTest) {"Test"} else {"New"}
[$myVerb]-AzureRmResourceGroupDeployment `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
OR something like this:
$command = if ($booleanTest) {"Test-AzureRmResourceGroupDeployment"} else {"New-AzureRmResourceGroupDeployment"}
$command `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
I tried the $command version but it failed with this:
At
C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d
eploy.ps1:36 char:13
+ -ResourceGroupName $ResourceGroup
+ ~~~~~~~~~~~~~~~~~~ Unexpected token '-ResourceGroupName' in expression or statement. At
C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d
eploy.ps1:36 char:32
+ -ResourceGroupName $ResourceGroup
+ ~~~~~~~~~~~~~~
To do exactly what you are describing you'd need to wrap the whole command as a string and then call it with Invoke-Expression. For Example:
$MyCommand = "$myVerb-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroup -TemplateFile $TemplateUri"
Invoke-Expression $MyCommand
But I think this isn't a very clear way to write a script. A better option would be to use Splatting, which is where you create a hashtable of the parameters that you can then send the cmdlet via a special # character with the variable name. For example:
$AzureParams = #{
ResourceGroupName = $ResourceGroup
TemplateFile = $TemplateUri
TemplateParameterFile = $TemplateParamFile
}
If ($booleanTest) {
Test-AzureRmResourceGroupDeployment #AzureParams
} Else {
New-AzureRmResourceGroupDeployment #AzurParams
}
This also has the benefit of avoiding using the backtick character, which is generally encouraged as it's hard to spot and easy to break.
I don't recommend using this over the other answer but to directly answer your question, add the invocation operator &
$command = if ($booleanTest) {
"Test-AzureRmResourceGroupDeployment"
} else {
"New-AzureRmResourceGroupDeployment"
}
& $command `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
To complement the existing helpful answers:
Invoke-Expression should always be the last resort and is not needed here. With Invoke-Expression, it is tricky to get the quoting right, and its use can be a security risk (execution of arbitrary commands passed as a string, analogous to eval in POSIX-like shells).
Splatting (Get-Help about_Splatting) is always worth considering:
it is a more robust alternative to multi-line parameter-passing with line continuations, as Mark's answer explains.
it allows incremental, conditional construction of the set of parameter values as well as their use in multiple invocations.
In the case at hand, however, since only the command name is variable, Patrick's answer based on &, the call operator is simplest (see Get-Help about_Operators).
Generally, you need & whenever the command name is not an unquoted literal (e.g., notepad foo.txt works, but 'notepad' foo.txt doesn't).
To put it differently: you need &, if your command name is:
in quotes (whether '...' or "..."); e.g., 'notepad'
or is a variable reference; e.g., $cmdName
or is the result of an expression (e.g., ('get' + '-item')
& is needed in theses case in order to tell PowerShell that your intent is to invoke a command as opposed to evaluating an expression; without &, such tokens would be interpreted as starting an expression; see Get-Help about_Parsing to learn about PowerShell's two fundamental parsing modes, argument mode and expression mode.
While it may not be the most readable solution, you can therefore even combine an expandable string with an embedded subexpression ($(...) - again, see Get-Help about_Operators) to get away without the need for an aux. variable:
& "$( if ($booleanTest) {'Test'} else {'New'} )-AzureRmResourceGroupDeployment" `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
Using Splatting as suggested by Mathias R. Jessen:
Function Do-AzureRmResourceGroupDeployment ([ValidateSet("Test", "New")]$Verb, $ResourceGroupName, $TemplateFile, $TemplateParameterFile) {
$PSBoundParameters.Remove("Verb")
& "$Verb-AzureRmResourceGroupDeployment" #PSBoundParameters
}

How to replace a backslash CR LF with a <br> with powershell

I've tried many combinations of attempting to replace a "\ cr lf" with an html "br" tag after "foo".
My input file (tempA.txt) looks like this (there is a cr lf at the end of line 1 after the slash):
foo\
bar
I'm using a powershell command (within a bat file) like this:
type c:\temp\tempA.txt
powershell -Command "(gc c:\temp\tempA.txt) -replace '\\`r`n', '<br>' | Out-File c:\temp\tempB.txt"
type c:\temp\tempB.txt
My output file (tempB.txt) isn't changing. I want the output file to contain
foo<br>bar
How do you replace the "\ cr lf" with a simple html "br" tag?
Change your first -replace operator arg to use a double quoted string:
... -replace "\\`r`n", '<br>'
A single quoted string in PowerShell is a literal string so the backtick doesn't work to escape characters.
Get-Content will split your file into an array of lines. Based on this, you can just replace \ with <br> and join the lines together.
(gc c:\temp\tempA.txt) -replace '\\', '<br>' -join '' | Out-File c:\temp\tempB.txt

Writing tabs to a file using PowerShell

I need to echo a series of elements of an array in PowerShell, but provide various delimiters between the elements, so I'm using;
Add-Content -Path $tempInputDir\testoutput.log -value ($($fields[0]) + " "+
$($fields[1]) + " " + $($fields[2]) + " " + $($fields[3]) + " "+
$($fields[15]) + " " + $($fields[17]))
}
I need to be able to add tabs and space characters, as you can see from the code above I've just done this by physically adding tabs and spaces in between double quotes, but I'm sure this will cause problems down the line.
What's the correct way to echo these characters to a file? I read somewhere that "'t" could be used, but that doesn't seem to work?
You can use `t for a tab character in a double quoted string. You can also simplify the above to:
"$($fields[0]) $($fields[1]) $($fields[2]) $($fields[3]) $($fields[15]) $($fields[17])" | Add-Content $tempInputDir\testoutput.log
To join the nominated fields together with tabs:
[string]::join("`t", (0..3,15,17 | % {$fields[$_]}))

Resources