Powershell - Hashtable in Foreach statement - powershell

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.

Related

Using Powershell and HTMLBody.Replace how do I replace values inside an existing table?

I have an existing email template file for Outlook with To, CC, Subject and Body prefilled.
I can replace the values I need on the subject just fine, however, when it comes to the HTMLBody part, it only replaces values outside the table; I've tested this by putting all 15 placeholders outside the table.
In Powershell, I defined an array with the items that will be replaced and another that reads the values from a JSON file, then I loop through both in order to replace the values on the HTMLBody.
This is the code in question:
$emailToreplaceValues=#(
"[DailyReportDate]",
"[DailyReportSuccess]",
"[DailyReportFailure]",
"[DailyReportFailureRate]"
)
$newValues=#(
$valuesJSON.DailyReport.Date,
$valuesJSON.DailyReport.Success,
$valuesJSON.DailyReport.Failure,
$dailyReportFailureRate
)
$reportEmail = $outlookObj.CreateItemFromTemplate("$emailTemplate")
$reportEmail.Subject = $reportEmail.Subject.Replace("[date]", $date)
for($i=0;$i -le $newValues.Count;$i++) {
$reportEmail.HTMLBody = $reportEmail.HTMLBody.Replace($emailToreplaceValues[$i], $newValues[$i])
}
There's more values but for the sake of brevity, I only included a few of the values, from my understanding, the issue is that some of those values are inside a HTML table cell but I don't know if I can access the table or cells directly.
Firstly, do not use MailItem.HTMLBody property as variable - it is expensive to set and read, and it might not be the same HTML you set as Outlook performs some massaging and validation. Introduce an explicit variable, set it to the value of HTMLBody, do all your string replacements in a loop using that variable, then set the MailItem.HTMLBody property once.
You can also try to output the value of that variable to make sure the old values to be replaced are really there and are not broken by HTML formatting or encoding.
For the sake of future reference, the only way I was able to fix this, was by grabbing the html code off the email that I based my email template off.
I organized it so that any tags I want replaced are in their own line without anything else other than the spaces for indentation, then defined it as a variable that goes through the replace cycle and gets assigned to the MailItem.HTMLBody property after the replace cycle.

Powershell - changing value of returned SQL data variable fails

In Powershell, I am doing a SQL query for a single row of data. Lets say $data for example.
The response from the query a System.Data.DataSet type. Within it, there is a tables property that has the data I need.
$data.Tables
ServerName : Server15
SamAccount : Admin-Server15
LastPWDReset : 1/15/2019 12:00:00 AM
LastPWDResetAttempt :
I don't intend to write this data back out of anything. Instead, I want to display it, and convert the empty "LastPWDResetAttemp" to "NONE" where it is blank.
I thought it would be done like this:
$data.Tables.lastPWDResetAttempt = "None"
but that gives me an error The property 'lastPWDResetAttempt' cannot be found on this object. Verify that the property exists and can be set.
I can't help but think I am missing some conversion from "Dataset" to "String".
I've tried to-string but in doing so, I ended up with just a string of data and not the headings. Nothing I could update, or easily use to build my eventual table.
My work around:
$webdata = "" | select ServerName,SamAccount,LastPWDReset,LastPWDResetAttempt
$webdata.ServerName = $data.tables.servername
$webdata.SamAccount = $data.tables.samaccount
$webdata.LastPWDReset = $data.tables.LastPWDReset
$webdata.LastPWDResetAttempt = $data.tables.LastPWDResetAttempt
$webdata.LastPWDResetAttempt = "Never"
works. I just can't believe there isn't an easier way, nor do I understand why I can view a list of the data, just to not then be able to set it.
I think it is because Tables is an array and does not have the property LastPWDResetAttempt.
You can try the following instead:
$data.Tables[0].Rows[0].LastPWDResetAttempt = "None"
Also I think your workaround, though it may contain more lines of code, is actually a better solution though.

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"
}

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"

How to edit a PowerShell array item returned by a search?

I am trying to change a value of a specific item in a hash table. I can do this by iterating through the entire object, testing every single key for a specific value, then changing it if the condition is met like so:
for ($i=0; $i -le $haystack.length-1; $i++)
{
if ($haystack[$i].name -eq "needle")
{
$haystack[$i].currentstatus = "found"
}
}
The above code works but it seems like there has to be a more efficient way to accomplish the task especially when the haystack is large and there is only one needle.
I tried to use where-object and can find the record I'm looking for:
$haystack | where-object {$_.name -eq "needle"}
This seems much better than doing a brute force search but I do not know how to get at that record now. If I had the index in the array then I can easily use that to edit the value I want so is there a way to get the array index? How is this usually done? Thanks.
If you control the creation of $haystack, and $haystackitem.name is always unique, I would suggest creating a hashtable with Name as the index.
If either of the above conditions are not true, you could speed things up a bit by use foreach ($object in $collection) {} instead. You don't need the index to the object because the objects will be passed by reference. Any changes you make to the object will be seen within the array.
But the best performance would be to create some managed code to sort the array and use an effective search algorithm. But that would be more work.
Where object does a for each any way and has to since it returns all items that match your test condition. The generic use case for a hash is to have a key which you can use to effectively find your object if you are having to iterate perhaps you have chosen a poor key.
You can iterate through the array and retrieve the index for a particular 'name' property value in the array by doing something similar the following:
$index = 0..($haystack.Count - 1) | Where {$haystack[$_].name -eq 'needle'}