I am attempting to display information for administrators processing user changes to easily see what changes are being made to certain fields in Active Directory users. I've written a PowerShell script to process these changes, but I'm having trouble formatting the output for the administrators who are running the script. See this post for a similar, but different problem.
My code:
$output = [pscustomobject]#{'UserName' = $user.samAccountName; 'FirstName' = $user.GivenName;'LastName' = $user.Surname;'DisplayName' = $user.DisplayName;'UPN' = $user.UserPrincipalName;'E-Mail_Address' = $user.proxyAddresses;'Title' = $user.Title;'Office' = $user.PhysicalDeliveryOfficeName;'Dept' = $user.Department;}
$output[$index++] | Add-Member -NotePropertyMembers #{'NewUserName' = $samAccountName; 'NewFirstName' = $firstName;'NewLastName' = $lastname;'NewDisplayName' = $displayName;'NewUPN' = $UPN;'NewE-Mail_Address' = $SMTP1;'NewTitle' = $Title;'Newoffice' = $office;'NewDept' = $department;}
$output
Output:
UserName : FirstLast
FirstName : First
LastName : Last
DisplayName : First Last
UPN : FirstLast#company.com
E-Mail_Address : SMTP:FirstLast#company.com
Title : CEO
Office : HQ
Dept : Executives
NewDept : Maintenance
NewE-Mail_Address : SMTP:FirstLast#company.com
NewOffice : The Dump
NewFirstName : First
NewLastName : Last
NewUserName : FirstLast
NewDisplayName : First Last
NewUPN : FirstLast#company.com
NewTitle : Trash Collector
Desired Output:
UserName : FirstLast NewUserName : FirstLast
FirstName : First NewFirstName : First
LastName : Last NewLastName : Last
DisplayName : First Last NewDisplayName : First Last
UPN : FirstLast#company.com NewUPN : FirstLast#company.com
E-Mail_Address : SMTP:FirstLast#company.com NewE-Mail_Address : SMTP:FirstLast#company.com
Title : CEO NewTitle : Trash Collector
Office : HQ Newoffice : The Dump
Dept : Executives NewDept : Maintenance
Below will create the two Format-List outputs next to eachother.
Because more than likely this will not fit the width of the console screen, the output is captured first and output using Out-String with a high number for parameter -Width.
Like this, you can also save to text file.
$outputOld = [pscustomobject]#{
'UserName' = $user.samAccountName; 'FirstName' = $user.GivenName;
'LastName' = $user.Surname;'DisplayName' = $user.DisplayName;
'UPN' = $user.UserPrincipalName;'E-Mail_Address' = $user.proxyAddresses;
'Title' = $user.Title;'Office' = $user.PhysicalDeliveryOfficeName;
'Dept' = $user.Department}
$outputNew = [pscustomobject]#{
'NewUserName' = $samAccountName; 'NewFirstName' = $firstName;
'NewLastName' = $lastname;'NewDisplayName' = $displayName;'NewUPN' = $UPN;
'NewE-Mail_Address' = $SMTP1;'NewTitle' = $Title;'Newoffice' = $office;
'NewDept' = $department}
# capture the Format-List output of each object and split into a string array
$outLeft = #(($outputOld | Format-List | Out-String) -split '\r?\n')
$outRight = #(($outputNew | Format-List | Out-String) -split '\r?\n')
# determine the maximum length of each string in the list that goes to the left
$maxLength = ($outLeft | Measure-Object -Property Length -Maximum).Maximum
# get the maximum number of lines
$maxLines = [math]::Max($outLeft.Count, $outRight.Count)
# collect the combined output
$result = for ($i = 0; $i -lt $maxLines; $i++) {
$left = if ($i -lt $outLeft.Count) { "{0,-$maxLength}" -f $outLeft[$i] } else { ' ' * $maxLength }
$right = if ($i -lt $outRight.Count) { $outRight[$i] } else {''}
('{0} {1}' -f $left, $right).TrimEnd()
}
# display on screen
$result | Out-String -Width 1000
# save to text file
$result | Out-String -Width 1000 | Set-Content -Path 'D:\Test\output.txt'
This doesn't produce exactly the same character-by-character output as you're after, but it does produce something similar using the built-in formatting methods without lots of stringifying of values.
First, set up some test data, which would need a small change to your sample code to generate as two objects, instead of your combined $output variable:
$oldValues = [pscustomobject] [ordered] #{
"UserName" = "FirstLast"
"FirstName" = "First"
"LastName" = "Last"
"DisplayName" = "First Last"
"UPN" = "FirstLast#company.com"
"E-Mail_Address" = "SMTP:FirstLast#company.com"
"Title" = "CEO"
"Office" = "HQ"
"Dept" = "Executives"
};
$newValues = [pscustomobject] [ordered] #{
"NewDept" = "Maintenance"
"NewE-Mail_Address" = "SMTP:FirstLast#company.com"
"NewOffice" = "The Dump"
"NewFirstName" = "First"
"NewLastName" = "Last"
"NewUserName" = "FirstLast"
"NewDisplayName" = "First Last"
"NewUPN" = "FirstLast#company.com"
"NewTitle" = "Trash Collector"
};
Next, we map the variables into an array of PropertyName, OldValue, NewValue objects:
$rows = $oldValues.psobject.properties `
| foreach-object {
$property = $_;
[pscustomobject] [ordered] #{
"PropertyName" = $property.Name
"OldValue" = $property.Value
"NewValue" = $newValues.("New" + $property.Name)
}
};
And then we can format it using the built-in cmdlets:
$rows | format-table
# PropertyName OldValue NewValue
# ------------ -------- --------
# UserName FirstLast FirstLast
# FirstName First First
# LastName Last Last
# DisplayName First Last First Last
# UPN FirstLast#company.com FirstLast#company.com
# E-Mail_Address SMTP:FirstLast#company.com SMTP:FirstLast#company.com
# Title CEO Trash Collector
# Office HQ The Dump
# Dept Executives Maintenance
The nice thing is you can adjust things like column widths, word wrap, etc just using the Format-Table parameters, or even use Format-List instead:
$rows | format-list
# ... etc ...
#
# PropertyName : Title
# OldValue : CEO
# NewValue : Trash Collector
#
# PropertyName : Office
# OldValue : HQ
# NewValue : The Dump
#
# ... etc ...
And you can filter it to show just changed values:
$rows | where-object { $_.NewValue -ne $_.OldValue } | format-table
# PropertyName OldValue NewValue
# ------------ -------- --------
# Title CEO Trash Collector
# Office HQ The Dump
# Dept Executives Maintenance
It relies on the property names being in the format "Xyz -> NewXyz", but there's ways around that if it's not true in all cases...
you can use ANSI ESCAPE codes to apply decorations. This sample is based in pscustomobject with all values, but you can create two pscustomobject to make clear the code.
Notes:
Change ESC to $([char]27) or `e in Ps6 (thank you Mr. mclayton)
I prefer use Add-Member item per item.
Tested with PowerShell 5.1 ($PSVersionTable command).
$output = [pscustomobject]#{'UserName' = 'User1'; 'FirstName' = '$user.GivenName';'LastName' = '$user.Surname';'DisplayName' = '$user.DisplayName';'UPN' = '$user.UserPrincipalName';'E-Mail_Address' = '$user.proxyAddresses';'Title' = '$user.Title';'Office' = '$user.PhysicalDeliveryOfficeName';'Dept' = '$user.Department';}
$output | Add-Member -NotePropertyMembers #{'NewUserName' = 'User2'}
$output | Add-Member -NotePropertyMembers #{'NewFirstName' = '$firstName'}
$output | Add-Member -NotePropertyMembers #{'NewLastName' = '$lastname'}
$output | Add-Member -NotePropertyMembers #{'NewDisplayName' = '$displayName'}
$output | Add-Member -NotePropertyMembers #{'NewUPN' = '$UPN'}
$output | Add-Member -NotePropertyMembers #{'NewE-Mail_Address' = '$SMTP1'}
$output | Add-Member -NotePropertyMembers #{'NewTitle' = '$Title'}
$output | Add-Member -NotePropertyMembers #{'Newoffice' = '$office'}
$output | Add-Member -NotePropertyMembers #{'NewDept' = '$department'}
# Counter for column 1 and column 2
$Counter =0
$Counter1 =0
# Temporally variables
$Text
$Label
# Do the magic
foreach( $property in $output.psobject.properties.name )
{
if ( $Counter -lt 9 )
{
$Counter = $Counter +1
$Text = $output.$property
$Label = $property
echo "ESC[$Counter;1H $Label : $Text "
} else
{
$Counter1 = $Counter1 +1
$Text = $output.$property
$Label = $property
echo "ESC[$Counter1;60H $Label : $Text "
}
}
#Move to end
echo "ESC[20;1H "
Result
Other ANSI commands
Happy coding my friends.
Related
first of all sorry if my english is not the best. but ill try to explain my issue with as much detail as i can
Im having an issue where i cant get Format-Table to effect the output i give it.
below is the part im having issues with atm.
cls
$TotalSize = $($mailboxes. #{name = ”TotalItemSize (GB)”; expression = { [math]::Round((($_.TotalItemSize.Value.ToString()).Split(“(“)[1].Split(” “)[0].Replace(“,”, ””) / 1GB), 2) } });
$UserN = $($mailboxes.DisplayName)
$itemCount = $($mailboxes.ItemCount)
$LastLogonTime = $($mailboxes.ItemCount)
$allMailboxinfo = #(
#lager dataen som skal inn i et objekt
#{Username= $UserN; ItemCount = $itemCount; LastLogonTime = $($mailboxes.ItemCount); Size = $TotalSize}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$Table = $allMailboxinfo | Format-Table | Out-String
$Table
the output of this gives me what almost looks like json syntax below each title of the table.
Username LastLogonTime ItemCount Size
-------- ------------- --------- ----
{username1, username2,username3,userna...} {$null, $null, $null, $null...} {$null, $null, $null, $null...} {$null, $null, $null, $null...}
running the commands by themselves seem to work tho. like $mailboxes.DisplayName gives the exact data i want for displayname. even in table-format.
the reason im making the table this way instead of just using select-object, is because im going to merge a few tables later. using the logic from the script below.
cls
$someData = #(
#{Name = "Bill"; email = "email#domain.com"; phone = "12345678"; id = "043546" }) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$moreData = #(
#{Name = "Bill"; company = "company 04"}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
$Merge = #(
#plots the data into a new table
#{Name = $($someData.Name); e_mail = $($someData.email); phone = $($someData.phone); id = $($someData.id); merged = $($moreData.company) }) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }
#formatting table
$Table = $Merge | Format-Table | Out-String
#print table
$Table
if you are wondering what im doing with this.
My goal, all in all. is a table with using the info from Exchange;
DisplayName, TotalItemSize(GB), ItemCount, LastLogonTime, E-mail adress, archive + Maxquoata, Quoata for mailbox.
You're creating a single object where each property holds an array of property values from the original array of mailbox objects.
Instead, create 1 new object per mailbox:
# construct output objects with Select-Object
$allMailBoxInfo = $mailboxes |Select #{Name='Username';Expression='DisplayName'},ItemCount,#{Name='LastLogonTime';Expression='ItemCount'},#{Name='Size';Expression={[math]::Round((($_.TotalItemSize.Value.ToString()).Split("(")[1].Split(" ")[0].Replace(",", "") / 1GB), 2) }}
# format table
$Table = $allMailBoxInfo | Format-Table | Out-String
# print table
$Table
I've had this idea about getting the output from 2 separate functions, that return a PSCustomObject as a list, and formatting them into one table. My problem is simple... I don't know how to do it. lol
With the various of combinations that I tried, here's whats given me some promising results:
$Var1 = [PSCustomObject]#{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
} | Format-List | Out-String -Stream
$Var2 = [PSCustomObject]#{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
} | Format-List | Out-String -Stream
[PSCustomObject]#{
TableOne = $Var1.Trim().Foreach({$_})
TableTwo = $Var2.Trim()
} | Format-Table -AutoSize
The output:
TableOne TableTwo
-------- --------
{, , UserName : Abraham, Stuff1 : stuff1...} {, , ComputerName : DESKTOP-OEREJ77, Stuff2 : stuff2...}
I say promising in the respect that it shows the actual content of $var1 and 2, whereas my other attempts didn't. I also left the .foreach() operator there to show one of the many many different tricks I tried to get this working. For a quick second I thought the Out-String cmdlet would've done the trick for me, but was unsuccessful.
Has anyone ever done something similar to this?
EDIT:
Nevermind, I figured it out.
Used a for loop to iterate through each line assigning it the the PSCustomObject one at a time. Also used the .Where() operator to remove white spaces, and compared the two arrays to find the largest number to use it as the count.
$Var1 = $([PSCustomObject]#{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
} | Format-List | Out-String -Stream).Where{$_ -ne ''}
$Var2 = $([PSCustomObject]#{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
ExtraStuff = 'More'
} | Format-List | Out-String -Stream).Where{$_ -ne ''}
$Count = ($Var1.Count, $Var2.Count | Measure-Object -Maximum).Maximum
$(for($i=0;$i -lt $Count; $i++) {
[PSCustomObject]#{
TableOne = $Var1[$i]
TableTwo = $Var2[$i]
}
}) | Format-Table -AutoSize
Output:
TableOne TableTwo
-------- --------
UserName : Abraham ComputerName : DESKTOP-OEREJ77
Stuff1 : stuff1 Stuff2 : stuff2
ExtraStuff : More
It's an interesting way to format two collections with corresponding elements.
To indeed support two collections with multiple elements, a few tweaks to your approach are required:
# First collection, containing 2 sample objects.
$coll1 =
[PSCustomObject] #{
UserName = $env:USERNAME
Stuff1 = 'stuff1'
},
[PSCustomObject] #{
UserName = $env:USERNAME + '_2'
Stuff1 = 'stuff2'
}
# Second collection; ditto.
$coll2 =
[PSCustomObject] #{
ComputerName = $env:COMPUTERNAME
Stuff2 = 'stuff2'
ExtraStuff = 'More'
},
[PSCustomObject]#{
ComputerName = $env:COMPUTERNAME + '_2'
Stuff2 = 'stuff2_2'
ExtraStuff = 'More_2'
}
# Stream the two collections in tandem, and output a Format-List
# representation of each object in a pair side by side.
& {
foreach ($i in 0..([Math]::Max($coll1.Count, $coll2.Count) - 1)) {
[PSCustomObject] #{
TableOne = ($coll1[$i] | Format-List | Out-String).Trim() + "`n"
TableTwo = ($coll2[$i] | Format-List | Out-String).Trim() + "`n"
}
}
} | Format-Table -AutoSize -Wrap
The above ensures that multiple objects are properly placed next to each other, and yields something like the following:
TableOne TableTwo
-------- --------
UserName : jdoe ComputerName : WS1
Stuff1 : stuff1 Stuff2 : stuff2
ExtraStuff : More
UserName : jdoe_2 ComputerName : WS1_2
Stuff1 : stuff2 Stuff2 : stuff2_2
ExtraStuff : More_2
I am fairly new to PowerShell and I want for a USB key plugged, to retrieve some info. Right now my script is:
Get-WmiObject win32_diskdrive |
ForEach-Object{
$disk = $_
$_.GetRelated('Win32_PnPEntity')|
ForEach-Object{
$pnp = $_
$_.GetRelated('Win32_USBController') |
ForEach-Object{
$usb = $_
[pscustomobject]#{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {VID=$matches['vid']; PID=$matches['pid']}
}
}
}
}
The line beginning with
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {VID=$matches['vid']; PID=$matches['pid']}
does not work. I want to translate deviceid (which I can get by doing USBDeviceID = $usb.DeviceID) ID in PID UID directly.
It throws the following error
Error with code “Missing = operator after key in hash literal" for the statement "if ($usb.DeviceID -match '.* ...
What am I missing ? many thanks for helping me .
Gerald
This is because the way you intend to add properties to the PsCustomObject is wrong.
Either do this:
$result = [PsCustomObject]#{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
}
# add items to the object if the condition is true
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {
$result | Add-Member -MemberType NoteProperty -Name 'VID' -Value $matches['vid']
$result | Add-Member -MemberType NoteProperty -Name 'PID' -Value $matches['pid']
}
# output the PsCustomObject
$result
or use a Hashtable as temporary storage:
# create a Hastable to temporarily store results in
$hash = [ordered]#{
SerialNumber = $disk.SerialNumber
Model = $disk.Model
Size = $disk.Size
}
# add items to the hash if the condition is true
if ($usb.DeviceID -match '.*VID_(?<vid>[0-9A-F]{4})&PID_(?<pid>[0-9A-F]{4}).*') {
$hash['VID']=$matches['vid']
$hash['PID']=$matches['pid']
}
# next cast to PsCustomObject and output
[PsCustomObject]$hash
xml sample
<?xml version="1.0" encoding="UTF-8"?>
<CUSTOMERS xml:lang="en">
<CUSTOMER CREATED_DATE="2020-10-16 13:21:09.0" GROUP_ID="" ID="1509999">
<NAME>
<TITLE></TITLE>
<FIRST_NAME>John</FIRST_NAME>
<LAST_NAME>Smith</LAST_NAME>
</NAME>
<GENDER/>
<DATE_OF_BIRTH/>
<CONTACT_DETAILS>
<TELEPHONE MARKETING_OPT_IN="F" TYPE="MOBILE">0123456789</TELEPHONE>
<EMAIL MARKETING_OPT_IN="F">test#yahoo.com</EMAIL>
</CONTACT_DETAILS>
<ATTRIBUTE NAME="theCompany-News and offers on theCompany Womenswear_OPT_EMAIL">T</ATTRIBUTE>
<ATTRIBUTE NAME="Email Soft Opt In_OPT_EMAIL">F</ATTRIBUTE>
<ATTRIBUTE NAME="REGISTERED_ON_WEBSITE">T</ATTRIBUTE>
</CUSTOMER>
</CUSTOMERS>
I have inherited an Azure Powershell function which builds a list of values from XML file.
I need to add some code to access this value:
<ATTRIBUTE NAME="Email Soft Opt In_OPT_EMAIL">F</ATTRIBUTE>
This is the Powershell Code I have so far
[xml]$xml = Get-Content C:\Users\Jason2\Desktop\XMLfolder\theSample.xml
$xml
$CustomerListFull = #()
foreach ($customer in $xml.CUSTOMERS.CUSTOMER)
{ $BuildList = New-Object -TypeName psobject
$BuildList | Add-Member -MemberType NoteProperty -Name TITLE -Value $customer.NAME.TITLE.Trim()
$BuildList | Add-Member -MemberType NoteProperty -Name FIRSTNAME -Value $customer.NAME.FIRST_NAME.Trim()
$BuildList | Add-Member -MemberType NoteProperty -Name LASTNAME -Value $customer.NAME.LAST_NAME.Trim()
$BuildList | Add-Member -MemberType NoteProperty -Name EMAILCONSENT -Value "0"
$BuildList | Add-Member -MemberType NoteProperty -Name EMAILSOFTOPTIN -Value "2"
if ($customer.ATTRIBUTE.NAME -like "*OPT_EMAIL") {
foreach ($value in $customer.ATTRIBUTE.NAME) {
if ($value -match "theCompany-News and offers on theCompany Womenswear_OPT_EMAIL") {
$BuildList.EMAILCONSENT = "1"
}
if ($value -match "Email Soft Opt In_OPT_EMAIL") {
$BuildList.EMAILSOFTOPTIN = $customer.ATTRIBUTE.'#text'
}
}
}
$CustomerListFull += $BuildList
}
$CustomerListFull
which is incorrectly giving me all three Attribute Name values (into field EMAILSOFTOPTIN)
TITLE :
FIRSTNAME : John
LASTNAME : Smith
EMAILCONSENT : 1
EMAILSOFTOPTIN : {T, F, T}
I have tried several things to try and access the value, user marsze yesterday showed me nodes which is great but I can't seem to make it work in my forloop, I'm failing miserably.
$BuildList.EMAILSOFTOPTIN = $customer.SelectNodes("//*[local-name()='ATTRIBUTE'][#NAME='Email Soft Opt In_OPT_EMAIL']").InnerText
$BuildList.EMAILSOFTOPTIN = $customer.[ATTRIBUTE].[NAME='Email Soft Opt In_OPT_EMAIL').InnerText
$nodes = $xml.SelectNodes("//*[local-name()='ATTRIBUTE'][#NAME='Email Soft Opt In_OPT_EMAIL']")
$BuildList.EMAILSOFTOPTIN = $nodes.InnerText
Please help to put me out of my misery
There are multiple tiny flaws in your code.
1.)
$customer.ATTRIBUTE.NAME -like "*OPT_EMAIL"
If the left operand is a collection, the result is also a collection, namely of all the items that return true for the operation, in this case all values of NAME that match *OPT_EMAIL". Also, this check is unnecessary, because you make another literal comparison later.
2.)
$value -match "Email Soft Opt In_OPT_EMAIL"
-Match is probably not a good choice here, because it treats the right value as regex. It will work in this case, but I think you want -eq
3.)
$customer.ATTRIBUTE.'#text'
This will always return a collection of the inner text of all <ATTRIBUTE> nodes of the current customer, namely {T, F, T}
===
Here is my version, with some additional changes, but that is just a matter of personal taste:
[xml]$xml = Get-Content "C:\Users\Jason2\Desktop\XMLfolder\theSample.xml"
# you can build the array directly, like this
# because the += operator on arrays is terribly slow
$customerListFull = #(foreach ($customer in $xml.Customers.Customer) {
# defaults
$emailConsent = 0 # or $false?
$emailSoftOptIn = "2"
# loop attributes
# the "OPT_EMAIL" check is dispensable here
foreach ($attribute in $customer.Attribute) {
# switch is a good replacement for a lot of if's,
# that basically all do the same check
switch ($attribute.Name) {
"theCompany-News and offers on theCompany Womenswear_OPT_EMAIL" {
$emailConsent = 1 # or $true?
}
"Email Soft Opt In_OPT_EMAIL" {
$emailSoftOptIn = switch ($attribute.InnerText.Trim()) {
"F" { 0 }
"T" { 1 }
}
### OR ###
$emailSoftOptIn = #{F = 0; T = 1}[$attribute.InnerText.Trim()]
}
}
}
# Create and output the object directly.
# This is an easier way to construct an object,
# which also keeps the property order
[PSCustomObject]#{
Title = $customer.Name.Title.Trim()
FirstName = $customer.Name.First_Name.Trim()
LastName = $customer.Name.Last_Name.Trim()
EmailConsent = $emailConsent
EmailSoftOptIn = $emailSoftOptIn
}
### OR ###
# use [ordered]
New-Object -TypeName PSObject -Property ([ordered]#{
Title = $customer.Name.Title.Trim()
FirstName = $customer.Name.First_Name.Trim()
LastName = $customer.Name.Last_Name.Trim()
EmailConsent = $emailConsent
EmailSoftOptIn = $emailSoftOptIn
})
})
I'm using DBATools Module Invoke-DBQQuery ( based on Invoke-SQLCMD2) to query a SQL database.
The query returns single record as a PSObject called $Results that looks like this...
FileName : C12345
BADGENUMBER : BADGENUMBER=12345
LASTNAME : LASTNAME=SMITH
FIRSTNAME : FIRSTNAME=JOHN
CIA : CIA=YES
SOCIALSECURITY : SOCIALSECURITY=999999999
DACDATE : DACDATE=07/16/2022
UIC : UIC=42158
I need to output this PSObject to a TXT file with just the values no
Field Titles one field on each row. that looks like this...
C12345
BADGENUMBER=12345
LASTNAME=SMITH
FIRSTNAME=JOHN
CIA=YES
SOCIALSECURITY=999999999
DACDATE=07/16/2022
UIC=42158
How do I go about producing the test file in the format I need?
$Results| Out-File c:\test.test.txt
produces the first output I listed.
Appreciate any assistance anyone can provide.
-MARK-
Here some different angles to solve
$result = Invoke-DbaQuery -SqlInstance $sql -Query 'select * from MyTable' -As PSObject
# Simulate a 2 rows result
$result = [PSCustomObject]#{
FileName = 'C12345'
BADGENUMBER = 'BADGENUMBER=12345'
LASTNAME = 'LASTNAME=SMITH'
FIRSTNAME = 'FIRSTNAME=JOHN'
CIA = 'CIA=YES'
SOCIALSECURITY = 'SOCIALSECURITY=999999999'
DACDATE = 'DACDATE=07/16/2022'
UIC = 'UIC=42158'
},[PSCustomObject]#{
FileName = 'C12345'
BADGENUMBER = 'BADGENUMBER=12345'
LASTNAME = 'LASTNAME=SMITH'
FIRSTNAME = 'FIRSTNAME=JOHN'
CIA = 'CIA=YES'
SOCIALSECURITY = 'SOCIALSECURITY=999999999'
DACDATE = 'DACDATE=07/16/2022'
UIC = 'UIC=42158'
}
# Using RegEx -replace to remove the front part
($result | Out-String) -replace '(?m)^[\w\s]+:\s','' | Out-File C:\Temp\test1.txt
# Looping for every properties (they will get reordered by property name)
# I just saw Mathias suggestion and it would produce the same result
$result | Get-Member -Type NoteProperty | ForEach-Object {$result.($_.Name)} | Out-File C:\Temp\test2.txt
# Simplier solution
$output = foreach ($row in $result) {
$row.FileName
$row.BADGENUMBER
$row.LASTNAME
$row.FIRSTNAME
$row.CIA
$row.SOCIALSECURITY
$row.DACDATE
$row.UIC
"" # you probably want to have an empty row seperating each record
}
$output | Out-File C:\Temp\test3.txt