I have a script that reports NTDS service status from entire forest there are few 2003 servers which I want exclude below is the script.
$getForest = [system.directoryservices.activedirectory.Forest]::GetCurrentForest()
$getForest.domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}
I was trying something like
$getForest = [system.directoryservices.activedirectory.Forest]::GetCurrentForest()
$getForest.domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name} | where-object {$_.name -notlike "server2003.domain.local"}
No luck
Your second ForEach-Object isn't needed, so I've consolidated it into the first.
For this kind of thing I would recommend creating an array of names you want excluded, which I called $exclude.
Then I'm using the -notcontains operator to check the name against the list from within Where-Object.
$exclude = #(
'server2003.domain.local'
'other2003.domain.local'
)
$getForest = [system.directoryservices.activedirectory.Forest]::GetCurrentForest()
$getForest.domains |
ForEach-Object {$_.DomainControllers.Name} |
Where-Object {$exclude -notcontains $_.name}
I got it working
$exclude = #(
'dc2.local'
'dc3.local'
'dc4.local'
'dc5.local'
)
(Get-ADForest).Domains | %{ Get-ADDomainController -Filter * -Server $_ } | Where-Object {$exclude -notcontains $_.hostname} | select Hostname
Related
I'm writing a script to delete Windows user profiles older than 90 days.
When running the following command
Get-ciminstance -Class win32_userprofile | where-object {$_.LastuseTime -gt (get-date).AddDays(90)
The "LastUseTime" for my workstations are all resetting to the every time the machine was rebooted, which are automatically rebooted every 2 weeks. So in return I have all profiles returned when running that cmdlet.
My attempt at resolving this is going into the C:\users\ directory and identifying the user folders that were last modified over 90 days ago with the following script and assigning the values to a variable. Users have IDs of 6 digits (ex. 123456, 111222.e, 021561). We want to avoid deleting profiles that have letters in the names (ex. c:\users\markdavis c:\users\administrator)
$profiles = Get-childitem -Path C:\Users\* -Directory | where-object {$_.LastWriteTime -lt (get-date).AddDays(-90)} | Where-Object {$_.Name -match "\d\d\d\d\d\d"} | Select-Object -Property FullName
checking the variable will return
PS C:\WINDOWS\system32> $profiles
FullName
--------
C:\Users\123456
C:\Users\111222.e
C:\Users\021561
Now here is where I am having trouble completing the script as the following cmdlet is failing to pull up the correctly filtered user profiles before I use Remove-CIMInstance to delete them, I tried many different ways to try to make it work, and now questioning if it is even possible to pass the variable to the following script. Appreciate the help!
$profiles = Get-childitem -Path C:\Users\* -Directory | where-object {$_.LastWriteTime -lt (get-date).AddDays(-90)} | Where-Object {$_.Name -match "\d\d\d\d\d\d"} | Select-Object -Property FullName
forEach($profile in $profiles){
Get-ciminstance -Class win32_userprofile | Where-object {$_.LocalPath -match "$profile"} | Remove-CimInstance
}
I've also tried passing forcing into an array - but was also unsuccessful.
$profiles = #(Get-childitem -Path C:\Users\* -Directory | where-object {$_.LastWriteTime -lt (get-date).AddDays(-90)} | Where-Object {$_.Name -match "\d\d\d\d\d\d"} | Select-Object -Property FullName)
Try (getting the FullName properties as array):
$profiles = (Get-ChildItem -Path C:\Users\* -Directory | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-90)} | Where-Object {$_.Name -match "\d\d\d\d\d\d"}).FullName
forEach($profile in $profiles){
Get-CimInstance -class win32_userprofile | Where-Object {$_.LocalPath -match "$profile"} | Remove-CimInstance
}
Or (using the FullName property of each object we got using Where-Object):
$profiles = Get-ChildItem -Path C:\Users\* -Directory | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-90)} | Where-Object {$_.Name -match "\d\d\d\d\d\d"}
forEach($profile in $profiles){
Get-ciminstance -Class win32_userprofile | Where-object {$_.LocalPath -match $profile.FullName} | Remove-CimInstance
}
I have a collection of type Microsoft.Win32.RegistryKey Example:
$arr = Get-ChildItem HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
The 3rd element contains the property I am interested in. I access it using:
$arr[3] | Get-ItemProperty | Where-Object {$_.DisplayName -like "MyProgram*"}
This works fine. Now I am trying to loop over the collection (index number is not known):
$arr | ForEach-Object { Get-ItemProperty $_ | Where-Object {$_.DisplayNAme -like "MyProgram*"}
Returns the error: "Cannot find path because it does not exist".
How can I display the same output as $arr[3] | ... using a loop?
What am I doing wrong?
Did you try to search for it?
Get-ItemProperty -Path REGISTRY::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object {$_.Displayname -like 'MyProgram*'}
I have a script that filters my logs, but the problem is that when I would like to delete everything else but certain files I get errors of Unrecognized escape sequence. I've been trying to split the values but it seems that nothing works. I also tried -exclude before, but didn't get it to work. It's supposed to remove all the other files but $result and $clr.
$files = #()
[xml]$photonconfig = Get-Content C:\Users\Administrator\Desktop\PhotonServer.config
$photonconfig.SelectNodes("Configuration/*") | Select-Object -Expand Name | % {
$_.Replace("xxx","")
} | ForEach {
$files+= Get-ChildItem C:\Users\Administrator\Desktop\log\log/*$_*.log |
sort -Property LastWriteTime -Descending |
Select-Object -First 3
}
$result = $files | Sort-Object LastAccessTime -Descending |
Select-Object -First 3
$clr = "PhotonCLR.log"
$all = Get-ChildItem C:\Users\Administrator\Desktop\log\log/* |
Where-Object { $_.Name -notmatch $result } |
Remove-Item
The second operand of the -match and -notmatch operators is a regular expression, not an array of file names. Use the -contains operator instead:
... | Where-Object { $result -notcontains $_.Name } | ...
On PowerShell v3 and newer you can also use the -notin operator, which feels a little more "natural" to most people:
... | Where-Object { $_.Name -notin $result } | ...
Note that for this to work you also need to expand the Name property when building $result:
$result = $files | Sort-Object LastAccessTime -Descending |
Select-Object -First 3 -Expand Name
I have to query my Outlook Add-ins and check if two specific ones are installed.
This is what I have:
$searchScopes = "HKCU:\SOFTWARE\Microsoft\Office\Outlook\Addins","HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\Addins"
$searchScopes | % {Get-ChildItem -Path $_ | % {Get-ItemProperty -Path $_.PSPath} | Select-Object #{n="Name";e={Split-Path $_.PSPath -leaf}},FriendlyName,Description} | Sort-Object -Unique -Property name
This shows me all installed Add-ins. Now I dont know how to filter the result to get a true or false.
Like the following
If List contains 'addin1' then 'addin1' installed = true
Do you have a list of addins to check if they are installed? What do you want to do once you have found that something is installed or not?
You could make use of the -in operator, which checks a value against a list and is true if the value is in the list. All this code does is print to host; the logic in the loop will need to be changed to match your requirements.
$searchScopes = "HKCU:\SOFTWARE\Microsoft\Office\Outlook\Addins","HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\Addins"
$names = $searchScopes | % {Get-ChildItem -Path $_ | % {Get-ItemProperty -Path $_.PSPath} | Select-Object #{n="Name";e={Split-Path $_.PSPath -leaf}},FriendlyName,Description} | Sort-Object -Unique -Property name
if("addin1" -in $names){
Write-Host "addin1 is installed."
}
Using your code, add the second line into a variable
$searchScopes = "HKCU:\SOFTWARE\Microsoft\Office\Outlook\Addins","HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\Addins"
$Results = $searchScopes | % {Get-ChildItem -Path $_ | % {Get-ItemProperty -Path $_.PSPath} | Select-Object #{n="Name";e={Split-Path $_.PSPath -leaf}},FriendlyName,Description} | Sort-Object -Unique -Property name
then query the results:
$Results.Name -contains 'TeamViewerMeetingAddIn.AddIn'
or
$Results.FriendlyName -match 'Google Apps'
To filter:
$Results | ? {$_.Name -contains 'TeamViewerMeetingAddIn.AddIn'}
I'm trying to make the following PowerShell script more generic. I want to pass in an array of excludes rather than a fixed list. I can't figure out how to do this except my partial solution below:
ORIGINAL
This gets all the files in a path except a list of wildcard files or folders:
Get-ChildItem -Path "$sitePath" -Recurse | `
where {!$_.PSIsContainer } | `
Select -ExpandProperty FullName | `
Where {$_ -notlike "$sitePath\Custom\*"} | `
Where {$_ -notlike "$sitePath\Download\*"} | `
Where {$_ -notlike "$sitePath\Temp\*"} | `
Where {$_ -notlike "$sitePath\Portal\*"} | `
Where {$_ -notlike "$sitePath\web.config*"} | `
SELECT $_
PARTIAL SOLUTION
This is the best I've come up with. It allows me to create an array of wildcards called $excludeList, but is limited and is slightly slower:
$excludeList = #("$sitePath\Custom\*",
"$sitePath\Download\*",
"$sitePath\Portal\*",
"$sitePath\web.config*")
Get-ChildItem -Path "$sitePath" -Recurse | `
where {!$_.PSIsContainer } | `
Select -ExpandProperty FullName | `
Where {$_ -notlike $excludeList[0]} | `
Where {$_ -notlike $excludeList[1]} | `
Where {$_ -notlike $excludeList[2]} | `
Where {$_ -notlike $excludeList[3]} | `
Where {$_ -notlike $excludeList[4]} | `
Where {$_ -notlike $excludeList[5]} | `
Where {$_ -notlike $excludeList[6]} | `
Where {$_ -notlike $excludeList[7]} | `
Where {$_ -notlike $excludeList[8]} | `
Where {$_ -notlike $excludeList[9]} | `
Where {$_ -notlike $excludeList[10]} | `
SELECT $_
Is there a better way to pass an array in to the where clause? All the solutions I've found only allow non-wildcard matches.
Hope someone can help!
One approach would be to iterate over the items in the exclude list, and only include a path if it does not match any of the exclusions:
$excludeList = #("$sitePath\Custom\*",
"$sitePath\Download\*",
"$sitePath\Portal\*",
"$sitePath\web.config*")
Get-ChildItem -Path "$sitePath" -Recurse |
where { !$_.PSIsContainer } |
select -ExpandProperty FullName |
where { $path = $_; -not #($excludeList | ? { $path -like $_ }) }
If all of your excluded items follow the same pattern, you can also simplify the exclude list by moving the common pattern to the like call:
$excludeList = #('Custom','Download','Portal','web.config')
Get-ChildItem -Path "$sitePath" -Recurse |
where { !$_.PSIsContainer } |
select -ExpandProperty FullName |
where { $path = $_; -not #($excludeList | ? { $path -like "$sitePath\$_*" }) }
If you're willing to go with a regex instead, you can simplify this a lot:
$excludeList = [regex]::Escape("$sitePath\Custom\"),
[regex]::Escape("$sitePath\Download\"),
[regex]::Escape("$sitePath\Temp\") -join "|"
Get-ChildItem $sitePath -Recurse | `
where {!$_.PSIsContainer } | `
Select -ExpandProperty FullName | `
Where {$_ -notmatch $excludeList}
Not sure why you have the trailing Select $_, it is unnecessary AFAICT.
You should try -contains and -notcontains operators if you are trying to compare against an array.
$array = "name1","name2","name3"
#This will return false
$array -contains "name"
#this will return true
$array -notcontains "name"