I want to get the Display Name, Name, Start Mode, Start Name, and State of all Automatic services that are in a Stopped state on a Windows server. Normally, I would just do
get-wmiobject -class win32_service | ? {$_.StartMode -eq "Auto" -and $_.State -eq "Stopped"} | select DisplayName, Name, StartMode, StartName, State
However, the cmdlet above does not distinguish between a state of "Automatic" and "Automatic Delayed Start". The cmdlet I have below will not report any services that have a state of auto delayed start, but I don't know how to get it to also display the other properties I need.
(Get-WmiObject -Class Win32_Service -Filter "state = 'stopped' and startmode = 'auto'" | Select-Object -ExpandProperty name) | Where-Object {(Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Services | Where-Object {$_.property -contains "DelayedAutoStart"} | Select-Object -ExpandProperty PSChildName) -notcontains $_} | Select-Object #{l='Service Name';e={$_}}
How can I modify the above cmdlet so that it will also display the other properties I want?
EDIT:
I know the method below will work, but its inefficient and non-powershell-like.
$auto_services = #((get-wmiobject -class win32_service -filter "state='stopped' and startmode='auto'" | select-object -expandproperty name) | ? {(get-childitem HKLM:\SYSTEM\CurrentControlSet\Services | ? {$_.property -contains "DelayedAutoStart"} | Select-Object -ExpandProperty PSChildName) -notcontains $_})
foreach ($service in $auto_services) { Get-WMIobject -class win32_service | ? {$_.Name -eq $service} | Select DisplayName, name, startmode, startname, state}
EDIT 2:
What would be even better is if you could list all services and the desired properties and somehow make it so that the "Automatic Delayed Start" services actually show "Auto Delayed Start" as the StartMode instead of showing just "Auto".
Using PowerShell 4.0 (with -PipelineVariable) you can do the following :
get-wmiobject -class win32_service -PipelineVariable s | ? {$_.StartMode -eq "Auto" -and $_.State -eq "Stopped"}| where {(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\services\$($_.name)" -Name 'DelayedAutoStart' -ErrorAction "silentlycontinue").DelayedAutoStart -eq 1} | % {select -InputObject $s -Property DisplayName, Name, StartMode, StartName, State}
Using previous versions you should assign the service object to a var during the pipeline.
get-wmiobject -class win32_service | % {$s=$_;$s} | ? {$_.StartMode -eq "Auto" -and $_.State -eq "Stopped"}| where {(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\services\$($_.name)" -Name 'DelayedAutoStart' -ErrorAction "silentlycontinue").DelayedAutoStart -eq 1} | % {select -InputObject $s -Property DisplayName, Name, StartMode, StartName, State}
Edited
Here is a version for PowerShell 2.0 of all stopped services that are in "Automatic" startmode and not not "Automatic Delayed Start" :
get-wmiobject -class win32_service | % {$s=$_;$s} | ? {$_.StartMode -eq "Auto" -and $_.State -eq "Stopped"}| % {$d = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\services\$($_.name)" -Name 'DelayedAutoStart' -ErrorAction "silentlycontinue").DelayedAutoStart;$_ } | where {$d -ne '1'} |% {select -InputObject $s -Property #{name="DelayedAutoStart";expression={$d}},DisplayName, Name, StartMode, StartName, State}
Related
This is probably a version issue, but I simply need to get the server name into the Format-Table PowerShell command.
$compArray = Get-Content C:\Users\Me\Documents\ServerList_All.txt
$Proc = foreach ($strComputer in $compArray) {
Get-WMIObject Win32_Service | Where-Object {
$_.Name -like 'SQL*' -or
$_.Name -like 'MSSQL*' -or
$_.Name -like 'OLAP*' -or
$_.Name -like 'MSDTS*' -or
$_.Name -like 'MSOLAP*' -or
$_.Name -like 'ReportServer*'
} | Sort-Object -Property Name | Format-Table $strComputer, Name, State
}
$Proc | Out-File C:\Users\ME\Documents\ServerStatus_All.txt
This works in PS v2:
| Sort-Object -Property Name | Format-Table Name, State
This does not, but does work in PS v3:
| Sort-Object -Property Name | Format-Table $strComputer, Name, State
Error:
Format-Table : Cannot convert System.Management.Automation.PSObject to one of the following types {System.String, System.Management.Automation.ScriptBlock}.
The only difference is the $strComputer variable. I am reading from a text file, and everything is beautiful in v3+.
No, I cannot upgrade to a newer PS version on the server I am running this from, sadly.
This should work for you in both...
$compArray = (Get-ADComputer -Filter *).Name
$Proc = foreach ($strComputer in $compArray) {
Get-WMIObject -Class Win32_Service -ComputerName $strComputer |
Where-Object {
$_.Name -like 'SQL*' -or
$_.Name -like 'MSSQL*' -or
$_.Name -like 'OLAP*' -or
$_.Name -like 'MSDTS*' -or
$_.Name -like 'MSOLAP*' -or
$_.Name -like 'ReportServer*'
} |
Select-Object -Property #{Name = 'Computer';Expression={$strComputer}}, Name, State |
Sort-Object -Property Name |
Format-Table -AutoSize
}
$Proc
# Results
Computer Name State
-------- ---- -----
LABSQL01 MSSQLFDLauncher Running
LABSQL01 MSSQLSERVER Running
LABSQL01 SQLBrowser Stopped
LABSQL01 SQLSERVERAGENT Running
LABSQL01 SQLTELEMETRY Running
LABSQL01 SQLWriter Running
Computer Name State
-------- ---- -----
LABWSM01 MSSQL$MICROSOFT##WID Stopped
Get-WmiObject -Class Win32_Printer | where{$_.Network -eq ‘true‘}| foreach{$_.delete()}
I know this script will delete all network printers, but I need to delete only certain network printers…like CLEPRINT15-2 and CLEPRINT 15-4, but not 15-3. How would I do this?
You already have a where filter on the Network property just more conditionals on the Name property.
Get-WmiObject -Class Win32_Printer |
Where-Object {$_.Network -eq $true -and ($_.Name -eq 'CLEPRINT15-2' -or $_.Name -eq 'CLEPRINT15-4')} |
ForEach-Object {$_.Delete()}
Note: Also be careful with smart quotes. ‘ is different than '
Try this additional where condition with a RegEx class [24]:
Get-WmiObject -Class Win32_Printer |
where{$_.Network -eq $true -and $_.Name -match '^CLEPRINT-?15-[24]$'} |
foreach{$_.delete()}
I have some requirement where I have to find out the current version and update details of an installed application (highlighted):
And I have this PowerShell snippet for modification:
$server="XXXXXXXXXX"
$ServiceInfo = Get-WmiObject win32_service -ComputerName $server -ExpandProperty Version | Where-Object {$_.Name -eq "VSTTAgent"}
if($ServiceInfo.State -eq "Running")
{
$userAccount = $ServiceInfo.DisplayName.ToString()
Write-Host ("VSTTAgent service is Running on $server and $userAccount ")
}
To get the product version, you can use the Get-Item cmdlet using the PathName property of your $ServiceInfo object:
$ServiceInfo.PathName.Trim('"') | Get-Item | select -expand VersionInfo | select ProductVersion
Essentially the same as #MartinBrandl, but the WMI-only version.
Get-WmiObject win32_service -Filter 'Name="VSTTAgent"' -ComputerName $server | ForEach-Object {
$filter = 'Name="{0}"' -f $_.PathName -replace '\\', '\\'
$version = (Get-WmiObject CIM_DataFile -Filter $filter -ComputerName $server).Version
if ($_.State -eq 'Running') {
$userAccount = $ServiceInfo.DisplayName.ToString()
Write-Host ("VSTTAgent ($version) service is Running on $server and $userAccount")
}
}
I've got a script which goes out to computer names from a text file and then polls the services on those machines and writes the results back to a text file.
Here's what I currently have set up:
$Computers = Get-Content computername.txt
$Output = Foreach ($Computer in $Computers) {
Write-Output "`n" "Status of $Computer".ToUpper()
Get-WMIobject -Computername $Computer win32_service | Where-Object {$_.startname -ne "LocalSystem" -and $_.startname -ne "localservice" -and $_.startname -notlike "*AUTHORITY*"} | ft name, startname, startmode, state
}
$Output | Out-File ServiceReport.txt
Is there a way to run multiple sessions at once instead of processing this incrementally? IE - send the command to all the systems at once and then receive the response and record appropriately? I've looked in to Invoke-Command and a few other things but have yet to improve time, get results to write back to the file, or get those options working generally.
Get-WMIObject will multi-thread. You just need to give it more than one computer at a time to work with:
$Computers = Get-Content computername.txt
Get-WMIobject -Computername $Computers win32_service |
Where-Object {$_.startname -ne "LocalSystem" -and $_.startname -ne "localservice" -and $_.startname -notlike "*AUTHORITY*"} |
ft PSComputerName, name, startname, startmode, state |
Out-string |
Out-File ServiceReport.txt
You'll lost the ability to have that "Status of $Computer" line before each one but you can make up for it by including the computer name in the selected objects.
How can I get the InstallDate from Win32Reg_AddRemovePrograms to display by day/month/year?
This is the command I need to use
get-wmiobject -Class Win32Reg_AddRemovePrograms -ComputerName
AComputer| where {$_.DisplayName -notlike "hotfix" -and
$_.DisplayName -notlike "Security Update" -and $_.DisplayName
-notlike "*Update for Windows *"} | select DisplayName,Version,Publisher,InstallDate
If the InstallDate looks like the InstallDate of the Win32_Product class (e.g 20131209):
[DateTime]::ParseExact('20131209','yyyyMMdd',$null).ToString('dd/MM/yyyy')
just to let you know the Win32Reg_AddRemovePrograms class is not a common class, it is added by the SMS/SCCM. It also only shows info related to 32-bit programs. Source For that reason I do not have the class available on the station and cannot provide you with the exact steps . Please provide output of this commands:
$item = $gwmi Win32Reg_AddRemovePrograms | select -first 1
$item.InstallDate
$item.InstallDate.GetType().fullname
One way is to format the date like the example below.
$date=Get-Date
Monday, December 9, 2013 5:29:50 AM
$date.ToString("dd/MM/yyyy")
09/12/2013
EDIT:
I don't have access to Win32Reg_AddRemovePrograms, so not tested.
try adding this to the end:
| %{ $_.InstallDate = ($_.InstallDate.tostring("dd/MM/yyyy") ); $_ }
So the final: (added ` for line breaks)
get-wmiobject -Class Win32Reg_AddRemovePrograms -ComputerName AComputer| `
where {$_.DisplayName -notlike "hotfix" -and $_.DisplayName -notlike "Security Update" -and $_.DisplayName -notlike "*Update for Windows *"} | `
select DisplayName,Version,Publisher,InstallDate | `
%{ $_.InstallDate = ($_.InstallDate.tostring("dd/MM/yyyy") ); $_ }
Or if it is in the date format like Shay mentioned,
| %{ $_.InstallDate = ([DateTime]::ParseExact($_.InstallDate,'yyyyMMdd',$null).ToString('dd/MM/yyyy')) ;$_}
Full script:
get-wmiobject -Class Win32Reg_AddRemovePrograms -ComputerName AComputer| `
where {$_.DisplayName -notlike "hotfix" -and $_.DisplayName -notlike "Security Update" -and $_.DisplayName -notlike "*Update for Windows *"} | `
select DisplayName,Version,Publisher,InstallDate | `
%{ $_.InstallDate = ([DateTime]::ParseExact($_.InstallDate,'yyyyMMdd',$null).ToString('dd/MM/yyyy')) ;$_}