I've been working at this script for a while and I can't seem to figure it out:
$servers = Get-Content -path c:\users\jason\documents\skyperservers.txt
Foreach ($server in $servers){get-cswindowservice -computername $servers | where-object {$_.status -eq "running"}}
I keep getting the error
Get-CSWindowService : Cannot convert 'System.Object[]' to the type
'System.String' required by parameter 'ComputerName'. Specified method
is not supported...
Essentially, I'm trying to display all services from the command for each skype server and their service health status whether "running" or "stopped"
Two things about your code:
You are iterating the collection $servers using variable $server, but you do not use that as parameter for the Get-CSWindowService cmdlet. Instead you feed it the entire collection $servers (System.Object[]), which is what the error is telling you.
If you also want to see servers where the CsWindowService is stopped, add this to your Where-Object clause and best return objects so you can combine the service status with the server name.
Try
$servers = Get-Content -Path 'c:\users\jason\documents\skyperservers.txt'
$result = foreach ($server in $servers) {
Get-CsWindowService -ComputerName $server |
# or use regex: Where-Object {$_.Status -match 'Running|Stopped'}
Where-Object {$_.Status -eq 'Running' -or $_.Status -eq 'Stopped'} |
# include the server name in the output
Select-Object #{Name = 'ComputerName'; Expression = {$server}}, Status
}
Now you can display the results on screen
$result
or for instance save the results to a Csv file
$result | Export-Csv -Path 'X:\SkypeServers_Status.csv' -NoTypeInformation
Related
I have this script that changes services per a csv file input
Import-CSV .\SSAS_services.csv |
ForEach-Object{
Get-Service $_.Service -ComputerName $_.Server -PipelineVariable svc|
Set-Service -Status $_.Task -StartupType $_.'Startup Type' -PassThru
} |
Select-Object MachineName, Name, Status, StartType, #{n='OldStatus';e={$svc.Status}}, #{n='OldStartType';e={$svc.StartType}} |
tee-object -FilePath '.\ChangeServices_LOG.txt' #-Append
Server,Service,Startup Type,Task
DCVPIM108,SQL Server Analysis Services (MSSQLSERVER),automatic,start
server2,"SQL Server Analysis Services (MSSQLSERVER), SQL Server Analysis Services (MSSQLSERVER) CEIP",Manual,stop
it works great, except for my -PipelineVariable svcis not working as intended. if a service was "stopped" and "Manual" before being changed to "running" and "automatic", it doesnt get the old values "stopped" and "Manual" for OldStatus and OldStartType
MachineName : DCVPIM108
Name : MSSQLServerOLAPService
Status : Running
StartType : Automatic
OldStatus : Running
OldStartType : Automatic
why is that?
The -PipelineVariable / -pv common parameter only works:
within a single pipeline.
in script blocks in later segments of the same pipeline.
Since you're using it in a pipeline that is nested inside the ForEach-Object script block, the commands in the outer pipeline cannot use it.
However, I suggest restructuring your command so that you don't need a pipeline variable for Get-Service anymore.
Instead,
-PipelineVariable $csvRow is used with Import-Csv, so that you can more easily refer to it even in nested pipelines (the alternative would be to define the variable explicitly at the start of the ForEach-Object script block as $csvRow = $_).
$svc is then declared as an -OutVariable, so that the original service state is captured before Set-Service is called to change it.
Getting a service, setting its startup type, and enriching the CSV-row object with additional information now all happen inside the ForEach-Object script block.
Import-CSV .\SSAS_services.csv -PipelineVariable csvRow | ForEach-Object {
Get-Service -Name $csvRow.Service -ComputerName $csvRow.Server -OutVariable svc |
Set-Service -Status $csvRow.Task -StartupType $csvRow.'Startup Type'
$csvRow | Select-Object MachineName, Name, Status, StartType,
#{n='OldStatus';e={$svc.Status}},
#{n='OldStartType';e={$svc.StartType}}
} | Tee-object -FilePath '.\ChangeServices_LOG.txt'
I guess what you want is to pass same object down the multiple pipes. I haven't use -PipeLineVariable much, but looks like it just creating a nicer alias for $_ . If you need to push something specific down the pipeline I guess you need to use write-ouput with custom object or hashtable. Below is a dummy sample, pushing down and modifying a hastable:
$services = "xagt" , "xbgm" , "XblGameSave"
$list = new-object System.Collections.ArrayList
$serv | foreach {
$svc = Get-Service $_ ; Write-Output #{Name = $svc.Name; Stat=$svc.Status}
} | foreach {$_.SomeNewItem = "new stuff"; $list.Add($_)}
But in your case one pipeline might be sufficient. Try something like that:
Import-CSV .\SSAS_services.csv | foreach {
$old = Get-Service $_.Service;
Set-Service -Name $_.Service -Status Running
$new = Get-Service $_.Service;
$data = $_.MachineName, $_.Service, $old.Status, $new.Status -join ","
Write-Host $data
$data >> Log.txt
}
I wrote a PowerShell script that gets some cluster information. One of the columns I need is from the first argument in the pipeline and I can't find a way to return it's value.
function Get-SQL-Clusters {
Param([string]$server)
$servers = Get-Content -LiteralPath "C:\temp\sql_clusters.txt"
if ($server -ne 1) {
$files = foreach ($box in $servers) {
Invoke-Command -ComputerName $box {
Get-ClusterResource | Get-ClusterParameter
} | Where-Object {
$_.Name -eq "Address"
} | Format-Table PSComputerName, ClusterObject, State, Name, Value -AutoSize
}
} else {
Write-Warning "'$server' is not a valid path."
}
return $files
}
When I run this, I get the data I need but State is blank. It's in Get-ClusterResource, but the IP, which is what I'm mostly looking for, is in Get-ClusterParameter.
Ideally I would like to return the name of the cluster, each of the alwayson names, it's IP and it's current state so I can see if the active IP is on the primary site or on the DR site.
Your call to Invoke-Command places the Get-ClusterResource | Get-ClusterParameter calls into its own script block {...}, then pipes the results of evaluating those expressions to the Where-Object cmd. This may not be the intended order of operations.
Project your results using the Select-Object cmdlet at intermediate places in your pipeline to give you access to the desired properties at later stages (specific syntax hasn't been checked;YMMV):
Invoke-Command -ComputerName $box { Get-ClusterResource | Select-Object -Property State, #{Name="ClusterParameter";Expression = {(Get-ClusterParameter -InputObject $_) }}| Where-Object { $_.ClusterParameter.Name -eq ...
Will produce objects like:
State | ClusterParameter
------------------------
foo ClusterParameter.ToString()
The almost final code. It's not 100% complete but I get the State and IP values now and will fix the rest later. Another change I made was to stop using text files and created a hash table for my servers because of formatting problems I had with text files.
function Get-SQL-Clusters-scrap
{
param([string]$server)
import-module c:\temp\sql_hashtable2.ps1
$servers = $sql_servers.hadr
if ($server -ne 1)
{
$files = ForEach ($box in $servers) {invoke-command -ComputerName $box {Get-ClusterResource |
foreach-object {($state) = ($_.State); $_ |
get-clusterparameter |Where-Object {$_.Name -eq "Address"} |
Format-Table ClusterObject,#{Name=”State”;Expression={$state}}, Name, Value, PSComputerName -AutoSize}}}
}
else
{Write-Warning "'$server' is not a valid path."}
return $files
}
I wrote a script that would fetch all the services running under an account name.
This part works fine except I want to add results to an existing csv. Add-content is messing up with my format. Please help as i am new here.
script:
$servers = #("a", "b")
$domain = "abc.com"
foreach($server in $servers){
$serverFQDN = $server+"."+"$domain"
Invoke-Command -computername $serverFQDN{
param($server)
Write-host "On" + $server -ForegroundColor Yellow
Get-WMIObject Win32_Service | Where-Object {$_.startname -match "ciqdev*" }
# | where-object {$_.state -eq "running"}
}-argumentlist $server | select pscomputername,caption | export-Csv Z:\RT\myCSV.csv
}
Use -Append :
export-Csv Z:\RT\myCSV.csv -Append
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.
I am new to PowerShell and ran into a bit of a roadblock. I am trying to pull program name and version information from multiple servers.
I have a list of the program names in a $list variable, but the program names also contain the version numbers in them. I am just storing the names of the programs in the list variable without the version numbers.
I am trying to figure out a way to use both the -like and -in parameters with the Where-Object cmdlet in order to match the full program entry name (e.g. AdToUserCacheSync 1.10.1.10) with my entry in the $list variable (e.g. AdToUserCacheSync).
How can I do this?
$list = Get-Content "\\server\c$\temp\list.txt"
$storeTestServers = Get-Content "\\server\c$\temp\testStores.txt"
foreach ($server in $storeTestServers) {
Get-WmiObject -Class Win32_Product -ComputerName $server |
Select-Object -Property PSComputerName, Name, Version |
Where-Object {$_.pscomputername -like "940*" -and $_.name -like -in "*$list*"}
}
The Where-Object FilterScript block is just a scriptblock that returns $true, $false or nothing - you can do all kinds of crazy things inside it, including looping over an array to see if there is a wildcard match in one of the entries:
Where-Object {
$ProductName = $_.Name
$_.pscomputername -like "940*" -and (
$list | ForEach-Object {
if($ProductName -like "*$_*"){ return $true }
}
)
}
I found the Adobe version by PowerShell:
Get-WmiObject -Class Win32_Product -ComputerName 127.0.0.1 |
Select-Object -Property PSComputerName, Name, Version |
Where-Object {$_.Name -like "Adobe*"} | Out-File Adobe_Log.log