Wednesday, 14 January 2015

Use PowerShell to search Windows Event Logs

PowerShell is an excellent tool for searching through Windows event logs. I find myself using it more and more these days as it enables me to find the information I need much quicker than using the filter feature of the Event Viewer snap in.

The cmdlet to use for searching the event logs is get-eventlog. For the full help file from PowerShell, enter the following

help Get-EventLog -Full

The get-eventlog cmdlet uses the switch -LogName. This is used to specify the event log you want to search, eg System, Application etc.

To get a list of available event logs, enter

Get-EventLog -List

or

Get-EventLog -LogName *

 









You can then list all events from that event log with the command Get-EventLog -LogName LogName
Eg,

Get-EventLog -LogName System

This will return everything from the event log, probably hundreds or even thousands of events, so the next job is to filter for the events you are interested in.

We can examine an individual event log to get an idea of how to filter

Get-EventLog -LogName System -Newest 1

This command will return the most recent System event log
 






The information displayed is a subset of the complete data available for this event log. PowerShell will automatically select the columns to display so that it fits easily on the screen. To see everything, we need to pipe the output to the format-list cmdlet.

Get-EventLog -LogName System -Newest 1 | Format-List -Property *
This command returns all the properties and values for this event log











Now you can see all the familiar properties of the event, such as EventID, EntryType, Time Written etc. I can now filter my result based on one or more of these properties.

For example,
show all events where the message contains "the service entered the stopped state"
show all events where the event id equals 41 and the date is 10 Jan 2015
show all events where the EntryType is error, the source is Asp.Net or .Net runtime and the date is between 01 Jan - 10 Jan 2015

All of this is achieved by piping the results of get-eventlog to the where-object cmdlet

Get-EventLog -LogName System | Where-Object { $_.Message -like "*the service entered the stopped state*" }

In this example you can see that I have used the Message property of the event and the -like operator to match it to the text I am looking for.


Get-EventLog -LogName System | Where-Object { $_.EventID -eq 41 -and $_.TimeWritten -like "01/14/2015*" }
In this example you can see that I have used the EventID and TimeWritten properties of the event
$_.EventID -eq 41
$_.TimeWritten -like "01/14/2015*"

The -and operator links these two properties together


Get-EventLog -LogName System -After (Get-Date -Date '1/1/2015') -Before (Get-Date -Date '10/1/2015') | Where-Object { $_.EntryType -eq "Error" -and ($_.Source -like "Asp.Net*" -or $_.Source -like ".net runtime*") }

In this example I use the date property of the get-eventlog results to filter the events before passing them to the where-object cmdlet. This is done using the -before and -after switches. After that, the where-object command is used in the same way as the previous examples.

The only difference is the two $_.Source properties are surround by brackets (). This is necessary so that the -or operator applies to only those two entries. I could add more $_.Source properties inside the brackets with additional -or operators if I wanted to increase this list beyond 2.

Understanding the PowerShell operators is key to getting the results you want, this link contains useful information about operators
http://technet.microsoft.com/en-gb/library/hh847759.aspx

Finally, you can export your results using any of PowerShell's export commands. I find export-csv works well:

Get-EventLog -LogName System | Where-Object { $_.Message -like "*the service entered the stopped state*" } | Export-Csv C:\scripts\events.csv



Monday, 12 January 2015

PowerShell and IIS 6

IIS 6

Windows Server 2003 running IIS 6 does not support the latest version of PowerShell, and will not allow the use of the WebAdministration module or the most recent IIS cmdlets

(see this site for WebAdministration Cmdlets http://technet.microsoft.com/en-us/library/ee790599.aspx)

To use PowerShell with IIS 6, you must use WMI, specifically the IIS WMI provider. To do this, use the Get-WmiObject cmdlet.
The WMI namespace is root/Microsoftv2. The following link gives a list of classes that can be used:
http://msdn.microsoft.com/en-us/library/ms525265(v=vs.90).aspx


 

WMI Classes

I experimented with the different classes to find the properties that I needed. For example IISWebServer will give information on each site, IISWebServerSetting will give more detailed information on each site. IISWebVirtualDir will give information on virtual directories and applications and IISWebVirtualDirSetting will again give more detail on virtual directories and applications.

For example, try running each of these commands, then view the results to see how the output changes.

Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServerSetting
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebVirtualDir
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebVirtualDirSetting

The next step is to use the where-object and select-object cmdlets to display only the results you want.

Eg.
This command will return a list of sites by site ID
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer | Select-Object -ExpandProperty Name

Whereas this command will return a specific site by specifying the site ID
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer | Where-Object { $_.Name -like "W3SVC/123456789" }

Also, this command will return a specific site by specifying the site ID along with all the settings for that site
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServerSetting | Where-Object { $_.Name -like "W3SVC/123456789" }

I was interested in listing all Physical Paths that were being used by each site in IIS. For this I need the IISWebVirtualDirSetting class and the Path property

Eg.
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebVirtualDirSetting | Select-Object -ExpandProperty Path
 

I can also add the -unique switch to eliminate any duplicates, and pipe the results to sort-object to put the output in alphabetical order

Eg,
Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebVirtualDirSetting | Select-Object -ExpandProperty Path -Unique | Sort-Object
 

Script


I put this all together into a script that will output the site name followed by a list of all Physical Paths in use by IIS. One of the challenges here was identifying a class that contained both the site name and physical path. This was not possible with one class, so I had to do it in stages.

I obtained the Name property from IIsWebServer class. This is the Site ID, and I can use this to filter both ServerComment property from IIsWebServerSetting class for a user friendly website name, and the path property from IIsWebVirtualDirSetting for the Physical Path

Script text


$WebSiteID = Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer | Select-Object -ExpandProperty Name

ForEach ( $Site in $WebSiteID )

{
$WebSiteName = Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServerSetting | Where-Object { $_.Name -like "$site" } | Select-Object -Expandproperty ServerComment

write-host "`r`n" $WebSiteName

$AppPath = Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebVirtualDirSetting | Where-Object { $_.Name -like "$site/*" } | select -expandproperty path

$AppPath = $AppPath | select-object -unique | sort-object
$AppPath
}


One more thing to note is that I use -ExpandProperty rather than -Property to filter the results from the where-object and select-object cmdlets. This is to convert the output to a string. If I don't do this, I get the object itself, rather than a string containing the objects. To see what this actually means, try running these two commands and notice the difference in the results and the available methods and properties.

Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer | Select-Object -Property Name | Get-Member
 

Get-WmiObject -Namespace "root/MicrosoftIISv2" -Class IIsWebServer | Select-Object -ExpandProperty Name | Get-Member












Friday, 30 May 2014

Use PowerShell to set random periodic restart time on all Application Pools

I have written a PowerShell script that will look at all IIS Application Pools, then set the recycle setting for Specific Time to a random time between 02.01 - 02.59.

It will create a log file D:\AppPoolRestart.txt which contains the App Pool name and the recycle time.



import-module webadministration
$AppPools = get-item -Path IIS:\AppPools\*
If (Test-Path D:\scripts\AppPoolRestart.txt) 
{
remove-item -path D:\AppPoolRestart.txt
}

ForEach ( $app in $appPools )

$minute = Get-Random -Minimum 1 -Maximum 59
$Name = $app.Name
$time = "02:"+"$minute"+":00"
Set-ItemProperty -Path IIS:\AppPools\$Name -Name Recycling.periodicRestart.schedule.collection -Value @{value="$time"}
$output = "$Name"+" $time"
out-file -Filepath D:\AppPoolRestart.txt -inputobject "$output" -append
}

Thursday, 24 November 2011

SBS 2008 C drive runs out of space - shrink SharePoint database log file

I have seen serveral cases recently where a server running Small Business Server 2008 has run out of space on the C Drive. Using Tree Size, I identified a folder which contained a large amount of data:

C:\Windows\SYSMSI

The area of this folder which contained all the data was

C:\Windows\SYSMSI\SSEE\MSSQL.2005\MSSQL\Data

This folder contained many SQL databases and log files, and after some research I discovered that my largest files were Transactional Log files for Sharepoint.

The biggest of these files was


SharePoint_Config_ffffffff-ffff-ffff-ffff-fffffffffffffffffff_log.LDF

 and was up to 16Gb in size, but other culprits were


ShareWebDb_log.LDF
WSS_Content_fffff..._log.LDF



Large SharePoint log files
 




All these files are log files which can easily be shrunk down to a manageable size. SQL Server Management Studio is required for this.


To run SQL Management Studio, select

Start > All Programs > Microsoft SQL Server 2005 > SQL Server Management Studio Express



 


















Server name is
\\.\pipe\mssql$microsoft##ssee\sql\query
 

Then select Connect

Expand Databases and locate the datebase with the large log file



















Right click on the database and select New query

























The query window will appear on the right. Enter the following text:

ALTER DATABASE Database_name SET RECOVERY SIMPLE;
GO








Then click the Execute! button


If the database name contains a ' - ', you will get an error message (below).



In this case, the database name must be surrounded by " ", eg:


ALTER DATABASE "SharePoint_Config_29c26fca-17b8-48c1-9704-b869932abcb6" SET RECOVERY SIMPLE;
GO


Then select Execute!



You should see a message which reads Commad(s) completed successfully

Next, Select the database


Right click > Tasks > Shrink > Files


Change File type to Log

Click OK



Once this process has completed, right click the database again and select New query
Enter the following command (use " " around database_name if it contains ' - ')

ALTER DATABASE Database_name SET RECOVERY FULL;
GO

Execute!


Browse to the folder location

C:\Windows\SYSMSI\SSEE\MSSQL.2005\MSSQL\Data

and you should see a big difference in the size of the log file.

Tuesday, 2 August 2011

Backup Exec job status switches between Queued and Loading Media

I needed to restore two files today, which were backed up to external hard disk using Backup Exec (v12.5). I connected the drive which contained the backup data, then ran an inventory. I then created a restore job, selected my files to restore, then started the job running.

The Job Status changed to Queued, then to Loading Media, then back to Queued again.
This cycle continued, and the job would not start, it just remained cycling between Queued and Loading Media.

I resolved this bythe following process:

Select Devices, then in the Devices panel, right click the server name, then select Pause

Right click the server name again, then select Backup Exec services, then select Restart all services.
Wait for all the services to restart, then click OK to the messages that are displayed.

Right click on the server name in Devices again, and remove the tick from Paused

Restart all the services again.

Once I had done this, I ran the backup job again (Right click, Retry Job Now), and the job completed without any problem.

Nick