Export only the machines that meets criteria - powershell

I have a script that works great but I would like to only export the machines that meet one of the three conditions in the foreach statement. Right now it exports all the machines, which I have to clean up manually in excel.
#Create an LDAP searcher object and pass in the DN of the domain we wish to query
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://DC=ten,DC=thomsonreuters,DC=com")
#Pass in the ceriteria we are searching for.
#In this case we're looking for computers that are enabled and running Windows 7
$Searcher.Filter = "(&(objectCategory=computer)(objectClass=computer)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(operatingSystem=Windows 7*))"
$Searcher.PageSize = 100000
# Populate General Sheet(1) with information
$results = $Searcher.Findall()
$results | ForEach-Object { $_.GetDirectoryEntry() } |
select #{ n = 'CN'; e = { ($_.CN) } },
#{ n = 'DistinguishedName'; e = { $_.DistinguishedName } },
#{ n = 'extensionattribute7'; e = { $_.extensionattribute7 } },
#{ n = 'extensionattribute1'; e = { $_.extensionattribute1 } },
#{ n = 'NewComputerName'; e = { 'Filler' } } |
Export-Csv 'C:\temp\Windows7_Only.csv' -NoType -Force
$csv = Import-Csv -Path "c:\Temp\Windows7_Only.csv"
foreach ($row in $csv)
{
if (($row.CN -notmatch '^U\d{7}') -and ($row.DistinguishedName -like "*Laptops*") -and ($row.extensionattribute7 -match '^U\d{7}$') -and ($row.CN -notmatch '\d{3}'))
{
$row.NewComputerName = $row.extensionattribute7 + "-TPL-ZZ"
}
elseif (($row.CN -notmatch '^U\d{7}') -and ($row.DistinguishedName -like "*Desktops*") -and ($row.extensionattribute7 -match '^U\d{7}$') -and ($row.CN -notmatch '\d{3}'))
{
$row.NewComputerName = $row.extensionattribute7 + "-TPD-ZZ"
}
elseif (($row.CN -notmatch '^U\d{7}') -and ($row.DistinguishedName -like "*Virtual*") -and ($row.extensionattribute7 -match '^U\d{7}$') -and ($row.CN -notmatch '\d{3}'))
{
$row.NewComputerName = $row.extensionattribute7 + "-TPV-ZZ"
}
}
$csv | export-csv c:\temp\fixed.csv -NoTypeInformation -Force

Try this:
$csv = $csv | where { ($_.CN -notmatch '^U\d{7}') -and ($_.CN -notmatch '\d{3}') -and ($_.extensionattribute7 -match '^U\d{7}$') -and (($_.DistinguishedName -like "*Laptops*") -or ($_.DistinguishedName -like "*Desktops*") -or ($_.DistinguishedName -like "*Virtual*")) }
Before the final line. It should filter out any ones that haven't met any of the criteria in the foreach loop

Related

Where-Object to match from Left to Right on all prerequires?

See the below example code.
I have several objects I need to match on several prerequires.
Lets say I want my Where-Object to not match when the NameRegex is one of the 2 values, the name not equals DisplayName1 and the AccessRights not match.
This means that when I run the below code I want to get Object $User1 back.
This is not happening what so ever.
Should I do this the other way around and then match them in some sort of hashtable?
Has anyone figured this out for a single Where-Object?
$User1 = [PSCustomObject]#{
Name = 'Name1'
DisplayName = 'DisplayName1'
AccessRights = 'AccessRights1'
}
$User2 = [PSCustomObject]#{
Name = 'Name2'
DisplayName = 'DisplayName2'
AccessRights = 'AccessRights2'
}
$User3 = [PSCustomObject]#{
Name = 'Name3'
DisplayName = 'DisplayName3'
AccessRights = 'AccessRights3'
}
$Test = $User1,$User2,$User3
$NameRegex = '^Name2$|^Name3'
$ACRegex = '^AccessRights2$|^AccessRights3$'
$Test | Where-Object { $_.Name -notmatch $NameRegex -and $_.DisplayName -ne 'DisplayName1' -and $_.AccessRights -notmatch $ACRegex }
And some others I've tried:
$Test | Where-Object { ($_.Name -notmatch $NameRegex -and $_.DisplayName -ne 'DisplayName1' -and $_.AccessRights -notmatch $ACRegex) }
$Test | Where-Object { ((($_.Name -notmatch $NameRegex) -and $_.DisplayName -ne 'DisplayName1') -and $_.AccessRights -notmatch $ACRegex) }
$Test | Where-Object {$_ -notmatch ((($_.Name -notmatch $NameRegex) -and $_.DisplayName -ne 'DisplayName1') -and $_.AccessRights -notmatch $ACRegex) }

Creating new PsObject

I must be doing something wrong here results are empty, I tried converting html with PsObject it requires -Append that creates multiple html tables and not suited to send an email, any help appreciated.
Foreach($sender in $senders){
$users=Get-TransportServer|Get-MessageTrackingLog -Start (Get-Date).AddHours(-4) -ResultSize Unlimited -Sender $sender.PrimarySmtpAddress |?{$_.Recipients -notlike "*#domain.us" -and $_.RecipientCount -eq "1" -and $_.RecipientStatus -notlike "*,*" -and $_.eventid -eq 'RECEIVE' }
}
$users | % {
$t = New-Object PSObject -Property #{
Sender = $_.Sender
Receiver = $_.Recipients
Messagesubject=$_.Messagesubject
RecipientCount =$_.RecipientCount
TimeStamp=$_.TimeStamp
}
$outtbl += $t
}
$outtbl
Why do you need $users, $outtbl, or $t?
foreach ( $sender in $senders ) {
Get-TransportServer |
Get-MessageTrackingLog -Start (Get-Date).AddHours(-4) -ResultSize Unlimited -Sender $sender.PrimarySmtpAddress |
Where-Object { ($_.Recipients -notlike "*#domain.us") -and
($_.RecipientCount -eq 1) -and
($_.RecipientStatus -notlike "*,*") -and
($_.eventid -eq 'RECEIVE') } | ForEach-Object {
[PSCustomObject] #{
Sender = $_.Sender
Receipients = $_.Recipients
MessageSubject = $_.MessageSubject
RecipientCount = $_.RecipientCount
TimeStamp = $_.TimeStamp
}
}
}
(Not tested - this is just an example of how to eliminate unnecessary variables and write clearer code.)
This code sample requires PowerShell 3.0 or newer because it uses [PSCustomObject].
This was it
foreach ( $sender in $senders ) {
Get-TransportServer |
Get-MessageTrackingLog -Start (Get-Date).AddHours(-4) -ResultSize Unlimited -Sender $sender.PrimarySmtpAddress |
Where-Object { ($_.Recipients -notlike "*#domain.us") -and
($_.RecipientCount -eq 1) -and
($_.RecipientStatus -notlike "*,*") -and
($_.eventid -eq 'RECEIVE') } | ForEach-Object {
$results += New-Object PSObject -Property #{
Sender = $_.Sender
Receiver = $_.Recipients
MessageSubject = $_.MessageSubject
RecipientCount = $_.RecipientCount
TimeStamp = $_.TimeStamp
}
}
}
$results| ConvertTo-Html -Head $style| Out-File $reportpath

Format Array inside array to later use as an E-Mail body

I create an empty $array early in my script and later i loop over some stuff and want to add this stuff to my array. This works as intended.
$AspxFiles = gci $path $filter -r | ? { $_.DirectoryName -notlike '*Werkstatt*' -and `
$_.DirectoryName -notlike '*- Kopie*' -and `
$_.DirectoryName -notlike '*.1*' -and `
$_.DirectoryName -notlike '*.0*' -and `
$_.DirectoryName -notlike '*.2*' -and `
$_.Name -notlike '*- Kopie*'
}
$array = #()
foreach ($file in $AspxFiles)
{
$getURL = sls -Path $file.FullName -Pattern $regex -AllMatches | ? { $_ -notlike '*www.w3.org*' -and `
$_ -notlike '*jquery.com*' -and `
$_ -notlike '*www.mwe*' } |
% { $_.Matches } | % { $_.Value }
foreach ($URL in $getURL)
{
$Request = [System.Net.WebRequest]::Create($URL)
$Response = $Request.GetResponse()
$Status = [int]$Response.StatusCode
if ($Status -ne 200 -or $Response.ResponseUri -like '*PageNotFound*')
{
$x = [PSCustomObject] #{
File = $file.Name
URL = $URL
} ; $array += $x
}
$Response.Close()
}
}
But the output of $array is like this:
#{File=B-1.56.aspx; URL=http://sdfsdfsdf/b-1.39.4_fr1_d.pdf}
#{File=B-1.56.aspx; URL=http://sdfsdfsdfssd/b-1.39.4_fr1_d.pdf}
#{File=B-1.58.aspx; URL=https://sdfffssd/b-1.39.6_de_d.pdf}
#{File=B-1.58.aspx; URL=https://fsdfsfb-1.39.6_de_d.pdf}
How can I get this formatted like a list so I can grab the File and URL Property to send it as an E-Mail body like this?:
$body = $array | sort File | ConvertTo-Html -Property File,URL -Head "<html><h2>Folgende Links wurden im Katalog nicht gefunden:</h2><br></html>" | Out-String
Looks like this is still only a part of your script but:
I'd transform your anded wildcards into a -notmatch RegEx with OR'ed | entries
and set $array = Foreach($file ... gathering all ouput
$REDir = '.*Werkstatt.*|.*- Kopie.*|.*\.[012].*'
$REURL = '.*www\.w3\.org.*|.*jquery\.com.*|.*www.mwe.*'
$AspxFiles = Get-ChildItem $path $filter -r |
Where-Object { $_.DirectoryName -notmatch $REDir -and `
$_.Name -notlike '*- Kopie*'}
$array = #()
$array = foreach ($file in $AspxFiles) {
$getURL = Select-String -Path $file.FullName -Pattern $regex -AllMatches |
Where-Object { $_ -notmatch $REURL } |
ForEach-Object { $_.Matches } | ForEach-Obkect { $_.Value }
ForEach ($URL in $getURL) {
$Request = [System.Net.WebRequest]::Create($URL)
$Response = $Request.GetResponse()
$Status = [int]$Response.StatusCode
if ($Status -ne 200 -or $Response.ResponseUri -like '*PageNotFound*') {
[PSCustomObject] #{
File = $file.Name
URL = $URL
}
}
$Response.Close()
}
}
$body = $array | Sort-Object File |
ConvertTo-Html -Property File,URL -Head `
"<html><h2>Folgende Links wurden im Katalog nicht gefunden:</h2><br></html>" |
Out-String

PowerShell - Add string between outputs

I'm trying to separate by a string (;), results from this :
$MasterKeys = ($MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} | select-String Name,Version,ComputerName | sort Name| ft -hide )
Here is the output of this command:
HP ePrint SW 5.1.20088 LT00438
I would like this instead:
HP ePrint SW; 5.1.20088; LT00438
Well, this is the full code :
I don't know where to put the Export-Csv -Path "file.txt" -Delimiter ";" -NoTypeInformation function :(
Function Get-InstalledSoftware
{
Param
(
[Alias('Computer','ComputerName','HostName')]
[Parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true,Position=1)]
[string[]]$Name = $env:COMPUTERNAME
)
Begin
{
$LMkeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall","SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
$LMtype = [Microsoft.Win32.RegistryHive]::LocalMachine
$CUkeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
$CUtype = [Microsoft.Win32.RegistryHive]::CurrentUser
}
Process
{
ForEach($Computer in $Name)
{
$MasterKeys = #()
If(!(Test-Connection -ComputerName $Computer -count 1 -quiet))
{
Write-Error -Message "Unable to contact $Computer. Please verify its network connectivity and try again." -Category ObjectNotFound -TargetObject $Computer
Break
}
$CURegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($CUtype,$computer)
$LMRegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($LMtype,$computer)
ForEach($Key in $LMkeys)
{
$RegKey = $LMRegKey.OpenSubkey($key)
If($RegKey -ne $null)
{
ForEach($subName in $RegKey.getsubkeynames())
{
foreach($sub in $RegKey.opensubkey($subName))
{
$MasterKeys += (New-Object PSObject -Property #{
"ComputerName" = $Computer
"Name" = $sub.getvalue("displayname")
"SystemComponent" = $sub.getvalue("systemcomponent")
"ParentKeyName" = $sub.getvalue("parentkeyname")
"Version" = $sub.getvalue("DisplayVersion")
})
}
}
}
}
ForEach($Key in $CUKeys)
{
$RegKey = $CURegKey.OpenSubkey($Key)
If($RegKey -ne $null)
{
ForEach($subName in $RegKey.getsubkeynames())
{
foreach($sub in $RegKey.opensubkey($subName))
{
$MasterKeys += (New-Object PSObject -Property #{
"ComputerName" = $Computer
"Name" = $sub.getvalue("displayname")
"SystemComponent" = $sub.getvalue("systemcomponent")
"ParentKeyName" = $sub.getvalue("parentkeyname")
"Version" = $sub.getvalue("DisplayVersion")
})
}
}
}
}
$files = "inventaireLT.txt"
$MasterKeys = ($MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} | select Name,Version,ComputerName | sort Name| ft -hide )
$MasterKeys >> $files
}
}
End
{
}
}
Clear-Content -path $files
Import-Module ActiveDirectory
Get-ADComputer -LDAPfilter "(name=LT*)" -SearchBase "OU=S****Y,DC=T***R,DC=com" | Get-InstalledSoftware
(gc inventaireLT.txt) | ? {$_.trim() -ne "" } | set-content inventaireLT.txt
You can export your data to a semicolon separated file by using Export-Csv and specifying the -Delimiter ";"
$MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} | select Name,Version,ComputerName | Export-Csv -Path "C:\folder\file.txt" -Delimiter ";" -NoTypeInformation
If you don't want the header line:
$MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} |
select Name,Version,ComputerName |
ConvertTo-Csv -Delimiter ";" -NoTypeInformation |
Select-Object -Skip 1 |
Set-Content -Path "C:\folder\file.txt"
EDIT:
In your code you would replace:
$MasterKeys = ($MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} | select Name,Version,ComputerName | sort Name| ft -hide )
$MasterKeys >> $files
with
$MasterKeys | Where {$_.Name -ne $Null -AND $_.SystemComponent -ne "1" -AND $_.ParentKeyName -eq $Null} | select Name,Version,ComputerName | ConvertTo-Csv -Delimiter ";" -NoTypeInformation | Select-Object -Skip 1 | Set-Content -Path $files

Powershell Compare text and replace if it does not meet specific criteria

Here is a sample of the csv file I import.
CN,DistinguishedName,extensionattribute7,extensionattribute1
CNPTL73J79ZN1,"CN=CNPTL73J79ZN1,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",tianyang.li,
USPTD079YZLN1,"CN=USPTD079YZLN1,OU=Desktops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",gary.ortiz,
USPTD07WM53M1,"CN=USPTD07WM53M1,OU=Desktops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",allen.watson,
USPTL7CC1P0P1,"CN=USPTL7CC1P0P1,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",u0147066,
USPTL77BTZ4R1,"CN=USPTL77BTZ4R1,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",U0172604,
U0165724-TPL-A,"CN=U0165724-TPL-A,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",U0165724,167
U0130173-TPL-A,"CN=U0130173-TPL-A,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",U0130173,167
U0068498-TPL-A,"CN=U0068498-TPL-A,OU=Laptops,OU=Workstations,OU=MSP01,DC=ten,DC=domain,DC=com",u0068498,167
A couple of things I need to do :
Check if the format of CN starts with UXXXXXXX
If it does not, check extensionattribute7 for proper formatted user id of Uxxxxxxx
If that exists, replace the CN with the name of Uxxxxxxx-TPL-ZZZ. the -TPL-ZZZ will be consistent though out all names.
I am totally confused how to search for the Uxxxxxxx but I need something like this, although I know this is completely incorrect.
Import-Csv c:\Temp\Windows7_Only.csv
if ($_CN -NotMatch'[U][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
{
Replace the name if extensionattribute7 contains a value of U####### and add the suffix of -TPL-ZZZ
}
Here is my script so far:
#Create an LDAP searcher object and pass in the DN of the domain we wish to query
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://DC=ten,DC=domain,DC=com")
#Pass in the ceriteria we are searching for.
$Searcher.Filter = "(&(objectCategory=computer)(objectClass=computer)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(operatingSystem=Windows 7*))"
$Searcher.PageSize = 100000
# Populate General Sheet(1) with information
$results = $Searcher.Findall()
$results | ForEach-Object { $_.GetDirectoryEntry() } |
select #{ n = 'CN'; e = { $_.CN -replace "'", "''" } },
#{ n = 'DistinguishedName'; e = { $_.DistinguishedName -replace "'", "''" } },
#{ n = 'extensionattribute7'; e = { $_.extensionattribute7 -replace "'", "''" } },
#{ n = 'extensionattribute1'; e = { $_.extensionattribute1 -replace "'", "''" } } |
Export-Csv 'C:\temp\Windows7_Only.csv' -NoType -Force
$csv = Import-Csv -Path "c:\Temp\Windows7_Only.csv"
foreach ($row in $csv)
{
if (($row.CN -notmatch '^U\d{7}') -and ($row.DistinguishedName -like "*Laptops*") -and ($row.extensionattribute7 -match '^U\d{7}$'))
{
$row.CN = $row.extensionattribute7 + "-TPL-ZZZ"
}
elseif (($row.CN -notmatch '^U\d{7}') -and ($row.DistinguishedName -like "*Desktops*") -and ($row.extensionattribute7 -match '^U\d{7}$'))
{
$row.CN = $row.extensionattribute7 + "-TPD-ZZZ"
}
$csv | export-csv c:\fixed.csv -Force
}
Good start, though let me say that if you have access to the Active Directory snap-in you should totally use that rather than creating LDAP searchers and what not.
Now, about your comparison... As Matt said your Match should be against $.CN. What that means is $, which represents the current record as it loops through records, and the .CN portion indicates that it should look at the CN property of the record.
Then you can use -Match and (again) like Matt said (he's new here but proving to be knowledgeable), that can be shortened to "U\d{8}".
Now, you actually want to find those that aren't like U\d{8}, so let's precede that with a ! which is an alias for -Not. Then let's check and see if ExtendedAttribute7 is the right thing. So then this looks like:
!$_.CN -like "U\d{8}" -and $_.ExtendedAttribute7 -match "U\d{8}"
Excellent! We have our filter for the rows that need updating. That is pretty much what Alexander did. As for me, I'd go more (using your script as a base):
#Create an LDAP searcher object and pass in the DN of the domain we wish to query
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://DC=ten,DC=domain,DC=com")
#Pass in the ceriteria we are searching for.
#In this case we're looking for users with a particular SAM name.
$Searcher.Filter = "(&(objectCategory=computer)(objectClass=computer)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(operatingSystem=Windows 7*))"
$Searcher.PageSize = 100000
# Populate General Sheet(1) with information
$results = $Searcher.Findall()
$Computers = #()
ForEach($Item in $results){
$Comp = $Item.GetDirectoryEntry()
If($Comp.distinguishedName -like "*desktops*"){$Suffix = "TPD-ZZZ"}else{$Suffix = "TPL-ZZZ"}
$CN = If(!$Comp.CN -match "U\d{8}" -and $Comp.extensionattribute7 -match "U\d{8}"){$Comp.extensionattribute7+$Suffix}else{$Comp.CN}
$Computers += [PSCustomObject][Ordered]#{
'CN' = $CN -replace "'", "''"
'DistinguishedName' = $Comp.DistinguishedName[0] -replace "'", "''"
'extensionattribute7' = $Comp.extensionattribute7[0] -replace "'", "''"
'extensionattribute1' = $Comp.extensionattribute1[0] -replace "'", "''"
}
}
$Computers | Export-Csv 'C:\temp\Windows7_Only.csv' -NoType -Force
$Computers
Assuming that I understand your requirements correctly:
$csv = Import-Csv -Path "c:\Temp\Windows7_Only.csv"
foreach ($row in $csv) {
if ($row.DistinguishedName -like "*Desktops*") {
$suffix = "-TPD-ZZZ"
}
elseif ($row.DistinguishedName -like "*Laptops*") {
$suffix = "-TPL-ZZZ"
}
if ( ($row.CN -notmatch '^U\d{7}') `
-and ($row.extensionattribute7 -match '^U\d{7}$') ) {
$row.CN = $row.extensionattribute7 + $suffix
}
}
$csv | export-csv c:\fixed.csv -Force -NoTypeInformation