i need some help in order to complete the script, i have already script which deleting specific profiles on the remote server, but i want o add time frame. Example: if the profile was not used for more than 120 days delete it.
Function Get-OldProfiles {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)] [string]$computerName
)
PROCESS {
foreach ($computer in $computerName) {
Write-host -ForegroundColor Yellow "Housekeeping on $computer"
Write-host -ForegroundColor Yellow "Mapping drive \\$computer\c$"
$drive = New-PSDrive -Name $computer.replace(".","-") -PSProvider FileSystem -Root \\$computer\C$
Write-host -ForegroundColor Yellow "Checking windows version"
#Cheking windows version
$version = (Get-WmiObject -ComputerName $computer -Class Win32_OperatingSystem).version
Write-host -ForegroundColor Yellow "Windows version $version"
#Profile Deleting area.
if ($version -ge 6) {
Write-host -ForegroundColor Yellow "Getting profiles from WMI"
$profiles = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like 'C:\\Users\\%'" | Where-object localpath -Match 'B.{5}R$'| Select-Object {$_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-2)}
if ($profiles -ne $null) {
$profiles | foreach {
Write-host -ForegroundColor Red ("Deleting profile: " + $_.LocalPath)
#$_.Delete()
}
}
}
}
}
}
I've tried this:
$profiles= Get-WmiObject -ComputerName $computer -class Win32_UserProfile -filter "Special = False -and LocalPath Like 'C:\\Users\\%'" | Where-object localpath -Match 'B.{5}R$' | Where {$_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-120)}
But it returns an error
Get-WmiObject : Invalid query "select * from Win32_UserProfile where Special = False -and LocalPath Like 'C:\\Users\\%'"
At line:22 char:24 + $profiles= Get-WmiObject -ComputerName $computer -class Win32_UserPr ...
You can't use -and in a WQL-filter, it's just AND. Try:
$profiles = Get-WmiObject -ComputerName $computer -Class Win32_UserProfile -filter "Special = False AND LocalPath Like 'C:\\Users\\%'" |
Where-Object { ($_.localpath -Match 'B.{5}R$') -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-120)) }
Related
I'm using this Powershell script to retrieve info of remote servers from a central server.
In this case, there are about 150 servers on Active Directory:
$Servers = Get-ADComputer -Filter 'Name -like "...*"' | Select-Object -ExpandProperty Name
foreach ($computer in $Servers)
{
try
{
$ping = Test-Connection -ComputerName $computer -count 1 -ErrorAction Stop
$IP = ($ping.IPV4Address).IPAddressToString
$hardware = Get-CimInstance -Class Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
$totalMemory = (Get-CimInstance Win32_PhysicalMemory -ComputerName $computer | Measure-Object -Property capacity -Sum).sum /1gb
$os = Get-CimInstance -Class Win32_OperatingSystem -ComputerName $computer
$cpu = Get-CimInstance -Class Win32_processor -ComputerName $computer | Group-Object -Property Name |
Select-Object -Property Name,
#{Name = 'TotalSockets'; Expression = {$_.Count}},
#{Name = 'TotalCores'; Expression = {($_.Group | Measure-Object -Property NumberOfCores -Sum).Sum}},
#{Name = 'TotalLogicalProcessors'; Expression = {($_.Group | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum}}
#$disks = Get-WmiObject Win32_Volume -ComputerName $computer -Filter "DriveType='3'" | Sort-Object Name
# create new custom object to keep adding store information to it
$Result = New-Object -TypeName PSCustomObject -Property #{
ComputerName = $computer.ToUpper()
IPAddress = $IP
Manufacturer = $hardware.Manufacturer
Model = $hardware.Model
ADDescription = (Get-ADComputer -Identity $computer -Properties Description).Description -join ';'
ProductName = $os.Caption
OSVersion = $os.version
BuildNumber = $os.BuildNumber
OSArchitecture = $os.OSArchitecture
Domain = $hardware.Domain
'RAM (GB)' = $totalMemory
CPU = $cpu.Name
CPUTotalSockets = $cpu.TotalSockets
CPUTotalCores = $cpu.TotalCores
CPUTotalLogicalProcessors = $cpu.TotalLogicalProcessors
CPUVirtualizationFirmwareEnabled = (Get-CimInstance -Class Win32_processor -ComputerName $computer).VirtualizationFirmwareEnabled -join ','
}
# Column ordering, re-order if you like
<#$colOrder = 'ComputerName', 'IPAddress', 'Manufacturer', 'Model', 'ADDescription',
'ProductName', 'OSVersion', 'BuildNumber', 'OSArchitecture',
'Domain', 'RAM (GB)', 'CPU', 'CPUTotalSockets', 'CPUTotalCores',
'CPUTotalLogicalProcessors', 'CPUVirtualizationFirmwareEnabled'#>
# Return all your results
#$Result | Select-Object -Property $colOrder
$Result | Select-Object "ComputerName", "IPAddress", "Manufacturer", "Model", "ADDescription", "ProductName", "OSVersion", "BuildNumber",
"OSArchitecture", "RAM (GB)", "CPU", "CPUTotalSockets", "CPUTotalCores", "CPUTotalLogicalProcessors", "CPUVirtualizationFirmwareEnabled", "Domain" |
Export-Csv -Path "C:\SQL\Get-Inventory.csv" -Delimiter '|' -Append -NoTypeInformation
#$disks | Format-Table DriveLetter, Label, #{Name='Size(GB)'; Expression={[decimal]('{0:N0}' -f($_.Capacity/1gb))}}, #{Name='FreeSpace(GB)'; Expression={[decimal]('{0:N0}' -f($_.FreeSpace/1gb))}}
}
catch
{ Write-Output "--- $computer ---" $Error[0] `n | Add-Content -Path C:\SQL\UnreachableServers.txt }
}
The Powershell's process uses an average of 50/75 Mb of RAM. It's possible to reduce the RAM usage?
I accept any kind of advice given my little experience on Powershell :)
Thanks in advance.
Alessandro
I am trying to find a service, stop it and then disable it remotely using Powershell. It can find and stop but cannot disable. For disabling, I have to run the Set-Service command separately. Can it be done in one line?
The following code-snippet will stop the Print Spooler service, but will not disable it:
$ip = "10.10.10.10"
$svc_name = "Spooler"
get-service -ComputerName $ip | Where-Object {$_.Name -eq $svc_name} | Stop-Service | Set-Service -StartupType Disabled
The following code-snippet will stop and disable the Print Spooler service:
$ip = "10.10.10.10"
$svc_name = "Spooler"
get-service -ComputerName $ip | Where-Object {$_.Name -eq $svc_name} | Stop-Service
Set-Service $svc_name -StartupType Disabled
Powershell version is 5.1.14393.2969.
Edit:
The following line will also find and disable. So, it looks like I can give two instructions with pipeline.
get-service -ComputerName $ip | Where-Object {$_.Name -eq $svc_name} | Set-Service -StartupType Disabled
You need to use Set-Service to set the startup type, as outlined in your question:
Set-Service -StartupType Disabled $svc_name
If you want to do it in "one line", you can use the -PassThru argument on Stop-Service to return the service object which can then be sent down the pipeline (you also don't need a Where-Object clause, Get-Service can filter on service name as well):
Get-Service -ComputerName $ip $svc_name | Stop-Service -PassThru | Set-Service -StartupType Disabled
You had this close in your original question, but it didn't work because you didn't use the-PassThru parameter on Stop-Service. As a note, many cmdlets that don't return an object by default do include a -PassThru parameter to return an object that can further processed if necessary, this isn't limited to Stop-Service by any means.
Bender's answer works in PowerShell 5.1, but the -ComputerName parameter was removed from the Get-Service cmdlet in PowerShell 6+. If you're trying to do this in pwsh.exe (i.e. PowerShell 6+), you can use code like the following:
[string[]] $servers = #('server1', 'server2, 'server3')
[scriptblock] $disableServiceScriptBlock = {
[string] $serviceName = 'SERVICE NAME TO DISABLE GOES HERE'
Stop-Service -Name $serviceName
Set-Service -Name $serviceName -StartupType Disabled
}
Invoke-Command -ComputerName $servers -ScriptBlock $disableServiceScriptBlock
Here's a longer code snippet with better error reporting so you know what server an error occurred on:
[string[]] $servers = #('server1', 'server2, 'server3')
[scriptblock] $disableServiceScriptBlock = {
[string] $serviceName = 'SERVICE NAME TO DISABLE GOES HERE'
Stop-Service -Name $serviceName -ErrorVariable stopError -ErrorAction SilentlyContinue
Set-Service -Name $serviceName -StartupType Disabled -ErrorVariable disableError -ErrorAction SilentlyContinue
# If an error occurred, report which server it occurred on with the error message.
[string] $computerName = $Env:ComputerName
if ($stopError)
{
Write-Error "$computerName : Stop Error: $stopError"
}
if ($disableError)
{
Write-Error "$computerName : Disable Error: $disableError"
}
}
Invoke-Command -ComputerName $servers -ScriptBlock $disableServiceScriptBlock
***Stopping both Windows Firewall and Windows Defender Firewall***
$date = get-date -uformat "%m%d%y-%H"
$day = Get-Date -Format yyyyMMdd
$dayold = Get-Date -Format "%M%d%y"
$today = (Get-Date -Format yyyyMMdd)+"-"+(get-date -uformat %H)
$ErrorActionPreference = "SilentlyContinue"
$ServerList = (Get-adcomputer -SearchBase "OU=site,OU=servers,DC=subdomain,DC=domain,DC=root" -filter {name -like "*cont*ext*"} -SearchScope Subtree -Properties Name) |select name
$ServerList=$ServerList.name
(Test-Connection -ComputerName $env:LOGONSERVER.Remove(0,2) -Count 1 -quiet)|Out-Null
foreach ($server in $ServerList){
if(Test-Connection -ComputerName $server -Count 1 -quiet){
$result = (get-service -ComputerName $server -name MpsSvc |select *)
if($result.Status -eq "Running")
{
get-service -ComputerName $server -name MpsSvc |stop-service -Force
get-service -ComputerName $server -name MpsSvc |set-service -ComputerName $server -StartupType Disabled
}
elseif($result.StartType -ne "Disabled"){
set-service -ComputerName $server -name MpsSvc -StartupType "Disabled"
}
$result = (get-service -ComputerName $server -name MpsSvc |select *)
$server+": "+"The "+$result.DisplayName+" is "+$result.Status+" and "+$result.StartType
}
}
Im trying extract a report from AD of a list of devices that have BitLocker enabled.
We have a Win 2008 r2 Domain Controller and most of our devices are Win 10 with a few Win 8.1 in the mix.
I'm no expert in power shell but have used it in the past on an amateur level. I found the following command online and tried it but when viewing the .CSV all fields are populated except for the "BitlockerPasswordSet" field.
Does anyone have any ideas on how to fix this or better yet a solution they have used that works?
Thanks in advance!
Param (
[string]$SearchBase = "OU=Office-UK,DC=MyDomainName,DC=local"
)
Try { Import-Module ActiveDirectory -ErrorAction Stop }
Catch { Write-Warning "Unable to load Active Directory module because $($Error[0])"; Exit }
Write-Verbose "Getting Workstations..." -Verbose
$Computers = Get-ADComputer -Filter * -SearchBase $SearchBase -Properties LastLogonDate
$Count = 1
$Results = ForEach ($Computer in $Computers)
{
Write-Progress -Id 0 -Activity "Searching Computers for BitLocker" -Status "$Count of $($Computers.Count)" -PercentComplete (($Count / $Computers.Count) * 100)
New-Object PSObject -Property #{
ComputerName = $Computer.Name
LastLogonDate = $Computer.LastLogonDate
BitLockerPasswordSet = Get-ADObject -Filter "objectClass -eq 'msFVE-RecoveryInformation'" -SearchBase $Computer.distinguishedName -Properties msFVE-RecoveryPassword,whenCreated | Sort whenCreated -Descending | Select -First 1 | Select -ExpandProperty whenCreated
}
$Count ++
}
Write-Progress -Id 0 -Activity " " -Status " " -Completed
$ReportPath = "C:\temp\BitLockerComputerReport.csv"
Write-Verbose "Building the report..." -Verbose
$Results | Select ComputerName,LastLogonDate,BitLockerPasswordSet | Sort ComputerName | Export-Csv $ReportPath -NoTypeInformation
Write-Verbose "Report saved at: $ReportPath" -Verbose
I'm trying to set the properties of a local account on a bunch of servers to "password never expires". This is the best I could figure out. I keep getting:
Get-WmiObject : Invalid parameter
At C:\Users\xxxxxx\AppData\Local\Temp\4f06fa1c-61da-4c65-ac0b-a4167d83d51c.ps1:4 char:14
+ Get-WmiObject <<<< -class Win32_UserAccount -Filter "name = 'localaccount'" - ComputerName $server | Set-WmiInstance -Argument #{PasswordExpires = 0}
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
--------- Here's what I am trying ------------
$servers = Get-Item c:\list.txt
foreach ($server in $servers)
{
Get-WmiObject -class Win32_UserAccount -Filter "name = 'localaccount'" -ComputerName $server | Set-WmiInstance -Argument #{PasswordExpires = 0}
}
Thank you!
Your mistake is in this line:
$servers = Get-Item c:\list.txt
The Get-Item cmdlet returns a FileInfo object, not the content of the file. For reading the content into a variable you need the Get-Content cmdlet.
This should work:
Get-Content 'c:\list.txt' | % {
gwmi Win32_UserAccount -Computer $_ -Filter "name='localaccount'" |
Set-WmiInstance -Argument #{PasswordExpires = $false}
}
You could also do the property change like this (source):
Get-Content 'c:\list.txt' | % {
$account = gwmi Win32_UserAccount -Computer $_ -Filter "name='localaccount'"
$account.PasswordExpires = $false
$account.Put()
}
I wrote a script to copy files to the "All Users" desktop or "Public Desktop"
However we have a mixed environment. Some people are using Windows XP and other people are using Windows 7.
$SOURCE = "I:\Path\To\Folder\*"
$DESTINATION7 = "c$\Users\Public\Desktop"
$DESTINATIONXP = "c$\Documents and Settings\All Users\Desktop"
$computerlist = Get-Content I:\Path\To\File\computer-list.csv
$results = #()
$filenotthere = #()
$filesremoved = #()
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
Write-Host "\\$computer\$DESTINATION\"
Copy-Item $SOURCE "\\$computer\$DESTINATION\" -Recurse -force
} else {
$details = #{
Date = get-date
ComputerName = $Computer
Destination = $Destination
}
$results += New-Object PSObject -Property $details
$results | export-csv -Path I:\Path\To\logs\offline.txt -NoTypeInformation -Append
}
}
DESTINATION is empty. Expanding on Keith's suggestion:
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
$OS = Get-WmiObject -Computer $computer -Class Win32_OperatingSystem
if($OS.caption -like '*Windows 7*'){
$DESTINATION = $DESTINATION7
}
if($OS.caption -like '*Windows XP*'){
$DESTINATION = $DESTINATIONXP
}
}
}
This could avoid the error you're getting also. empty $DESTINATION.
In your foreach loop through $computerlist you can grab the OS Caption for each computer by using WMI:
$OS = Get-WmiObject -Computer $computer -Class Win32_OperatingSystem
Ant then check the $OS
if($OS.caption -like '*Windows 7*'){
#Code here for Windows 7
}
#....
I had a slightly different goal...But thanks for the basics.
del C:\scripts\OS.csv
$computerlist = Get-Content c:\scripts\computerlist.csv
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
Get-WMIObject Win32_OperatingSystem -ComputerName $computer |
select-object CSName, Caption, CSDVersion, OSType, LastBootUpTime, ProductType| export-csv -Path C:\Scripts\OS.csv -NoTypeInformation -Append
}
}