PowerShell: using #{Add=''} sometimes work and sometimes it does not - powershell

When an object can have multiple values on an object like, I use most of the time:
-Object #{Add=''} or -Object #{Remove=''}. But I notice that this not works all the time, than you need to set all the values because other wise it replaces the existing values.
For example, when I use:
Set-Mailbox "Contoso Executives" -GrantSendOnBehalfTo #{Add='tempassistants#contoso.com','tempassistants#contoso.com'}
The #{Add=''} is working. But when I use:
Set-RetentionPolicy "MRM Policy" -RetentionPolicyTagLinks #{Add='tag1','tag2'}
I get the following error:
Cannot convert value "System.Collections.Hashtable" to type
Why does this happens? RetentionPolicyTagLinks can have multiple values in the same way as GrantSendOnBehalfTo can have.

Your issue is within the format of your RetentionPolicyTagLinks parameter.
Try the documentation below to help you with storing it in a variable first:
https://learn.microsoft.com/en-us/exchange/add-or-remove-retention-tags-exchange-2013-help

Related

Powershell - Hashtable in Foreach statement

I'm looking to get an idea of how to go about this.
In a for each loop. Do you need to define the variables before using them in a hash table for TITLE,DEPARTMENT,MANANGER,OFFICE
Currently, this does not set anything for the users in the foreach statement.
Foreach ($userdata in $datafile) {
$SetADUserdetails = #{
Identity=$userdata.Adusername
Title = $userdata.title
Office=$userdata.office
Department=$userdata.department
Manager=$userdata.manager
}
Set-ADUser #SetADUserdetails # Need to add Domain Controller Parameter
}
This is how the datafile looks like.
GivenName,Surname,Office,Title,Path,Manager,Department,Adusername
I'm sure if I set the variable first and then match the variable to hash table keys, it going to work.
Please let me know your thought. I'm fair new to PowerShell. I tried searching the internet for the correct method. No luck. just want to double-check before I define variables.
Yes, variables are rendered at runtime. When you define the hashtable the key will have the variable assigned at the time the hashtable was defined, or the last value that was set for that key with =.
In your code example, the keys of $SetADUserdetails have no value because the $userdata Properties have no value. Make sure that $datafile has the correct entries you are expecting and confirm each iteration of $userdata has some value. Either $datafile is incorrect or you are referencing each column by the wrong column name.

Is there a way to make a Powershell function ignore a default parameter's value if its parameter set is not in use?

I understand from this answer that when you have default parameters and multiple parameter sets in a Powershell function, the default parameter values will be instantiated even if the parameter set in use is not the one in which they are inserted.
Is there a way to avoid this?
For example, in the function below, assuming that there is a really expensive calculation used to compute the default value of $FirstParameter, I would like to avoid using it when it is not necessary:
function PrintStuff {
[CmdletBinding(DefaultParameterSetName='FirstSet')]
Param(
[Parameter(ParameterSetName='FirstSet')]
[String]$FirstParameter=(ReallyExpensiveFunction),
[Parameter(ParameterSetName='SecondSet')]
[String]$SecondParameter
)
if (-not ($FirstParameter -eq $null)) {Write-Host $FirstParameter}
Write-Host "$($PSCmdlet.ParameterSetName)"
}
function ReallyExpensiveFunction {
# Very expensive calculation
"I Am First"
}
However, at the moment running it would still give me the results below:
PS C:\> PrintStuff
# I Am First
# FirstSet
PS C:\> PrintStuff -SecondParameter "don't print this"
# I Am First
# SecondSet
As per above, when SecondSet is used $FirstParameter is still being defined. Is there a way to get only SecondSet printed when the second parameter set is used?
Bear in mind, I am looking to find out if there is a solution which would allow me to keep ReallyExpensiveFunction as the default value for $FirstParameter, and avoid solutions which would involve transferring the logic to the body of the function, such as:
...
Param(
[Parameter(ParameterSetName='FirstSet')]
[String]$FirstParameter,
...
)
if ($PSCmdlet.ParameterSetName -eq 'FirstSet' -and ($FirstParameter -eq '')) {
$FirstParameter = ReallyExpensiveFunction
}
...
Sorry if the pitch is too specific, but I am curious to find out if this is possible.
Unfortunately, the answer is no. ParameterSet allows to present a simpler interface to user for complex argument sets by filtering out the non-relevant ones. However, PowerShell goes through each parameter, whether it is in the selected parameterset or not and assign the default value to the parameter, if you specify one. So, simply put in the context of your question, ParameterSet may be thought as just a filter for presentation.

Powershell Parameter passing issue

I have a strange one I have searched the existing Q&A and haven't found a match.
I have written my functions using parameter validation using the basic format
function FunctioName
{
[CmdletBinding()]
Param(
[parameter(Mandatory)]
[String]$VariableName
)
When I set the parameter to Mandatory as above I get a parameter binding exception indicating a null value was passed. Running the script in debug I can see the function parameter being passed is not null and is a valid string.
When I run the script in the exact same way without the mandatory flag the string is passed into the function and it executes correctly.
Has anyone got any ideas, what could be the issue. This problem is affecting a number of functions in my application interestingly it appears that the affected functions all have only a single parameter functions with multiple parameters do not appear to be affected.
Ok thanks guys for your feedback its much appreciated. BTW i am using powershell 5 .
Further to the issue, looking into it further I found that the variable was being passed to the function as an array of strings, however an empty string value was being appended into the array which I believe was the cause for the issue. This is where it starts to get interesting, I will need to give a bit more background.
The script I am running queries active directory for user attributes meeting specific conditions, those that match I create an array of strings with each value a delimited value of the user,hostname and other attribute properties.
To ensure that I am getting the latest values I use the ASDI GetInfo method,which seems to trigger the odd behavior.
At a high level the functions are
Function GetuserAttr
{
$inscopeusers = New-Object System.Collections.ArrayList
$accountlist = (Get-ADUser -Filter { attribute1 -eq "value"} -Properties attribute1).SamAccountName
foreach ($user in $accountlist)
{
$DN = getDN($user) # basically a funtion I wrote to create ASDI object for user account.
$DN.GetInfo() # this method call appears to cause issues
$attr1 = $DN.Get("Attribute1")
$attr2 = $DN.Get("Attribute2")
$hoststring = "$($user)|$($attr1)|$($attr2)"
$inscopeusers.Add($hoststring) > null
}
return $inscopeusers
}
The string array returned in this function is fed into a number of other functions, one of which is the one that was giving the error that I originally brought up.
The thing is when I use the GetInfo method the array returned by this function contains several null values in the array, when I remove the command the array has no null strings.
Even more strange when I am operating on the array in other functions it appears that the array looses some of its properties when the GetInfo method is used. So for instance I am able to use the foreach loop to iterate through array values but I cannot access an array value by index such as $array[1].
By simply commenting out the GetInfo method call in the function the array returned seems to function normally and you can access array values by index.
I have another function that also uses GetInfo and returns a hash table, when I try to operate on the returned hashtable I cannot access values using a key value such as $hashtable['key'], but I can access them using $hashtable.key. I know this is really weird and can't really think what it could be
Has any one else experienced a similar problem.
You're missing an argument.
Function Test
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[String]
$Variable
)
Write "$Variable"
}

Modifying Many Custom PowerShell Objects

I have a list of several thousand custom PS Objects that are exported from another system, and all these custom objects are in a variable $queryResult. The system exports these objects with a field time that is in epoch time format in milliseconds (example: 1492536777453 = Tuesday, April 18, 2017 1:32:57 PM) . I need to change all of these time fields in the custom objects into human readable times. I already have a function that converts epoch time to human readable:
Function Convert-FromUnixDate ($UnixDate) {[timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddMilliSeconds($UnixDate))}
I also figured out how to convert all of them, however this just returns a list of times(obviously), and I can't figure out how to update the actual custom objects:
foreach ($i in $queryResult.events.time){$humanReadable = #{};Convert-FromUnixDate $i}
My problem is I want to update the actual value in each PS custom object so that, when I export all the objects to an excel file for the end user, they are readable. Your help is very much appreciated!
EDIT
I forgot to mention what happens when I try to update the values. I tried this statement below:
$aqlQueryResult.events.starttime = Convert-FromUnixDate ($aqlQueryResult.events.starttime)
When I try that, I receive the following error:
Cannot convert argument "value", with value: "System.Object[]", for
"AddMilliseconds" to type "System.Double": "Cannot convert the
"System.Object[]" value of type "System.Object[]" to type "System.Double"."
I understand that I'm receiving this error because my conversion function expects a double, but how can I either change this to expect the correct data type, or find another way to do this?
So with a bit of help from #FrodeF and #sodawillow, I have figured out how to update the values inside the actual objects! Below is the line I needed to add.
$queryResult.events | ForEach-Object {$_.time = (Convert-FromUnixDate ($_.time))}

Get binary data from registry key

I am trying to get the data from each registry entry into a variable in Powershell. I have a For statement that allows me to parse through the names, with another For statement under it that parses through the properties. Where I am stumped is how to get the actual binary value for the property? I don't see, or am overlooking something.
For the Names, I use Key[$i]. For the properties, I use $Key[$i].Property[$count]. How do I get the binary value for $Key[$i].Property[$count]? Thanks
You could simply use the GetValue() method.
$Key[$i].GetValue($Key[$i].Property[$count])
I usually use Get-ItemProperty to get registry values -
$key_path = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Font Management'
(Get-ItemProperty -Path $key_path)."Active Languages"