I have script that checks every 24 hours locally on server the status of all backup jobs along more details.
I want that script to check all my servers, lets say: "SRV1", "SRV2", "SRV3"
How can i manage that?
Here's the script:
$date = (Get-Date).AddHours(-24)
$sessions = Get-VBRComputerBackupJobSession
foreach ($PBackup_job in (Get-VBRComputerBackupJob | Select Name)) {
$PBackup_job_name = $PBackup_job.Name
write "------------ Physical Server Backup Job Name : $PBackup_job_name ------------"
$sessions | where {$_.CreationTime -ge $date} | sort CreationTime | Select CreationTime, endtime, result, state | Format-Table
}
Although I cannot test this myself, I think you could do that using Invoke-Command like below:
$servers = "SRV1", "SRV2", "SRV3"
# set the credentials for admin access on the servers
$cred = Get-Credential 'Please enter your admin credentials'
$result = Invoke-Command -ComputerName $servers -Credential $cred -ScriptBlock {
$date = (Get-Date).AddHours(-24).Date
$sessions = Get-VBRComputerBackupJobSession
foreach ($PBackup_job in (Get-VBRComputerBackupJob)) {
$sessions | Where-Object {$_.CreationTime -ge $date} |
Sort-Object CreationTime |
Select-Object #{Name = 'Server'; Expression = {$env:COMPUTERNAME}},
#{Name = 'BackupJobName'; Expression = {$PBackup_job.Name}},
CreationTime, endtime, result, state
}
}
# remove the extra properties PowerShell added and save to CSV
$result = $result | Select-Object * -ExcludeProperty PS*, RunSpaceId
# output on screen
$result | Format-Table -AutoSize
# write to file
$result | Export-Csv -Path 'X:\Somewhere\BackupJobs.csv' -NoTypeInformation
Related
I need to generate a csv containing running services to csv with the corresponding computer name
I know there is a simple way to do this and I have been tinkering with creating a new psobject, but I am not sure how to pipe the results to the new-object...
Here is what I am using:
$Input = "SomePath"
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "$Input"
ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Export-csv -Path "$Output"
}
What I need in the CSV is:
ComputerName, ServiceName, DisplayName
basically, I need to add the computer name to the array.
If you want to be able to pipe the results, use a foreach-object.
$Output = "SomeOtherPath"
Get-Content -Path "SomePath" | ForEach-Object {
Get-Service -ComputerName $_ | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName
} | Export-csv -Path "$Output"
If you want to stick to a foreach statement, collect it all first then export it.
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "SomePath"
$results = ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName
}
$results | Export-csv -Path "$Output"
Try like this (Don't use $Input as variable name)
$InputX = "SomePath"
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "$Input"
ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName | Export-csv -Path "$Output"
}
I am creating a script to retrieve all the machine names from a .txt file then Query against them;
ComputerName
UserName (Of the last person to logon to the machine)
Date it was last Logged on to/Used
This is what i have
Clear-Host
$machines = Get-Content -Path C:\Users\khalifam\Desktop\Winver\MachineNames.txt
ForEach ($Compu in $machines) {
Get-WmiObject –ComputerName $machines –Class Win32_ComputerSystem | Select
Username, PSComputerName | FT
}
As sidenotes:
the hyphens for the parameter names are not hyphens, but En-Dashes, so I gather this code is copied from the internet somewhere
inside the loop you are using the wrong variable on the ComputerName parameter which should be $Compu
Having said that, I don't think you can get the info you need from the WMI Win32_ComputerSystem class..
What you will need to do is to parse the info from the computers eventlog:
# get an array of computernames loaded from the text file
$machines = Get-Content -Path C:\Users\khalifam\Desktop\Winver\MachineNames.txt
$result = foreach ($computer in $machines) {
# test if the compurer is on-line
if (!(Test-Connection -ComputerName $computer -Count 1 -Quiet)) {
Write-Warning "Computer '$computer' is off-line."
# skip this computer and carry on with the next iteration
continue
}
# search the computers eventlog and parse the username and last logon time from that
# you can play around with other values for -MaxEvents if you feel you're missing information.
Get-WinEvent -ComputerName $computer -FilterHashtable #{Logname='Security';ID=4672} -MaxEvents 20 |
Where-Object { $_.Properties[1].Value -notmatch 'SYSTEM|NETWORK SERVICE|LOCAL SERVICE' } |
Select-Object #{Name ='ComputerName'; Expression = {$_.MachineName}},
#{Name ='UserName'; Expression = {$_.Properties[1].Value}},
#{Name ='LastLogon'; Expression = {$_.TimeCreated}} -First 1
}
# show on screen:
$result | Format-Table -AutoSize
# save as CSV file
$result | Export-Csv -Path 'D:\LastLogonInfo.csv' -NoTypeInformation
Update
If I understand your comment correctly, you would like a list of all users (except for a few) and retrieve their latest login on a computer from the list.
In that case you can do the following:
# get an array of computernames loaded from the text file
$machines = Get-Content -Path C:\Users\khalifam\Desktop\Winver\MachineNames.txt
$result = foreach ($computer in $machines) {
# test if the compurer is on-line
if (!(Test-Connection -ComputerName $computer -Count 1 -Quiet)) {
Write-Warning "Computer '$computer' is off-line."
# skip this computer and carry on with the next iteration
continue
}
# you do not want to include these account logins
$exclude = '\$|SYSTEM|NETWORK SERVICE|LOCAL SERVICE|KHALIFAM'
# search the computers eventlog and parse the username and last logon time from that
# you can play around with other values for -MaxEvents if you feel you're missing information.
Get-WinEvent -ComputerName $computer -FilterHashtable #{Logname='Security';ID=4672} -MaxEvents 100 |
Where-Object { $_.Properties[1].Value -notmatch $exclude } |
Select-Object #{Name ='ComputerName'; Expression = {$_.MachineName}},
#{Name ='UserName'; Expression = {$_.Properties[1].Value}},
#{Name ='LastLogon'; Expression = {$_.TimeCreated}} |
Group-Object -Property UserName | ForEach-Object {
$_.Group | Sort-Object LastLogon -Descending | Select-Object -First 1
}
}
# show on screen:
$result | Format-Table -AutoSize
# save as CSV file
$result | Export-Csv -Path 'D:\LastLogonInfo.csv' -NoTypeInformation
I have a script here that will return the information I need from the certificates binded in IIS from different web servers.
$Date = Get-Date
$servers = Get-Content C:\servers.txt
$cert = Foreach ($server in $servers) {
Invoke-Command -ComputerName $server -ScriptBlock{
Import-Module WebAdministration; Get-ChildItem -Path IIS:SslBindings | ForEach-Object -Process{
if ($_.Sites)
{
$certificate = Get-ChildItem -Path CERT:LocalMachine\My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
[PSCustomObject]#{
Sites = $_.Sites.Value
DnsNameList = $certificate.DnsNameList
NotAfter = $certificate.NotAfter
ExpireInDays = ($certificate.NotAfter - (Get-Date)).Days}
}
}
}
}
$cert | Select PSComputerName, DnsNameList, NotAfter, ExpireInDays | Where-Object {$_.ExpireInDays -lt 30} | Out-File C:\results.txt
This is what the output looks like in notepad:
PSComputerName DnsNameList NotAfter ExpireInDays
-------------- ----------- -------- ------------
ComputerName {URL.com} 1/1/2050 11:59:59 PM 11744
It returns a long lists of certificates with the supporting details. What I need to do is to put the details for the certificate\s which is\are expiring within 30 days into another TXT file in order for me to parse the content or attach the file itself in an email notification.
If you think there are more other ways to work around or simplify this script, I'm very open to recommendations. Thanks in advance.
Try something like this, which is taken from a script I use for a similar task:
# Note: It's usually better to filter with Where-Object and then Select-Object
$ExpiringCerts = $cert | Where-Object { $_.ExpireInDays -lt 30 } | Select-Object -Properties PSComputerName, DnsNameList, NotAfter, ExpireInDays;
if ($ExpiringCerts) {
$MailSettings = #{
SmtpServer = 'smtp.example.com';
Port = 25;
UseSsl = $false;
Subject = 'Subject Line';
To = 'to#example.com','other#example.com'
From = 'from#example.com';
Body = $ExpiringCerts | ConvertTo-Html -As Table -Fragment | Out-String;
BodyAsHtml = $true;
};
Send-MailMessage #MailSettings;
}
If you really need the results as a file attachment, then you can save the output to a file and use the -Attachment parameter on Send-MailMessage. Usually for this sort of notification using the email body makes a lot more sense, however.
I want to get the most errors of a list of servers and save it in the variable $AllErrors.
But the variable is empty if I want to print it out.
Is there a way to pass the variable out of the Invoke-Command?
This is my code:
Get-Content -Path C:\Users\$env:USERNAME\Desktop\Server.txt |
ForEach-Object{
Invoke-Command -ComputerName $_ -ScriptBlock{
$Date = (Get-Date).AddHours(-12)
$Events = Get-WinEvent -FilterHashtable #{LogName = 'System'; StartTime = $Date; Level = 2}
$Errors = $Events | Group-Object -Property ID -NoElement | Sort-Object -Property Count -Descending |
Select-Object -Property Name -First 1
}
}
$Errors | Out-File -FilePath C:\Users\$env:USERNAME\Desktop\AllErrors.txt
No, it's not possible, however you can assign the output of Invoke-Command to a variable. $Errors seems to be the only output of your Invoke-Command, so this should work. But looking at your code you will only get Errors for the last computer as you are constantly overwriting the $Errors variable in cycle. You should either declare $Errors outside of cycle, and append errors to it, or append to file after each cycle:
Get-Content -Path C:\Users\$env:USERNAME\Desktop\Server.txt |
ForEach-Object{
$Errors = Invoke-Command -ComputerName $_ -ScriptBlock{
$Date = (Get-Date).AddHours(-12)
$Events = Get-WinEvent -FilterHashtable #{LogName = 'System'; StartTime = $Date; Level = 2}
$Events | Group-Object -Property ID -NoElement | Sort-Object -Property Count -Descending |
Select-Object -Property Name -First 1
}
$Errors | Out-File -FilePath C:\Users\$env:USERNAME\Desktop\AllErrors.txt -Append
}
As an administrator I can get a users processes by running this
Get-Process -IncludeUserName | Where UserName -match test
But as a non-administrator I can't use -IncludeUserName becuase "The 'IncludeUserName' parameter requires elevated user rights".
So if I'm logged on as the user test, how do I list only his processes and not everything that's running?
This is faster, one line, doesn't require admin.
Get-Process | ? {$_.SI -eq (Get-Process -PID $PID).SessionId}
You can do that through WMI. Here is an excerpt of an article you can find here.
$View = #(
#{l='Handles';e={$_.HandleCount}},
#{l='NPM(K)';e={ (Get-Process -Id $_.ProcessId).NonpagedSystemMemorySize/1KB -as [int]}},
#{l='PM(K)';e={ $_.PrivatePageCount/1KB -as [int]}},
#{l='WS(K)';e={ $_.WorkingSetSize/1KB -as [int]}},
#{l='VM(M)';e={ $_.VirtualSize/1mB -as [int]}},
#{l='CPU(s)';e={ (Get-Process -Id $_.ProcessId).CPU -as [int]}},
#{l='Id';e={ $_.ProcessId}},
'UserName'
#{l='ProcessName';e={ $_.ProcessName}}
)
Get-WmiObject Win32_Process | % { $_ |
Add-Member -MemberType ScriptProperty -Name UserName -Value {
'{0}\{1}' -f $this.GetOwner().Domain,$this.GetOwner().User
} -Force -PassThru
} | ? UserName -match $env:USERNAME | ft $View -AutoSize
Get-Process alone will not give you this information, you'll need WMI:
$owners = #{}
gwmi win32_process |% {$owners[$_.handle] = $_.getowner().user}
$ps = get-process | select processname,Id,#{l="Owner";e={$owners[$_.id.tostring()]}}
foreach($p in $ps) {
if($p.Owner -eq $env:USERNAME) {
$p
}
}
Thanks for your code. Based on this, I created a modified version to allow users to kill (a subset of) their own processes:
#Script to allow users to kill (a subset of) their own processes
#Based on : https://stackoverflow.com/questions/35195221/list-process-for-current-user
#Previously we used Task Nanny created by Michel Stevelmans which is a lot faster, but it did not show a process that was causing issues for our users.
$UserProcesses = #()
$Owners = #{}
Get-WmiObject win32_process | Foreach{$owners[$_.handle] = $_.getowner().user}
$Processes = Get-Process | select processname,Description,Id,#{l="Owner";e={$owners[$_.id.tostring()]}}
Foreach($Process in $Processes)
{
IF($process.Owner -eq $env:USERNAME)
{
$UserProcesses += $Process
}
}
$UserProcessesToExclude = #(
'concentr', #Citrix Connection Center
'conhost', #Console Window Host
'dwm', #Desktop Windows Manager
'explorer', #Explorer
'Receiver', #Citrix Receiver Application
'rundll32', #Windows host process (Rundll32)
'ssonsvr', #Citrix Receiver
'taskhost' #Host Process for Windows Tasks
'wfcrun32' #Citrix Connection Manager
'wfshell' #Citrix wfshell shell
)
$UserProcesses | Where{$_.ProcessName -notin $UserProcessesToExclude} | Out-GridView -Title 'Task killer - Select the process(es) you want to kill. Hold CTRL to select multiple processes.' -PassThru | Foreach{Stop-Process -id $_.Id}