Powershell: Adding element to hashtable failed - powershell

PS C:\Users\Hind> $b=#{}
PS C:\Users\Hind> $b+={k="a";v="b"}
A hash table can only be added to another hash table.
At line:1 char:1
+ $b+={k="a";v="b"}
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : AddHashTableToNonHashTable
Why did it fail? How can I add one element to a hashtable successfully?

Correction, this fails because you are missing the # character in front of #{k="a";b="b"}
PS C:\Users\Hind> $b=#{}
PS C:\Users\Hind> $b+=#{k="a";v="b"}
#{} is declaring a new hash table. {} is a script block. They are not the same.

Initialising the hashtable should be with round bracket instead of curly brackets
$b=#()
$b+=#{k="a";v="b"}

Related

Add xml object to xml file in PowerShell

I am trying to create an RDCMan file (.rdg xml file) using PowerShell. I have started by defining this template
$newFileTemplate = '<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
<file>
<properties>
<expanded>False</expanded>
<name>Office Servers</name>
</properties>
<displaySettings inherit="None">
<liveThumbnailUpdates>True</liveThumbnailUpdates>
<allowThumbnailSessionInteraction>False</allowThumbnailSessionInteraction>
<showDisconnectedThumbnails>True</showDisconnectedThumbnails>
<thumbnailScale>1</thumbnailScale>
<smartSizeDockedWindows>True</smartSizeDockedWindows>
<smartSizeUndockedWindows>False</smartSizeUndockedWindows>
</displaySettings>
</file>
</RDCMan>
'
before creating an xml object like so
$File = 'D:\Test.rdg'
Set-Content $File $newFileTemplate
[XML]$XMLFile = [XML](Get-Content $File)
I would then like to define a function for adding a group of servers
# This function adds a new group element
Function Add-NewGroup($GroupName,$RDCManFile) {
[xml]$GroupXML = #"
<group>
<properties>
<expanded>False</expanded>
<name>$GroupName</name>
</properties>
</group>
"#
$Child = $RDCManFile.ImportNode($GroupXML.group, $true)
$RDCManFile.Configuration.AppendChild($Child)
}
And call it by running
Add-NewGroup('DCs',$XMLFile)
This would allow me to populate the xml file with all of the OUs in AD.
Is anyone able to tell me where I am going wrong?
Thanks
Update: The error I am getting is
You cannot call a method on a null-valued expression.
At D:\Users\user\Desktop\Projects\RDCMan\Create-RDG.ps1:179 char:5
+ $Child = $RDCManFile.ImportNode($GroupXML.group, $true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At D:\Users\user\Desktop\Projects\RDCMan\Create-RDG.ps1:180 char:5
+ $RDCManFile.Configuration.AppendChild($Child)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
And I am trying to do what was suggested here https://stackoverflow.com/a/29693625/2165019
The property 'Configuration' cannot be found on this object. Verify that the property exists. error at $RDCManFile.Configuration.AppendChild($Child).
If I can accept a .rdg file format and structure as defined in the Script to create a Remote Desktop Connection Manager group from Active Directory Technet article then I'd use
$RDCManFile.RDCMan.file.AppendChild($Child)
Follow the Theo's answer about calling a function.
Pass parameters as positional
Add-NewGroup 'DCs' $XMLFile
or as named
Add-NewGroup -GroupName 'DCs' -RDCManFile $XMLFile
This error (and second) most likely means that $RDCManFile is null.
You cannot call a method on a null-valued expression.
At D:\Users\user\Desktop\Projects\RDCMan\Create-RDG.ps1:179 char:5
+ $Child = $RDCManFile.ImportNode($GroupXML.group, $true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Try adding $RDCManFile | Out-Host at the top of the Add-NewGroup function to check what's contained in that variable.
You need to change the way you are calling the function.
Because of the comma in between the parameters, PowerShell sees this as one array value, so only parameter $GroupName will receive something.
Furthermore, you should not use brackets around the params, call the function like this:
Add-NewGroup 'DCs' $XMLFile
or send the parameters using their names:
Add-NewGroup -GroupName 'DCs' -RDCManFile $XMLFile

How to set environment variable with dot in name using powershell?

I want to set environment variable in powershell that has dot in name.
This line throws an error:
$env:Test.Env.Var1 = "test111"
The property 'Var1' cannot be found on this object. Verify that the property exists and can be set.
At line:1 char:1
+ $env:Test.Env.Var1 = "test111"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Is it possible to set "Test.Env.Var1" variable without using [Environment]::SetEnvironmentVariable method?
This can be done by
${env:test.value} = 'value'
Note the colon after env. This works in both powershell and pwsh
Cf. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables?view=powershell-7.2#variable-names-that-include-special-characters
It can be done by
${env:Test.Env.Var1} = 'value'
source
Thanks to #4c74356b41 who provided answer in comment.

PowerShell 'Invoke-Expression' command with single quotation

I am trying to invoke the following the command which contains the single quotation, but I am not able to execute and returns as an error:
$expression = $snapshot.properties.activities[1].typeProperties.parameters.rawinputlocation = '$$Text.Format(`'wasb://document.blob.co
re.windows.net/{0:yyyy}/{0:MM}/{0:dd}/DocumentActivity/raw/{{*}}.csv'`, SliceEnd)'
Invoke-Expression $expression
Error:
Invoke-Expression $expression
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException
FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand
This happens as the single quote, ', is escaped with a backtick, `.
The first one works, but the latter one is in the wrong order: the backtick is after the single quote. Consider the difference:
`'wasb://...csv'`
`'wasb://...csv`'

How to execute PowerShell Net MessageBox in cmd/batch

I have a batch file with lot of stuff. I there is one Alert Window with info for user.
On Windows Pro I'm using Msg command for it and it works fine.
On Windows Home there is no Msg, so I got the idea to use PowerShell instead:
[System.Windows.Forms.MessageBox]::Show("my text")
which works fine in PowerShell.
-However, when I try to use it in batch or execute it directly in Cmd, I only get the text:
C:\Windows\System32>powershell {[System.Windows.Forms.MessageBox]::Show("\""my text"\"")}
[System.Windows.Forms.MessageBox]::Show("my text")
Or I get errors:
C:\Windows\System32>powershell -command [System.Windows.Forms.MessageBox]::Show("my text")
At line:1 char:41
+ [System.Windows.Forms.MessageBox]::Show(my text)
+ ~
Missing ')' in method call.
At line:1 char:41
+ [System.Windows.Forms.MessageBox]::Show(my text)
+ ~~
Unexpected token 'my' in expression or statement.
At line:1 char:48
+ [System.Windows.Forms.MessageBox]::Show(my text)
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
or
C:\Windows\System32>powershell -command "& {[System.Windows.Forms.MessageBox]::Show('my text')}"
Unable to find type [System.Windows.Forms.MessageBox].
At line:1 char:4
+ & {[System.Windows.Forms.MessageBox]::Show('my text')}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Windows.Forms.MessageBox:TypeName) [],
RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
What should I do to get it to work?
(without rewriting the whole script to PowerShell, that is)
As TheMadTechnician stated, you may need to load it first.
This is effectively the same answer as theirs just over a couple of lines:
#Echo Off
PowerShell -Command^
"[Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')|Out-Null;"^
"[System.Windows.Forms.MessageBox]::Show(\"my text\")"
Pause
…and whilst double quotes around my text is not necessary, I've used them to show you the escapes.
You need to load the type before you can invoke it. You can do this:
powershell -command "[reflection.assembly]::LoadWithPartialName('System.Windows.Forms')|out-null;[windows.forms.messagebox]::Show('my message')"

Return value of environment variable with powershell

I have the name of an environment variable in a variable and I want to get the value. How do I do that? I've tried:
PS C:\Users\Joe> $v="USERDOMAIN"
PS C:\Users\Joe> "$env:$v"
At line:1 char:2
+ "$env:$v"
+ ~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidVariableReferenceWithDrive
PS C:\Users\Joe> "$env:$($v)"
At line:1 char:2
+ "$env:$($v)"
+ ~~~~~
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to
delimit the name.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidVariableReferenceWithDrive
Two lines
$v = "Path"
(get-item env:$v).Value
One line
iex ('$env:' + $x)
To complement Vladimir's helpful answer with a solution that makes direct use of the .NET framework:
$v="USERDOMAIN"
[Environment]::GetEnvironmentVariable($v)