Modifying Many Custom PowerShell Objects - powershell

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

Related

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

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

Using the toInteger function with locale and format parameters

I've got a dataflow with a csv file as source. The column NewPositive is a string and it contains numbers formatted in European style with a dot as thousand seperator e.g 1.019 meaning 1019
If I use the function toInteger to convert my NewPositive column to an int via toInteger(NewPositive,'#.###','de'), I only get the thousand cipher e.g 1 for 1.019 and not the rest. Why? For testing I tried creating a constant column: toInteger('1.019','#.###','de') and it gives 1019 as expected. So why does the function not work for my column? The column is trimmed and if I compare the first value with equality function: equals('1.019',NewPositive) returns true.
Please note: I know it's very easy to create a workaround by toInteger(replace(NewPositive,'.','')), but I want to learn how to use the toInteger function with the locale and format parameters.
Here is sample data:
Dato;NewPositive
2021-08-20;1.234
2021-08-21;1.789
I was able to repro this and probably looks to be a bug to me . I have reported this to the ADF team , will let you know once I hear back from them . You already have a work around please go ahead that to unblock yourself .

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.

Arguments passed byReference and/or mutable constant issue

Not sure how I can do a minimal working code example here, but I will at least try to explain what is going on.
I have a utility that processes some text files to extract data, and then provides that data back in various ways depend on commend line options and some data in an XML file. There is a variety of "Processes" I could look for in the data, and I can output the final data in one or more formats (txt, csv, xml), with potentially different "Processes" being output to different file types. And since I am processing potentially hundreds of txt files, I want to multi-three this. So I have created a function, and since the mix of processes to monitor and output types to emit is the same for every txt file, which I then want to compile into a single big data structure at the end, I have created that final data structure as a hash of hashes, but empty of data. Then I use
Set-Variable resultsContainer -option:constant -value:$results
to make a constant, which is empty of data, to hand off to the function. the idea being I can hand the function an empty container plus the path of a txt file, and it can fill the container and return it, where I can in theory use it to fill the mutable data container. So I do a foreach on the txt files, and pass what SHOULD be an empty container each time, like this.
$journalResults = Invoke-PxParseJournal -journal "$source\$journal" -container $resultsContainer
However, instead of staying empty, as I would expect for a constant, I am effectively passing all the previous journals' data to each successive iteration of the function. I proved this to myself by initializing a counter to 1 and then running this loop after the Invoke-PxParseJournal call.
foreach ($process in $resultsContainer.Keys) {
foreach ($output in $resultsContainer.$process.Keys) {
foreach ($item in $resultsContainer.$process.$output) {
Write-Host "$(Split-Path $journal -leaf) $process $output $item$('!' * $count)"
}
}
}
After the first Invoke the loop produces nothing, but from there everything is appended. So I see results like this
journal.0002.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!
journal.0003.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!!
journal.0004.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!!!
Identical repeats each time. Even odder, if I rerun the script in the console I WILL get an error saying
Set-Variable : Cannot overwrite variable resultsContainer because it is read-only or constant.
But still the results are data being appended. Now, my first thought was that because I was using the same variable name in the function as in the root script I was dealing with some scoping problem, so I changed the name of the variable in the function and gave it an alias, like this.
[Alias('container')]$parseJournal
I then populate and return the $parseJournal variable.
No change in behavior. Which now has me wondering if I just don't understand how parameters are passed. I had thought it was ByVal, but this is acting like it is ByReference, so even with the name change I am in fact just adding to the same data structure in memory each time.
Is there something obvious here that I am missing? FWIW< I am in PS 2.0 at the moment. I don't have a Win10 VM I can spin up easily at the moment to test there.

Parse setting explicit type using REST

I know you can set a Date field explicitly like so:
"date_brewed":{
"__type":"Date",
"iso":"2009-10-15T00:00:00.000Z"
}
But is there anyway to explicitly set the column type of 'Number' using REST? For instance, I'd like to set the column 'batch_size' to a Number instead of a string but when POST'ing via rest it keeps getting created as a string type column.
Meh, this was more of a Perl issue than a Parse issue.
What I had to do to tell Perl to treat the number like an actual number was to add a zero to the value. :/