Using powershell to restart computers if -LastBootupTime = -gt 10 days - database

I'm trying to make a script that checks how long the computers on a network are on, and if they are on for more then 10 days they need to restart. I'm planning to run the script automatically with task manager every Sunday.
Thanks to #vonPryz I've got something like this now:
$clients = get-content "C:\Documents\lijstcomputers.txt"
foreach ($client in $clients) {
if (test-connection -computername $client -BufferSize 16 -Count 1 -Quiet) {
write-Host $client is online
$uptime = (get-date) - (gcim Win32_OperatingSystem -computer $client).LastBootUpTime
$startTime = [Management.ManagementDateTimeConverter]::ToDateTime((gwmi Win32_OperatingSystem -computer $client).lastbootuptime)
if( $uptime.days -ge 10) {
restart-computer -computername $client
add-content -path "c:\path\to\log.txt" -value "$client, $startTime, $uptime"
}
}
else {
write-Host $client is offline
}
}
But now I'm getting this error:
gcim : WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and
that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for publ
ic profiles limits access to remote computers within the same local subnet.
At line:1 char:25
+ $uptime = (get-date) - (gcim Win32_OperatingSystem -computer $client).LastBootUp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ConnectionError: (root\cimv2:Win32_OperatingSystem:String) [Get-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80338126,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
+ PSComputerName : ASND0042
Cannot find an overload for "op_Subtraction" and the argument count: "2".
At line:1 char:1
+ $uptime = (get-date) - (gcim Win32_OperatingSystem -computer $client).LastBootUp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest

Since you already got some parts covered, this isn't just a plz give me teh codez and thus warrants help. So let's outline how the whole script should look.
# Write computer names into a file, one per row for easier management
$clients = get-content "c:\ListOfComputers.txt"
foreach ($client in $clients) {
# If computer's not up, there's no need to check uptime
if (test-connection -computername $client -BufferSize 16 -Count 1 -Quiet) {
write-Host $client is online
# Get uptime
$uptime = (get-date) - (gcim Win32_OperatingSystem -computer $client).LastBootUpTime
# Get start time
$startTime = [Management.ManagementDateTimeConverter]::ToDateTime((gwmi Win32_OperatingSystem -computer $client).lastbootuptime)
# Restart the client if uptime's at least 10 days.
if( $uptime.days -ge 10) {
restart-computer -computername $client
# Add client name, start date and uptime into a log file
add-content -path "c:\path\to\log.txt" -value "$client, $startTime, $uptime"
}
}
else {
write-Host $client is offline
}
}
This skeleton can be further improved by adding some error handling and, say, proper CSV export.

Related

Powershell Format Arrays to two dimensional Arrays

i had a problem a few days ago where my script that is supposed to extract all hostnames from an AD OU and then check for the space used and free space on disks for every single host. Since this is the first time i do something with powershell i ran into many problems. The Problem that i got now is that the script cant find the hostnames listed in an array. I think i found out why it wont work because it uses the wrong hostname.
Error message i get for every hostname:
Write-Warning : Es wurde kein Positionsparameter gefunden, der das Argument "#{Name=BUCHHOLZMVZ}" akzeptiert.
In Zeile:16 Zeichen:5
+ Write-Warning "Server " $server "nicht erreichbar"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Warning], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WriteWarningCommand
When i only use the command to get all hostnames of all servers i get:
Name
----
someserver
someserver1
someserver2
(and so on...)
Here is the script:
$servers = Get-ADComputer -Filter * -SearchBase "OU=ServerOU, DC=somedomain, DC=somedomain, DC=somedomain" | Select-Object Name
$allDisks = foreach ($server in $servers)
{
try {
Get-WmiObject Win32_LogicalDisk -ComputerName $server -Filter DriveType=3 -ErrorAction Stop |
Select-Object #{'Name'='ComputerName'; 'Expression'={$server}},
DeviceID,
#{'Name'='Size'; 'Expression'={[math]::truncate($_.size / 1GB)}},
#{'Name'='Freespace'; 'Expression'={[math]::truncate($_.freespace / 1GB)}}
}
catch {
Write-Warning "Server " $server "nicht erreichbar"
Continue
}
}
$allDisks |Export-Csv C:\Servers.csv -NoTypeInformation
Use the following for your first line:
$servers = Get-ADComputer -Filter * -SearchBase "OU=ServerOU, DC=somedomain, DC=somedomain, DC=somedomain" |
Select-Object -Expand Name
Using Select-Object without -Expand or -ExpandProperty outputs an object that contains properties and values. If you only want to output values of the selected properties you must use -Expand or member access ($servers.Name).

Using Invoke-Command to Get Application Pools on Remote Servers

I'm attempting to use Invoke-Command to get a list of application pools on multiple remote servers. So far I have something like:
$servers = Get-Content -Path "C:\Path\to\servers.txt"
$array = New-Object -TypeName 'System.Collections.ArrayList'
foreach ($server in $servers) {
Invoke-Command -ComputerName $server -ScriptBlock {
Import-Module WebAdministration
$sites = Get-ChildItem IIS:\sites
foreach ($site in $sites) {
$array.Add($site.bindings)}}}
However I get the error:
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : computername
I've tried using regular arrays instead of ArrayLists and I get the following error:
Method invocation failed because [Microsoft.IIs.PowerShell.Framework.ConfigurationElement] doesn't contain a method named 'op_Addition'.
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
+ PSComputerName : computername
Can anyone help point me in the right direction?
Your object $arrayis not known on your remote servers. So, one proposition is to send your array to the remote server, then add some values and return it :
$servers = Get-Content -Path "C:\Path\to\servers.txt"
$array = New-Object -TypeName 'System.Collections.ArrayList'
foreach ($server in $servers) {
$array = Invoke-Command -ComputerName $server -ScriptBlock {
param($array)
Import-Module WebAdministration
$sites = Get-ChildItem IIS:\sites
foreach ($site in $sites) {
[void]($array.Add($site.bindings))
}
$array
} -ArgumentList $array
}

Powershell Script Issue with SQL Server 2012/2014

I have a PowerShell script which works well when I run it on server with SQL Server default instance (MSSQLSERVER) but the same script fails on a server with a named instance (MSSQL$instance)
For the default instance (MSSQLSERVER)
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$service = Get-service -name 'MSSQLSERVER'
$status = $service.status
$CreateDB = "db-Test"
if ( $status -eq "Running" )
{
'Success' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
$db.Create()
$db.CreateDate
}
else
{
'Failed' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
}
Above script works very well. But below script throws error :
For named instance :
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$service = Get-service -name 'MSSQL$instancename'
$status = $service.status
$CreateDB = "db-Test"
if ( $status -eq "Running" )
{
'Success' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
$srv = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")
$db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
$db.Create()
$db.CreateDate
}
else
{
'Failed' | Out-File -FilePath c:\sqltest.log -Encoding ASCII
}
Above script for named SQL instance throws below error :
New-Object : Exception calling ".ctor" with "2" argument(s): "SetParent failed for Database 'Netmagic-Test'. "
At C:\mssql-test.ps1:11 char:7
+ $db = New-Object Microsoft.SqlServer.Management.Smo.Database($srv, "$CreateDB")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\mssql-test.ps1:12 char:1
+ $db.Create()
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Error Screen
Thanks,
Viral

Powershell - Unable to Compare Strings Output from Sharepoint List

After extracting a list from SharePoint, I need to validate each Item against its BRTeam value. Here is the script:
cls
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$sourceWebUrl = "http://theoracle/WorkingHere/"
$sourceListName = "Policies & Procedures"
$spSourceWeb = Get-SPWeb $sourceWebUrl
$spSourceList = $spSourceWeb.Lists[$sourceListName]
$spSourceItems = $spSourceList.Items
$spSourceItems | ForEach-Object {
Write-Host $_['Name']
Write-Host $_['BRTeam']
}
The code works fine in terms of getting the data and writing the required items to the host.
However, if I add the following If-Statement to validate the items, I am seeing an error:
if ($_['BRTeam'].Contains('HR')) {
Write-Host $_['Name']
Write-Host $_['BRTeam']
}
I have also tried replacing the Boolean check with $x -contains 'HR' after assigning $x = $_['BRTeam'], but this returns no output (no error either). Error below:
Method invocation failed because [Microsoft.SharePoint.Taxonomy.TaxonomyFieldValue] doesn't contain a method named 'Contains'.
At line:21 char:9
+ if ($_['BRTeam'].Contains('HR')) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Can anyone let me know what I am missing here?
I was able to resolve this by using the -Match operator instead:
$spSourceItems | ForEach-Object {
#Write-Host $_['ID']
#Write-Host $_['Workflow Started']
$x = $_['BRTeam']
if ($_['BRTeam'] -Match 'HR') {
Write-Host $_['Name']
}
}
If I am concerned that some other BRTeams may contain HR without actually being HR, I could also perform a -NotMatch against all the other departments.
E.g.:
$spSourceItems | ForEach-Object {
#Write-Host $_['ID']
#Write-Host $_['Workflow Started']
$x = $_['BRTeam']
if ($_['BRTeam'] -Notmatch 'Accounts' -And $_['BRTeam'] -Notmatch 'IT') {
Write-Host $_['Name']
}
}

Looking to speed up this PowerShell Function

I'm running the following code to pull data from SCOM 2012 and using an exported spreadsheet from SCCM 2012, output servers which are pending reboot along with their SCCM maintenance window for automated scheduled reboots.
The code takes around 5-8 minutes to run and I was wondering if there was any way to speed up the process. The code running under Begin Loop is the bottle neck.
Function Generate-RebootData{
IF(Get-Command Get-SCOMAlert -ErrorAction SilentlyContinue){}ELSE{Import-Module OperationsManager}
"Get Pend reboot servers from prod"
New-SCOMManagementGroupConnection -ComputerName ProdSrv
$AlertData = get-SCOMAlert -Criteria `
"Severity = 1 AND ResolutionState < 254 AND Name = 'Pending Reboot'" |
Select NetbiosComputerName
"Get Pend reboot servers from cert"
#For cert information
New-SCOMManagementGroupConnection -ComputerName CertSrv
$AlertData += Get-SCOMAlert -Criteria `
"Severity = 1 AND ResolutionState < 254 AND Name = 'Pending Reboot'" |
Select NetbiosComputerName
"Remove duplicates"
$AlertDataNoDupe = $AlertData | Sort NetbiosComputerName -Unique
"Create hash table"
$table = #{}
"Populate hash table"
Import-Csv D:\Scripts\servers2.csv | ForEach-Object {
$table[$_.Computername] = $_.'Collection Name'}
"Create final object"
$result = #{}
"Begin Loop"
$result = $AlertDataNoDupe | ForEach-Object { [PSCustomObject] #{
Server=$_.NetbiosComputerName
MaintenanceWindow=IF($table[$_.NetbiosComputerName]){$table[$_.NetbiosComputerName]}
ELSE{"Not found!"}
PingCheck=IF(Test-Connection -Count 1 $_.NetbiosComputerName -Quiet -EA SilentlyContinue)
{"Alive"}
ELSE{"Dead"}
LastReboot=Try{
$operatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName `
$_.NetbiosComputerName -ErrorAction Stop
[Management.ManagementDateTimeConverter]::ToDateTime(`
$operatingSystem.LastBootUpTime)}
Catch{"Access Denied!"}
} }
}
You should perform the PingCheck first, and only if that succeeds move on with the Get-WmiObject call - there's no need to contact a machine if you've just determined that it's "dead".
...
$result = $AlertDataNoDupe | ForEach-Object {
# Create hashtable
$Properties = #{
Server = $_.NetbiosComputerName
MaintenanceWindow = if($table[$_.NetbiosComputerName]){
= $_.NetbiosComputerName
} else {
'Not found!'
}
}
# Perform ping check, keep as boolean
$Properties['PingCheck'] = Test-Connection -Count 1 $_.NetbiosComputerName -Quiet -EA SilentlyContinue
$Properties['LastReboot'] = if($Properties['PingCheck'])
{
try
{
# Server seems to be online
$operatingSystem = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $_.NetbiosComputerName -ErrorAction Stop
[Management.ManagementDateTimeConverter]::ToDateTime($operatingSystem.LastBootUpTime)
}
catch
{
'Access Denied!'
}
}
else
{
# If server doesn't respond, declare it offline
'Computer offline!'
}
# create the object
New-Object -TypeName psobject -Property $Properties
}

Resources