PowerShell for-each loop output to file - powershell

How do I output/append the contents of this foreach loop to a text file?
The following below is not working out.
$Groups = Get-AdGroup -Properties * -filter * | Where {$_.name -like "www*"}
Foreach($G in $Groups)
{
write-host " "
write-host $G.Name
write-host "----------"
get-adgroupmember -Identity $G | select-object -Property SamAccountName
Out-File -filepath C:\test.txt -Append
}

$output =
Foreach($G in $Groups)
{
write-output " "
write-output $G.Name
write-output "----------"
get-adgroupmember -Identity $G | select-object -Property SamAccountName
}
$output | Out-File "C:\Your\File.txt"
All this does is saves the output of your foreach loop into the variable $output, and then dumps to data to your file upon completion.
Note: Write-Host will write to the host stream, and not the output stream. Changing that to Write-Output will dump it to the $output variable, and subsequently the file upon loop completion.
The reason your original code isn't working is that you're not actually writing anything to the file. In other words, you're piping no data to your Out-File call. Either way, my approach prefers a cache-then-dump methodology.

Related

How to Output to a Log File

How can I output the screen results to a txt file when I run this code?
#removes disabled clinical or corp accounts from SGs in the I-Drive OU
$searchOU = "OU=I-Drive,OU=SAS,OU=Application Security Groups,OU=Groups,OU=Enterprise,DC=z,DC=x,DC=y"
Get-ADGroup -Filter 'GroupCategory -eq "Security"' -SearchBase $searchOU | ForEach-Object{ $group = $_
Get-ADGroupMember -Identity $group | Get-ADUser | Where-Object {$_.Enabled -eq $false} | ForEach-Object{ $user = $_
$uname = $user.Name
$gname = $group.Name
Write-Host "Removing $uname from $gname" -Foreground Yellow
Remove-ADGroupMember -Identity $group -Member $user -Confirm:$false
}
}
Pipe the output of Get-ADGroup to Set-Content like so:
Get-ADGroup -Filter 'GroupCategory -eq "Security"' -SearchBase $searchOU | ForEach-Object{
$group = $_
Get-ADGroupMember -Identity $group | Get-ADUser | Where-Object { $_.Enabled -eq $false} | ForEach-Object{
$user = $_
$uname = $user.Name
$gname = $group.Name
Write-Host "Removing $uname from $gname" -Foreground Yellow
Remove-ADGroupMember -Identity $group -Member $user -Confirm:$false
}
} | Set-Content filename.txt
If you want any additional output (warnings, verbose, errors) change the last line a bit to redirect the other streams:
} *>&1 | Set-Content filename.txt
Alternatively, you can also use the built-in transcript logging to log everything to a file as well just call one of the following from within your script:
Start-Transcript
or if you want the log to go to a specific place:
Start-Transcript -Path "\Path\To\LogFile.log"
Note that transcript logging is more useful in scripts than during an interactive session.
Store the value you'd like to log in a variable say $abc
Write to log file and keep appending $abc | Out-File -FilePath "C:\Somewhere\log.txt" -Append -Encoding UTF8
Refer - Log output of ForEach loop

Get specific info on domain computers from AD OUs

I'm trying to Get the Name, Manufacturer, and model of computers so i can distinguish what computers are out of warranty in AD.
I'm trying to do this by getting the computer names and putting there info into the corresponding .csv file but this fails and puts 1 ou to multiple .csv files and then moves to the second ou and does the same thing?
$myMultiArray = #(("OU=Domain Controllers,DC=FABRIKAM,DC=COM"),
("OU=Computers,DC=FABRIKAM,DC=COM"))
$myFileArray = #(("‪D:\VS-Code\Powershell\AD_Computer_Management\OUs\Domain
Controllers.csv"),("‪D:\VS-
Code\Powershell\AD_Computer_Management\OUs\Computers.csv"))
foreach ($MultiOU in $myMultiArray) {
Get-ADComputer -Filter * -SearchBase $MultiOU -SearchScope 2 | Select-object Name | Out-File -FilePath "D:\VS-Code\Powershell\AD_Computer_Management\OUs\garbage.csv"
For ($i = 0; $i – $myFileArray.Length - 1; $i++) {
Write-Host $myMultiArray[$i]
[string[]]$cnArray = Get-Content -Path 'D:\VS-Code\Powershell\AD_Computer_Management\OUs\garbage.csv'
Write-Host $OU
if ($i -eq $i) {
foreach($CN in $cnArray){
Get-WmiObject -Class:Win32_ComputerSystem -ComputerName $OU | Format-List -Property Name, Manufacturer, Model | Out-File -FilePath $myFileArray[$1]
}
}
}
}
I've tried multiple variations of different loops and if statements.
I think there are two things:
Out-File -FilePath $myFileArray[$1]
Should be:
Out-File -FilePath $myFileArray[$i]
And also you might need to append:
Out-File -FilePath $myFileArray[$i] -Append
There are a couple of things wrong in your code, like $i – $myFileArray.Length, which should be $i –lt $myFileArray.Length.
Then there is Out-File -FilePath $myFileArray[$1] as Bernard Moeskops already mentioned.
Also your code seems to want to create both the Domain Controllers.csv aswell as the Computers.csv files regardless of the OU you are currently in.
Lastly, you are using Out-File to create the CSV files where for proper CSV output, you should use the Export-Csv cmdlet.
The following code should do what you want:
$myOUArray = "OU=Domain Controllers,DC=FABRIKAM,DC=COM", "OU=Computers,DC=FABRIKAM,DC=COM"
$myFilePath = "‪D:\VS-Code\Powershell\AD_Computer_Management\OUs" # just the path for the output files is needed
foreach ($OU in $myOUArray) {
# determine the file name from the OU we're in
$fileName = if ($OU -match 'OU=Domain Controllers') { 'Domain Controllers.csv' } else { 'Computers.csv'}
$filePath = Join-Path -Path $myFilePath -ChildPath $fileName
Write-Host "Getting computer info from OU '$OU'"
# get a string array of the computernames found in the OU
$computers = Get-ADComputer -Filter * -SearchBase $OU -SearchScope Subtree | Select-Object -ExpandProperty Name
# loop through this array to get the properties you want for
# each computer and store that as objects in the $result variable
$result = foreach($machine in $computers){
Get-WmiObject -Class:Win32_ComputerSystem -ComputerName $machine | Select-Object -Property Name, Manufacturer, Model
}
Write-Host "Creating file '$filePath'"
# save the CSV file to disk
$result | Export-Csv -Path $filePath -NoTypeInformation -Force
}

Foreach loop and writing the results to a file

I'm working on a script which iterates through all users found across a domain, grabs a few credentials and then returns them in the format of an SQL INSERT statement which I want stored in a .txt file as output.
So far I've only been able to write the last user to a file however I'm able to print out in the terminal every single user. I have a feeling that I'm overwriting the .txt output file each time I iterate through my foreach loop.
Below is my code which has been sanitised:
$users = Get-ADUser -Properties uidNumber, sAMAccountName -SearchBase' OU=LiveUsers,OU=Users,OU=MyBusiness,DC=local' -Filter *
$message = ""
Set-Content -Path C:\Desktop\UIDs\currentList.txt -Value $null # ensures file is blank
foreach ($user in $users | Select-Object -Property uidNumber, sAMAccountName){
#Search in specified OU and List above for UID and name and write to a file
$message = "INSERT INTO `DataBaseNameHere`.`currentUser` (`User_id`, `User_name`) VALUES ('" + $user.uidNumber + "', '" + $user.sAMAccountName + "');" |
Out-File -FilePath C:\Desktop\UIDs\currentList.txt
}
Get-Content -Path C:\Desktop\UIDs\currentList.txt
I've tried other variations of foreach loops, Out-File and Tee-Object so far.
Assuming that the sanitized code you provided does what you want except for leaving only a single line in the output file, you need to ensure that you have either no existing output file or that it's blank, and then you add the -append switch to the Out-File cmdlet:
$users = Get-ADUser -Properties uidNumber, sAMAccountName -SearchBase 'OU=LiveUsers,OU=Users,OU=MyBusiness,DC=local' -Filter *
Set-Content -Path C:\Desktop\UIDs\CurrentList.txt -Value $null # ensures file is blank
foreach ($user in $users | Select-Object -Property uidNumber, sAMAccountName) {
$message = "INSERT INTO `databaseNameHere`.`currentUser` (`User_id`, `User_name`) VALUES ('" + $user.uidNumber + "', '" + $user.sAMAccountName + "');"
Out-File -FilePath C:\Desktop\UIDs\currentList.txt -append # -append added to not overwrite existing content.
}
See Out-File at Microsoft Docs.
The code you posted would not write anything to a file since the loop defines $message without doing anything with it, and then calls Out-File without any input.
Something like this should do what you want:
Get-ADUser ... |
Select-Object uidNumber, sAMAccountName |
ForEach-Object { "INSERT INTO `databaseNameHere`.`currentUser` (...);" } |
Out-File -FilePath C:\Desktop\UIDs\currentList.txt
Beware though, that building INSERT statements that way is vulnerable to SQL injection and should be avoided.
So, after taking elements from a few of your answers I was able to modify my code and fix the loop. I was just using the Out-File cmdlet wrong.
$users = Get-ADUser -Properties uidNumber, sAMAccountName -SearchBase 'OU=LiveUsers,OU=Users,OU=MyBusiness,DC=myCompany,DC=local' -filter *
Clear-Content -Path C:\Desktop\UIDs\CurrentList.txt
foreach ($user in $users ){
“INSERT INTO `databasename`.`currentUser` (`User_id`, `User_name`) VALUES ('"+ $user.uidNumber + "','"+ $user.sAMAccountName +"');" |
Out-File -FilePath C:\Desktop\UIDs\CurrentList.txt -Append
}

How to check a list of groups to see if there are members

I've been working on a script to run through a list of groups in a CSV file to see if they have any members.
Ultimately I'm looking to have the script export the results to a separate CSV file.
$groups = Get-Content 'C:\Users\me\Desktop\testGroups.csv'
foreach ($groups in $groups) {
$users = Get-ADGroupMember -Identity $groups
if (($users | Measure-Object).Count -ne 0) {Write-Output "$groups has something" | Out-File C:\Users\me\Desktop\membersTest.csv -Append}
Else {Write-Output "$groups has nothing" | Out-File C:\Users\me\Desktop\membersTest.csv -Append}
}
This returns the following:
Length
27
31
41
30
...
I've attempted to change Write-Output to Write-Host and that appears to return the correct results, but it only displays it within the CMD window obviously.
Would someone be able to assist me with the process of correcting these IF Else statements?
End result is a csv, so build an object and export it.
$groups = Get-Content 'C:\Users\me\Desktop\testGroups.csv'
$GroupMemberCount = ForEach ($group in $groups) {
[PSCustomObhect]#{
Group = $group
MemberCount = (Get-ADGroupMember -Identity $group).Count
}
}
$GroupMemberCount | Out-Gridview
$GroupMemberCount | Export-Csv 'C:\Users\c002568\Desktop\membersTest.csv' -NoTypeInformation
I had this similar script for another project which might be helpful, I've modified to match your query. If you don't have need to display output, you can ignore that.
$groups = import-csv groups.csv
$outputFile = New-Item -ItemType file testOutputCSV.CSV -Force
foreach ($group in $groups) {
[array]$users = Get-ADGroupMember -Identity $group.samaccountname
if($users.count -ne 0){
Write-Output "$($group.samaccountname) has something "
}
else {
Write-Output "$($group.samaccountname) has 0 members"
}
$group.samaccountname +","+$users.count | Out-File $outputFile -Append
}
If the intention is to highlight the groups not having any members on console, as well as CSV, you can bring this line inside IF Else block, add more columns as needed.
$group.samaccountname +","+$users.count | Out-File $outputFile -Append
If you don't need to display anything on the console, you can omit IF Else block.
If you want to update CSV only for groups having 0 members or non-zero members, you can modify accordingly.
Edit: Masked $Users to be [array] since single member groups would return ADPrincipal

Work with ADComputer output in foreach loop

I want to output all hostnames within a network first with a foreach loop, in order (for example) to be able to ping them.
However with the following code I do not get any output in the console. The CSV file will be saved, but what is written in the loop will not be executed.
Does anyone know what the reason for this is and how I can solve it?
Import-Module activedirectory
Get-ADComputer -Filter * -Property * | Select Name | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8 | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
}
This occurs because Export-CSV does not output an object. Sometimes cmdlets like this have a -PassThru parameter which you can use to have an object passed along, but thats not the case with Export-CSV, they simply expect it to always be the last cmdlet in the pipeline.
You should instead do this:
$Computers = Get-ADComputer -Filter * -Property * | Select Name
$Computers | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8
$Computers | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
}
You could also do this:
Get-ADComputer -Filter * -Property * | Select Name | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
$_
} | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8
Noting that we have to add $_ to our ForEach-Object loop so that it outputs the current item to the pipeline, but that our Write-Host statements don't effect the pipeline because they are writing to the console only. To be honest though, this is a bit harder to follow for anyone else reading your code.