Add line breaks to Out-File cmdlet - powershell

I am trying to get the list of computers that has no antivirus but the out file is with computer names in one single line, can anyone help?
ForEach ($COMPUTER in (Get-ADComputer -Filter {OperatingSystem -notLike '*windows xp*' } | Select-Object -ExpandProperty Name))
{if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{write-host "cannot reach $computer" -f red}
else {
try
{
$AntiVirusProduct = Get-WmiObject -Namespace "root\SecurityCenter2" -Class AntiVirusProduct -ComputerName $computer -ErrorAction Stop
}
catch
{
Write-Warning "[ERROR] invalid namespace [$($computer)] : $_"
$noantivirus+=$computer
}
$noantivirus | out-file -Encoding Ascii -append c:\noantivirus.txt}}

You can try to join them by a NewLine:
$noantivirus -join [System.Environment]::NewLine | out-file -Encoding Ascii -append c:\noantivirus.txt
If this doesn't work, try with rn:
$noantivirus -join "`r`n" | out-file -Encoding Ascii -append c:\noantivirus.txt

I found it
$noantivirus = Add-Content c:\noantivirus.txt "`n$computer"

Related

powershell returning Get-ADComputer : The object name has bad syntax

I want to get all of the computers in a specific OU and ping them, but Im having trouble with Get-ADComputer.
code:
# Enter CSV file location
$csv = "filepath.csv"
# Add the target OU in the SearchBase parameter
$Computers = Get-ADComputer -Filter * -SearchBase "OU=Servers,DC=mydomain,DC=com" | Select Name | Sort-Object Name
$Computers = $Computers.Name
$Headers = "ComputerName,IP Address"
$Headers | Out-File -FilePath $csv -Encoding UTF8
foreach ($computer in $Computers)
{
Write-host "Pinging $Computer"
$Test = Test-Connection -ComputerName $computer -Count 1 -ErrorAction SilentlyContinue -ErrorVariable Err
if ($test -ne $null)
{
$IP = $Test.IPV4Address.IPAddressToString
$Output = "$Computer,$IP"
$Output | Out-File -FilePath $csv -Encoding UTF8 -Append
}
Else
{
$Output = "$Computer,$Err"
$output | Out-File -FilePath $csv -Encoding UTF8 -Append
}
cls
}
and im getting:
Get-ADComputer : The object name has bad syntax
At script.ps1:2 char 14
+ ... omputers = Get-ADComputer -Filter * -SearchBase "OU=Servers, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+CategoryInfo : NotSpecified: (:) [Get-ADComputer], ADException
+FullyQualifiedErrorId : ActiveDirectoryServer:8335,Microsoft,ActiveDirectory,Management,Command.GetADComputer
ps. this code is taken from here. yes I know Im not supposed to do that but after getting this error
time after time I wanted to try a code that works.
Double check that the OU you're using as the search base is correct. This error occurs when it's off.
Apart from that, I recommend using the System.Net.NetworkInformation.Ping class. It's a lot faster than Test-Connection because you have more control over the ping timeout.
$ping = New-Object System.Net.NetworkInformation.Ping
$pingTimeutMS = 200
$computers = Get-ADComputer -Filter * -SearchBase "OU=Servers,DC=mydomain,DC=com"
$results = $computers | Sort-Object Name | ForEach-Object {
$ComputerName = $_.Name
Write-Host "Pinging $ComputerName..."
$test = $ping.Send($ComputerName, $pingTimeutMS)
[pscustomobject]#{
"Computer" = $ComputerName
"IP Address" = if ($test.Status -eq "Success") { $test.Address } else { $test.Status }
}
}
$results | Export-Csv "filepath.csv" -Delimiter ',' -NoTypeInformation -Encoding UTF8
Not appending the lines to the CSV piecemeal feels a bit less clunky, too.

Out-File unnecessary characters

I have the script below which pings a list of machines, outputs the result to CSV and gets the lastlogontimestamp of the machine.
It works fine, except the lastlogontimestamp comes out like this:
CCC-APP01,172.22.100.15,#{lastLogonDate=07/25/2018 13:24:54}
How can I get rid of the extra characters: #{lastlogondate=...}?
$OutputCSV = "C:\TEMP\OUPingResults.csv"
$SearchLocation = "OU=AA,OU=Servers,DC=LocA,DC=XYZ,DC=com"
$Computers = Get-ADComputer -Filter * -SearchBase $SearchLocation |
Select Name |
Sort-Object Name
$Computers = $Computers.Name
$Headers = "ComputerName,IP Address,LastLogonTimeStamp"
$Headers | Out-File -FilePath $OutputCSV -Encoding UTF8
foreach ($computer in $Computers) {
Write-host "Pinging $Computer"
$Test = Test-Connection -ComputerName $computer -Count 1 -ErrorAction SilentlyContinue -ErrorVariable Err
if ($test -ne $null) {
$IP = $Test.IPV4Address.IPAddressToString
$LastLogonTimeStamp = Get-ADComputer $Computer -Prop CN,lastLogonTimestamp |
Select #{n="lastLogonDate";e={[datetime]::FromFileTime($_.lastLogonTimestamp)}}
$Output = "$Computer,$IP,$LastLogonTimeStamp"
$Output | Out-File -FilePath $OutputCSV -Encoding UTF8 -Append
} else {
$Output = "$Computer,$Err"
$Output | Out-File -FilePath $OutputCSV -Encoding UTF8 -Append
}
}
The expression ... |Select-Object #{N='SomeName';E={"SomeValue"}} will produce an object that has a property named SomeName with the value "SomeValue".
What you see in the output is a string representation of this object.
If you want only the value, change the $LastLogonTimeStamp assignment to:
$LastLogonTimeStamp = [datetime]::FromFiletime((Get-ADComputer $Computer -Prop lastLogonTimestamp).lastLogonTimestamp)

Parse String with PowerShell

I'm getting a report for users. The 'membership of' is a string with all the groups per user between double quotes.
I need to place \ between each group. Now I have:
"GROUP1""GROUP2""GROUP3"
And I need:
"GROUP1"\"GROUP2"\"GROUP3"
Right now my code is:
foreach ($server in $servers) {
$Comp = $server
if (test-connection -computername $Comp -count 1 -quiet) {
([ADSI]"WinNT://$comp").Children | ?{$_.SchemaClassName -eq 'user'} | %{
$groups = $_.Groups() | %{$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
$_ | Select #{n='Server';e={$comp}},
#{n='DistingishedName';e={$_.AdsPath}},
#{n='Nombre';e={$_.FullName}},
#{n='Departamento';e={$_.Department}},
#{n='Email';e={$_.EmailAddress}},
#{n='Active';e={if ($_.PasswordAge -like 0) {$false} else {$true}}},
#{n='PasswordExpired';e={if ($_.PasswordExpired) {$true} else {$false}}},
#{n='LastLogin';e={$_.LastLogin}},
#{n='Description';e={$_.Description}},
#{n='Groups';e={$Groups -join '"'}}
} | Export-Csv $ReportFile -Delimiter ';' -Force -Encoding UTF8 -NoTypeInformation -Append
} else {
Write-Warning "Server '$Comp' is Unreachable hence Could not fetch data" 3>> $LogFile
}
}
try -join '"\"' instead of -join '"'

How to check if hotfix KBxxxxxx (example: KB4012212) is installed in the PC or not?

I will create (with PowerShell script) a table and add the result(Positive/negative) to it.
I have a text file computers.txt, in which all PCs are listed.
Like this
CSNAME Hotfixinfo
PC1 is installed
PC2 is not installed
PC3 is installed
etc.
With my actual script I can only see the positive result.
Get-Content .\computers.txt | Where {
$_ -and (Test-Connection $_ -Quiet)
} | foreach {
Get-Hotfix -Id KB4012212 -ComputerName $_ |
Select CSName,HotFixID |
ConvertTo-Csv |
Out-File "C:\$_.csv"
}
I'd suggest parsing through and handling the positive and negative results (also faster than the pipeline ForEach-Object):
:parse ForEach ($Computer in (Get-Content C:\Path\computers.txt))
{
If (Test-Connection $Computer -Quiet)
{
$Result = Get-Hotfix -Id KB4012212 -ComputerName $Computer -ErrorAction 'SilentlyContinue'
If ($Result)
{
$Result |
Select-Object -Property CSName,HotFixID |
ConvertTo-Csv -NoTypeInformation |
Out-File "C:\$Computer.csv"
Continue :parse
}
"`"CSName`",`"HotFixID`"`r`n`"$Computer`",`"NUL`"" |
Out-File "C:\$Computer.csv"
} Else { Write-Host 'Unable to connect to $Computer' }
}

Why does this outputting numbers in the file not the machine name?

The file that I'm outputting doesnt contain the $machine and if its valid or not, it contains numbers. How do I get this to output the machine name and if its valid or not?
Import-Module ActiveDirectory
$enddate = Get-Date
$machines=(Get-ADComputer -filter * -SearchBase 'OU=this,OU=is,OU=my,DC=domain,DC=com' -Properties * | Select Name, lastlogondate |Where-Object {$_.LastLogonDate -lt ($enddate).AddMonths(-2)} |Sort lastlogondate).name
foreach ($machine in $machines)
{
if (test-Connection -ComputerName $machine -count 1 -ErrorAction SilentlyContinue)
{
Write-Output "$machine is valid"
}
Write-Output "$machine is not valid" | Export-Csv
c:\machine_not_valid.csv -Append -NoClobber -NoTypeInformation
}
Export-Csv expects an object, not a string. It then uses the properties of this object as headers for the CSV.
It is outputting numbers because it is receiving string as input, which has the single property Length
You also have an error in your code where the "$machine is not valid" part is outside of the if statement and not in an else statement.
If you have multiple values, Export-Csv is the way to go. If you only have one, use Out-Fileas you will not need to create an object:
Import-Module ActiveDirectory
$enddate = Get-Date
$machines=(Get-ADComputer -filter * -SearchBase 'OU=this,OU=is,OU=my,DC=domain,DC=com' -Properties * | Select Name, lastlogondate |Where-Object {$_.LastLogonDate -lt ($enddate).AddMonths(-2)} |Sort lastlogondate).name
foreach ($machine in $machines)
{
if (test-Connection -ComputerName $machine -count 1 -ErrorAction SilentlyContinue)
{
Write-Output "$machine is valid"
}else{
Write-Output "$machine is not valid" | Export-Csv c:\machine_not_valid.csv -Append -NoClobber
}
}