Change the format of timestamp that return my script - azure devops service - azure-devops

The timestamp is returning a timestamp with a strange format:
"TimeStamp": {
"value": "\/Date(1674758644068)\/",
"DisplayHint": 2,
"DateTime": "jueves, 26 de enero de 2023 12:44:04 p. m."
},
The problem is that I want to upload the information to powerBi and it gives me an error, for this I would like to make my script return this type of format:
"TimeStamp": "2022-08-08T19:00:53.0907571-05:00"
In my script the timestamp calls it in this function.
try {
$projectsDataArray = getProjects| ForEach-Object {
#{
TimeStamp = Get-Date
ProjectMeta = processProject($_)
}
}
#****Llamada con el recorrido para obtener el id de cada definiiton
$projectsDataArray | ConvertTo-Json -Depth 8 | Set-Content C:\Users\60085367\Documents\Proyecto3ApiDevOps\NuevaPrueba\devopsmetaFinal.json
}
catch {
Write-Output $_
}

TimeStamp = Get-Date -Format "o"

Related

Powershell Search-UnifiedAuditLog and export AuditData Field

I'm working on a function to export audit logs from Office 365. When dumping the logs, the AuditData field contains what I feel is the useful information. I'm looking to export only that field and convert it to a CSV. Below is my function.
Function ExportAuditLog($User) {
$logResults = #()
if ($user -eq $null) {
$user = SelectUser "Please select a user to audit"
}
$logData = Search-UnifiedAuditLog -StartDate ((Get-Date).AddDays(-30)) -EndDate (Get-Date) -UserIds $user -Operations MailboxLogin -Formatted | select AuditData
foreach ($entry in $logData) {
$logResults += $entry.AuditData
}
return $logResults
}
This is the output.
{
"CreationTime": "2018-12-01T14:08:55",
"Id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Operation": "MailboxLogin",
"OrganizationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"RecordType": "ExchangeItem",
"ResultStatus": "Succeeded",
"UserKey": "xxxxxxxxxxxxxxxx",
"UserType": "Regular",
"Version": 1,
"Workload": "Exchange",
"UserId": "user#domain.com",
"ClientIPAddress": "1.2.3.4",
"ClientInfoString":
"Client=Microsoft.Exchange.Autodiscover; Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.11001; Pro)",
"ExternalAccess": false,
"InternalLogonType": 0,
"LogonType": 0,
"LogonUserSid": "x-x-x-xx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxxxx",
"MailboxGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"MailboxOwnerSid": "x-x-x-xx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxxxx",
"MailboxOwnerUPN": "user#domain.com",
"OrganizationName": "domain.com",
"OriginatingServer": "",
"SessionId": ""
}
My goal is to have the first part of each line serve as the column header and the second part is the data.
Use the ConvertFrom-Json cmdlet to convert the field into a Powershell object:
$logResults += ConvertFrom-Json $entry.AuditData
Then use the Export-Csv cmdlet to export it to a csv file:
$logResults | Export-Csv -Path AuditData.csv -NoTypeInformation

Replace a value in a json using powershell

I have a json file with the following content -
{
"IsEnabled": true,
"EngineConfiguration": {
"PollInterval": "00:00:15",
"Components": [{
"Id": "Logs",
"FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"LogDirectoryPath": "C:\\log\\2018-05-25",
"TimestampFormat": "yyyy-MM-dd HH:mm:ss",
"Encoding": "UTF-8",
"Filter": "",
"CultureName": "en-US",
"TimeZoneKind": "UTC",
"LineCount": "1"
}
}]
}
}
I want to replace this date(mentioned in LogDirectoryPath) everyday using a managed task using powershell.
How can this be done using powershell?
This script will help you to update log directory.
Steps:
Get content of json file.
Update attribute value if exists. $JsonData.update | % {if(...)
Save content in same file.
Script:
$JsonData = Get-Content $JsonFilePath -raw | ConvertFrom-Json
$JsonData.update | % { if($JsonData.engineconfiguration.Components.Parameters.LogDirectoryPath)
{
$JsonData.engineconfiguration.Components.Parameters.LogDirectoryPath = "C:\log\$(Get-Date -Format 'yyyy-MM-dd')"
}
}
$JsonData | ConvertTo-Json -Depth 4 | set-content $JsonFilePath
The first step is converting the content to json:
$json = Convertfrom-json (get-content "\\path\To\Json\File.json")
Then editing the value as desired:
$json.engineconfiguration.Components.Parameters.LogDirectoryPath = "C:\log\$(Get-Date -Format 'yyyy-MM-dd')"
Then writing it back to file:
ConvertTo-Json $json -Depth 4 | Out-File C:\ProgramData\Temp\test.txt -Force
I have also faced the same kind of issue. I was looking to change the records of the below JSON file
{
"SQS_QUEUE_URL": "https://que-url.com/server1",
"SQS_EVENTS_QUEUE_URL": "https://events-server.com/server1/development_events",
"REGION": "region1",
"BUCKET": "test-bucket",
"AE_WORK_PATH": "C:\\workpath\\path1",
"ENV": "env"
}
Finally, I managed to find the easiest way to generate a JSON file from Powershell.
$json = Get-Content "c:\users\bharat.gadade\desktop\test.json" | ConvertFrom-Json
$json.SQS_QUEUE_URL = "https://que-url.com/server2"
$json.SQS_EVENTS_QUEUE_URL = "https://events-server.com/Server2/development_events"
$json.REGION = "region1 "
$json.BUCKET = "test-bucket"
$json.AE_WORK_PATH = "C:\workpath\path1"
$json.ENV = "env"
$json | ConvertTo-Json | Out-File "c:\users\bharat.gadade\desktop\test.json"

Create a dynamic ReST request body in PowerShell

I am currently working on a use case for invoking ReST request in PowerShell. The body of POST request is created dynamically, reading data from a CSV file.
Here is how my final request body should be
{
"#type": "mtTaskParameter",
"name": "$src_sfdc$",
"type": "EXTENDED_SOURCE",
"sourceConnectionId":"00002E0B00000000000C"
},
{
"#type": "mtTaskParameter",
"name": "$tgt_db_del$",
"type": "TARGET",
"targetConnectionId":"00002E0B00000000000D"
},
{
"#type": "mtTaskParameter",
"name": "$tgt_db_ups$",
"type": "TARGET",
"targetConnectionId":"00002E0B00000000000D"
},
{
"#type": "mtTaskParameter",
"name": "$tgt_status$",
"type": "TARGET",
"targetConnectionId":"00002E0B00000000000D"
}
}
Currently I have implemented like below
if($connectionParameterized -eq "true"){
$str = #"
"#type": "mtTaskParameter",
"name": "$name",
"type": "$type"
"#
if($type -eq "SOURCE"){
$sourceConnectionId = <get source id>
$str = $str+
#"
,"sourceConnectionId":"$sourceConnectionId"
"#
}
if($type -eq "TARGET"){
$targetConnectionId = <get target id>
$str = $str+
#"
,"targetConnectionId":"$targetConnectionId"
"#
}
$finalstr = $finalstr+#"
{
$str
},
"#
}
This works fine, but the code becomes really messy and so difficult to scale. Also while printing, the format is not proper.
Is there a better way to handle this?
Note: As evident from the example, the request body contains several special characters like #,$ etc.
This would be easier if you included your CSV, but basically, you can import the CSV as an array of objects, then convert that to JSON.
You can customize the objects that are created from importing the CSV by adding custom members so that the translation to JSON gives you the output you want.
You can also group or filter the array of objects to make different ones depending on certain conditions.
Here's a some sample code that probably won't work directly but should somewhat demonstrate the concept:
$json = Import-Csv -Path C:\my\data.csv |
ForEach-Object -Process {
$row = $_
$propName = $row.Type.ToLower() + 'ConnectionId'
$row | Add-Member -NotePropertyName $propName -NotePropertyValue $out["$mapping_name"].$name -Force -PassThru
} |
ConvertTo-Json

Date comparison (French locale) - getting wrong positive

I want to know which accounts were not connected on AD since 3 months
Here's my code
# connexion ADSI
$objDomaine = [ADSI]’’
$objRecherche = New-Object System.DirectoryServices.DirectorySearcher($objDomaine)
$objRecherche.Filter=’(&(objectCategory=person)(objectClass=user))’
# Fichiers de sortie
$OutFile = "\\xxx\xx\Utilisateurs_inactifs.log"
remove-item $OutFile
ADD-content -path $OutFile -value "LOGIN;CN_COMPLET;LASTLOGON"
foreach ( $ADuser in $objRecherche.FindAll() )
{
$LastLogon = $ADuser.Properties[’lastlogon’]
$LastLogon = [int64]::parse($LastLogon)
$date = (Get-Date -Year 1601 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0)
$date_derniere_connexion = $date.AddTicks($LastLogon)
#On formatte un peu le tout. On enleve l'heure et on enleve les \, des CNs.
$DATE_RESULT = $date_derniere_connexion -replace " ..:..:..",""
$RESULT = "$($ADuser.properties[’samaccountname’]);$($ADuser.path);$($DATE_RESULT)" -replace "\\\,",""
# On prend la date du jour et on retire 3 mois
$DATE3MONTHS = (get-date).addmonths(-3).toShortdateString()
# On test la date (pour enlever les occurences de non-login)
if ( $DATE_RESULT -ne '01/01/1601' )
{
# tester si la date de derniere connexion est plus vieille que 3 mois, si oui on ecrit dans le fichier.
if ( $DATE_RESULT -lt $DATE3MONTHS )
{ ADD-content -path $OutFile -value $RESULT }
}
}
In my outfile, I can see many users which last connection is NOT older than 3 months (yesterday!)
here's an sample of my outfile
xx;LDAP://CN=xx;15/09/2015
xx;LDAP://CN=xx;09/09/2015
xx;LDAP://CN=xx;16/09/2015
xx;LDAP://CN=xx;07/05/2014
xx;LDAP://CN=xx;16/09/2015
xx;LDAP://CN=xx;09/01/2015
NOTE : My dates are in french version DD/MM/YYYY
[datetime]::parse("$DATE_RESULT") # this will convert string to date. Parse for my french locale.
Why does PowerShell always use US culture when casting to DateTime?

Display current time with time zone in PowerShell

I'm trying to display the local time on my system with the TimeZone. How can I display time in this format the simplest way possible on any system?:
Time: 8:00:34 AM EST
I'm currently using the following script:
$localtz = [System.TimeZoneInfo]::Local | Select-Object -expandproperty Id
if ($localtz -match "Eastern") {$x = " EST"}
if ($localtz -match "Pacific") {$x = " PST"}
if ($localtz -match "Central") {$x = " CST"}
"Time: " + (Get-Date).Hour + ":" + (Get-Date).Minute + ":" + (Get-Date).Second + $x
I'd like to be able to display the time without relying on simple logic, but be able to give the local timezone on any system.
While this is a bit ... naive perhaps, it's one way to get an abbreviation without a switch statement:
[Regex]::Replace([System.TimeZoneInfo]::Local.StandardName, '([A-Z])\w+\s*', '$1')
My regular expression probably leaves something to be desired.
The output of the above for my time zone is EST. I did some looking as I wanted to see what the value would be for other GMT offset settings, but .NET doesn't seem to have very good links between DateTime and TimeZoneInfo, so I couldn't just programmatically run through them all to check. This might not work properly for some of the strings that come back for StandardName.
EDIT: I did some more investigation changing the time zone on my computer manually to check this and a TimeZoneInfo for GMT+12 looks like this:
PS> [TimeZoneInfo]::Local
Id : UTC+12
DisplayName : (GMT+12:00) Coordinated Universal Time+12
StandardName : UTC+12
DaylightName : UTC+12
BaseUtcOffset : 12:00:00
SupportsDaylightSavingTime : False
Which produces this result for my code:
PS> [Regex]::Replace([System.TimeZoneInfo]::Local.StandardName, '([A-Z])\w+\s*', '$1')
U+12
So, I guess you'd have to detect whether the StandardName appears to be a set of words or just offset designation because there's no standard name for it.
The less problematic ones outside the US appear to follow the three-word format:
PS> [TimeZoneInfo]::Local
Id : Tokyo Standard Time
DisplayName : (GMT+09:00) Osaka, Sapporo, Tokyo
StandardName : Tokyo Standard Time
DaylightName : Tokyo Daylight Time
BaseUtcOffset : 09:00:00
SupportsDaylightSavingTime : False
PS> [Regex]::Replace([System.TimeZoneInfo]::Local.StandardName, '([A-Z])\w+\s*', '$1')
TST
You should look into DateTime format strings. Although I'm not sure they can return a time zone short name, you can easily get an offset from UTC.
$formatteddate = "{0:h:mm:ss tt zzz}" -f (get-date)
This returns:
8:00:34 AM -04:00
Be loath to define another datetime format! Use an existing one, such as RFC 1123. There's even a PowerShell shortcut!
Get-Date -format r
Thu, 14 Jun 2012 16:44:18 GMT
Ref.: Get-Date
This is a better answer:
$A = Get-Date #Returns local date/time
$B = $A.ToUniversalTime() #Convert it to UTC
# Figure out your current offset from UTC
$Offset = [TimeZoneInfo]::Local | Select BaseUtcOffset
#Add the Offset
$C = $B + $Offset.BaseUtcOffset
$C.ToString()
Output:
3/20/2017 11:55:55 PM
I'm not aware of any object that can do the work for you. You could wrap the logic in a function:
function Get-MyDate{
$tz = switch -regex ([System.TimeZoneInfo]::Local.Id){
Eastern {'EST'; break}
Pacific {'PST'; break}
Central {'CST'; break}
}
"Time: {0:T} $tz" -f (Get-Date)
}
Get-MyDate
Or even take the initials of the time zone id:
$tz = -join ([System.TimeZoneInfo]::Local.Id.Split() | Foreach-Object {$_[0]})
"Time: {0:T} $tz" -f (Get-Date)
I just combined several scripts and finally was able to run the script in my domain controller.
The script provides the output of time and timezone for all the machines connected under the domain.
We had a major issue with our application servers and used this script to cross check the time and timezone.
# The below scripts provides the time and time zone for the connected machines in a domain
# Appends the output to a text file with the time stamp
# Checks if the host is reachable or not via a ping command
Start-Transcript -path C:\output.txt -append
$ldapSearcher = New-Object directoryservices.directorysearcher;
$ldapSearcher.filter = "(objectclass=computer)";
$computers = $ldapSearcher.findall();
foreach ($computer in $computers)
{
$compname = $computer.properties["name"]
$ping = gwmi win32_pingstatus -f "Address = '$compname'"
$compname
if ($ping.statuscode -eq 0)
{
try
{
$ErrorActionPreference = "Stop"
Write-Host “Attempting to determine timezone information for $compname…”
$Timezone = Get-WMIObject -class Win32_TimeZone -ComputerName $compname
$remoteOSInfo = gwmi win32_OperatingSystem -computername $compname
[datetime]$remoteDateTime = $remoteOSInfo.convertToDatetime($remoteOSInfo.LocalDateTime)
if ($Timezone)
{
foreach ($item in $Timezone)
{
$TZDescription = $Timezone.Description
$TZDaylightTime = $Timezone.DaylightName
$TZStandardTime = $Timezone.StandardName
$TZStandardTime = $Timezone.StandardTime
}
Write-Host "Timezone is set to $TZDescription`nTime and Date is $remoteDateTime`n**********************`n"
}
else
{
Write-Host ("Something went wrong")
}
}
catch
{
Write-Host ("You have insufficient rights to query the computer or the RPC server is not available.")
}
finally
{
$ErrorActionPreference = "Continue"
}
}
else
{
Write-Host ("Host $compname is not reachable from ping `n")
}
}
Stop-Transcript
Russia, France, Norway, Germany:
get-date -format "HH:mm:ss ddd dd'.'MM'.'yy' г.' zzz"
Output for Russian time zone: 22:47:27 Чт 21.11.19 г. +03:00
Others - just change the code.
If you have a internet connection... API
Function tzAbbreviation {
Try {
$webData = Invoke-WebRequest -Uri "https://worldtimeapi.org/api/ip" -UseBasicParsing -TimeoutSec 3 -ErrorAction Stop
$Content = ConvertFrom-Json $webData.Content
Return $($Content.Abbreviation)
}
Catch {}
}
$tzAbbreviation = tzAbbreviation
In the Netherlands...
Output: CET