Powershell Out-File output all on the same line - powershell

I have a powershell script that populates a variable, $Users, from the contents of a text file using the Get-Content cmdlet. I then want to append this information to the end of a different text file using Out-File. However, currently the output is appended all in a row. What I need is for each string to be on it's own line.
I have tried piping the variable into the Write-Output cmdlet and it displays correctly on the screen, but when I redirect it from Write-Output back to the Out-File cmdlet it appends the information all in a row again.
$Users = Get-Content "C:\Users\XXXX\Desktop\Password Reset\Users5.txt"<br>
Out-File -InputObject $Users -FilePath "C:\Users\XXXX\Desktop\Password Reset\RefUsers.txt"

If it was me I would use Add-Content for this with a pipe.
$Users = Get-Content -Path "C:\Users\XXXX\Desktop\Password Reset\Users5.txt"
$Users | Add-Content -Path "C:\Users\XXXX\Desktop\Password Reset\RefUsers.txt"
Pay attention to encoding. Add-Content uses ascii by default I believe. Also if you are not doing anything with the data you can skip the variable all together.
GC "C:\Users\XXXX\Desktop\Password Reset\Users5.txt" |
AC "C:\Users\XXXX\Desktop\Password Reset\RefUsers.txt"
Gc being an alias for Get-Content and Ac for Add-Content

Here is how my final script turned out:
$Users = Get-Content "C:\Users\XXXX\Desktop\Password Reset\Users5.txt"
Foreach($U in $Users){
Add-Content "C:\Users\XXXX\Desktop\Password Reset\RefUsers1.txt" "`n$U"
}
Thanks Matt!

Related

Column from powershell query with array list of servers is not exporting properly to csv

need some help with this bit of code. So I have got some powershell that is called from a bit of code as below:
powershell -file "E:\crs\shared\utils\EventViewerExport\EventViewerExport.ps1" "BAUT101,BAUT103,BAUT105,BAUT106,BAUT107,BAUT108,BAUT109,BAUT010"
The powershell code that the above calls is below:
#List of servers:
$ArraySvr = $args[0].split(",") ;
foreach ($Server in $ArraySvr){
$args = #{}
$args.Add("StartTime", ((Get-Date).AddMinutes(-160)))
$args.Add("EndTime", (Get-Date))
$args.Add("LogName", "System")
$args.Add("ID",7001)
Get-WinEvent -FilterHashtable $args -ComputerName $Server | select MachineName,LogName,LevelDisplayName,TimeCreated,ProviderName,ID,#{n='Message';e={(New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])}} | export-csv -Delimiter '|' -Path E:\crs\shared\utils\EventViewerExport\EventViewerExportFile.csv -Append -Force
}
The script is almost 100% perfect, except the "Message" column isn't pulling through the the CSV file while its in the foreach function.
My csv file looks like this:
#TYPE Selected.System.Diagnostics.Eventing.Reader.EventLogRecord
"MachineName"|"LogName"|"LevelDisplayName"|"TimeCreated"|"ProviderName"|"Id"|"Message"
"BAUT101.compname.adp"|"System"|"Information"|"03/03/2022 18:03:15"|"Microsoft-Windows-Winlogon"|"7001"|
However the Message column does pull through when I take out the foreach function, as below:
$args = #{}
$args.Add("StartTime", ((Get-Date).AddMinutes(-160)))
$args.Add("EndTime", (Get-Date))
$args.Add("LogName", "System")
$args.Add("ID",7001)
Get-WinEvent -FilterHashtable $args -ComputerName 'BAUT101' | select MachineName,LogName,LevelDisplayName,TimeCreated,ProviderName,ID,#{n='Message';e={(New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])}} | export-csv -Delimiter '|' -Path E:\crs\shared\utils\EventViewerExport\EventViewerExportFile.csv -Append -Force
By running this set of code with the foreach function, I get the correct csv export:
#TYPE Selected.System.Diagnostics.Eventing.Reader.EventLogRecord
"MachineName"|"LogName"|"LevelDisplayName"|"TimeCreated"|"ProviderName"|"Id"|"Message"
"BAUT101.compname.adp"|"System"|"Information"|"03/03/2022 18:03:15"|"Microsoft-Windows-Winlogon"|"7001"|"compname\djgood"
Does anyone know why on earth the Message column won't export when I'm running the powershell with an array of servers, but it will when I query a specific computer name?
Can anyone help me out please?
Thanks in advance.

Powershell search directory for code files with text matching input a txt file

Data mapping project, in house system to new vendor system. First step is find all the occurrences of current database field names (or column names to be precise) in the C# .cs source files. Trying to use Powershell. Have recently created PS searches with Get-ChildItem and Select-String that work well but the search string array was small and easily hard coded inline. But the application being ported has a couple hundred column names and significant amounts of code. So armed with a text file of all the column names Pipleline would seem like a god tool to create a the basic cross ref for further analysis. However, I was not able to get the Pipeline to work with an external variable anyplace other than first step. Trying using -PipelineVariable, $_. and global variable. Did not find anything specific after lots of searching. P.S. This is my first question to StackoOverflow, be kind please.
Here is what I hoped would work but do dice so far.
$inputFile = "C:\DataColumnsNames.txt"
$outputFile = "C:\DataColumnsUsages.txt"
$arr = [string[]](Get-Content $inputfile)
foreach ($s in $arr) {
Get-ChildItem -Path "C:ProjectFolder\*" -Filter *.cs -Recurse -ErrorAction SilentlyContinue -Force |
Select-String $s | Select-Object Path, LineNumber, line | Export-csv $outputfile
}
Did find that this will print the list one time but not twice. In fact it seems using the variable in this way results in processing simply skipping any further pipeline steps.
foreach ($s in $arr) {Write-Host $s | Write $s}
If it isn't possible to do this in Powershell easily my fallback is to do with C# although would much rather get the level up with PowerShell if anyone can point me to the correct understanding of how to do things in the Pipepline, or alternatively construct an equivalent function. Seems like such a natural fit for Powershell.
Thanks.
You're calling Export-csv $outputfile in a loop, which rewrites the whole file in every iteration, so that only the last iteration's output will end up in the file.
While you could use -Append to iteratively append to the output file, it is worth aking a step back: Select-String can accept an array of patterns, causing a line that matches any of them to be considered a match.
Therefore, your code can be simplified as follows:
$inputFile = 'C:\DataColumnsNames.txt'
$outputFile = 'C:\DataColumnsUsages.txt'
Get-ChildItem C:\ProjectFolder -Filter *.cs -Recurse -Force -ea SilentlyContinue |
Select-String -Pattern (Get-Content $inputFile) |
Select-Object Path, LineNumber, line |
Export-csv $outputfile
-Pattern (Get-Content $inputFile) passes the lines of input file $inputFile as an array of patterns to match.
By default, these lines are interpreted as regexes (regular expressions); to ensure that they're treated as literals, add -SimpleMatch to the Select-String call.
This answer to a follow-up question shows how to include the specific pattern among the multiple ones passed to -Pattern that matched on each line in the output.
I think you want to append each occurrence to the csv file. And you need to get the content of the file. Try this:
$inputFile = "C:\DataColumnsNames.txt"
$outputFile = "C:\DataColumnsUsages.txt"
$arr [string[]](Get-Content $inputfile)
foreach ($s in $arr) {
Get-ChildItem -Path "C:ProjectFolder\*" -Filter *.cs -Recurse -ErrorAction SilentlyContinue -Force | Foreach {
Get-Content "$_.Fullname" | Select-String $s | Select-Object Path, LineNumber, line | Export-csv -Append -Path "$outputfile"
}
}
-Append was not introduced before powershell v3.0 (Windows 8) then try this:
$inputFile = "C:\DataColumnsNames.txt"
$outputFile = "C:\DataColumnsUsages.txt"
$arr [string[]](Get-Content $inputfile)
foreach ($s in $arr) {
Get-ChildItem -Path "C:ProjectFolder\*" -Filter *.cs -Recurse -ErrorAction SilentlyContinue -Force | Foreach {
Get-Content "$_.Fullname" | Select-String $s | Select-Object Path, LineNumber, line | ConvertTo-CSV -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -Path "$outputfile"
}
}

Blank first line when using "select-string -pattern" to strip lines from file

I have a simple text file that looks like this...
A,400000051115,null,null,null,null,null,null,null,20190312,090300,Answer Machine,2019,3,14,10,0
A,400000051117,null,null,null,null,null,null,null,20190312,090300,Confirmed,2019,3,14,10,30
A,400000051116,null,null,null,null,null,null,null,20190312,090300,Answer Machine,2019,3,14,11,0
A,400000051114,null,null,null,null,null,null,null,20190312,090300,Wants to Cancel,2019,3,14,9,0
A,400000051117,null,null,null,null,null,null,null,20190312,091800,SMS Sent,2019,3,14,10,30
A,400000051116,null,null,null,null,null,null,null,20190312,091800,SMS Sent,2019,3,14,11,0
A,400000051115,null,null,null,null,null,null,null,20190312,091800,SMS Sent,2019,3,14,10,0
A,400000051116,null,null,null,null,null,null,null,20190312,093000,Appointment Cancelled/Rescheduled Via SMS,2019,3,14,11,0
I need to save all the lines except those that have "SMS Sent" in them to a new file. I am using the following...
get-content $SourceFile.FullName | select-string -pattern 'SMS Sent' -notmatch | Out-File $targetFile
Why in the resulting file do I get a blank first line?
If you change Out-File $targetFile to Out-Host or even just omit that last segment in the pipeline, you will see a blank line in the console output, too.
The output analog of Get-Content is Set-Content, so if you change Out-File $targetFile to Set-Content $targetFile the first line is no longer blank.
Also, since you're working with a CSV file you could use Import-CSV to read the data and Where-Object to filter on that specific column, although a little extra work is required to specify the headers and omit them from the output file...
$csvHeaders = 1..17 | ForEach-Object -Process { "Column $_" }
$csvHeaders[11] = 'Status'
Import-Csv -Path $SourceFile.FullName -Header $csvHeaders `
| Where-Object -Property 'Status' -NE -Value 'SMS Sent' `
| ConvertTo-Csv -NoTypeInformation `
| Select-Object -Skip 1 `
| Set-Content $targetFile
...which writes...
"A","400000051115","null","null","null","null","null","null","null","20190312","090300","Answer Machine","2019","3","14","10","0"
"A","400000051117","null","null","null","null","null","null","null","20190312","090300","Confirmed","2019","3","14","10","30"
"A","400000051116","null","null","null","null","null","null","null","20190312","090300","Answer Machine","2019","3","14","11","0"
"A","400000051114","null","null","null","null","null","null","null","20190312","090300","Wants to Cancel","2019","3","14","9","0"
"A","400000051116","null","null","null","null","null","null","null","20190312","093000","Appointment Cancelled/Rescheduled Via SMS","2019","3","14","11","0"
...to $targetFile. Note that all of the values are quoted now. If your input file does have headers then you could use simply...
Import-Csv -Path $SourceFile.FullName `
| Where-Object -Property 'Status' -NE -Value 'SMS Sent' `
| Export-Csv -NoTypeInformation -LiteralPath $targetFile
In either case the output file will not contain a leading blank line.

New Line in Export-CSV not working

I want to insert a blank new line when exporting to CSV, but what I get is "1" inserted instead of blank new line. Here is the code I am using:
foreach($Group in $Groups) {
Get-QADGroupMember $Group | select  Name | Export-CSV C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -NoTypeInformation -Append -Encoding UTF8 -UseCulture
$newLine = "`n"
$newLine | Export-CSV C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -NoTypeInformation -Append -Encoding UTF8 -UseCulture
}
Please suggest how I can get a blank new line inserted after every entry made.
It looks like your code is just outputting a single column of group names. If that is the case then I would not even bother with CSV output at that point and just use Set-Content. Adding in the newline then would be fairly easy.
$Groups | ForEach-Object{
(Get-QADGroupMember $_ | Select-Object -ExpandProperty Name) + "`n"
} | Set-Content C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV -Encoding UTF8
I used a more pipeline friendly foreach-object loop so you don't have to keep using append.
Export-Csv tries to "discover" the properties of the object, in this case a string - which only has one property, the Length - which happens to be 1.
Use Add-Content or Out-File -Append -NoNewline (version 5 only) to append to an existing file:
"" |Add-Content -Path C:\Users\Nikhil.Tamhankar\Desktop\temp\GroupsInfo.CSV

Out-File inside a foreach statement

im trying to run this script, it works but every time that it changes from item on the list it erases the file and starts over.
what i need this to do is to get from the list of items all the users and put them all in a single text file.
$sitios = Get-Content -Path C:\sitios.txt
Connect-SPOService -Url https://aaa.sharepoint.com/ -Credential Admin#aaa.onmicrosoft.com
foreach ($sitio in $sitios){
$sitio
Get-SPOUser -Site $sitio -Limit ALL | Out-File -FilePath C:\usuarios.txt
}
any help is appreciated
You could use the -Append switch of Out-File but all you should have to do is move it outside the loop.
(foreach ($sitio in $sitios){
Write-Host $sitio
Get-SPOUser -Site $sitio -Limit ALL
}) | Out-File -FilePath C:\usuarios.txt
That way all output will be sent to Out-File. I added Write-Host $sitio so that was not going to be in the file. You could also use Set-Content which is considered the preferential choice over Out-File
The brackets are needed around the loop so that we can use the pipe output. That foreach construct cannot have data directly piped from it. An answer here covers the reason.
That all being said you could then do something like this
$sitios | ForEach-Object{
Write-Host $_
Get-SPOUser -Site $_ -Limit ALL
} | Set-Content C:\usuarios.txt
This output should be a complex object that might not have a proper tostring equivalent. You can still get all the data with something like this instead.
$sitios | ForEach-Object{
Write-Host $_
Get-SPOUser -Site $_ -Limit ALL
} | Export-CSV C:\usuarios.txt -NoTypeInformation
You can use the Add-Content Cmdlet:
https://technet.microsoft.com/en-us/library/ee156791.aspx
Instead of Out-File use Add-Content
as in:
[...] | Add-Content C:\usuarios.txt