IIS log housekeeper service
A simple IIS log rotation Windows service with automatic/manual log location discovery and subfolder traversal for IIS 6 (Windows Server 2003), IIS 7.x (Windows Server 2008) and IIS 8.x (Windows Server 2012). The complete VB.Net source code is included in the download package.![Log rotation event log screenshot](pics/log_rotation_event_log_screenshot.png)
Download IisLogHousekeeper for IIS 6.x
Download IisLogHousekeeper for IIS 7.x / 8.x
Installation instructions:
- Download the zip file matching the server's IIS version and extract it to the server's "Program files (x86)" or "Program files" folder.
- Open IisLogHousekeeper.exe.config in a text editor and adjust the schedule, the log retention period and optionally the manual log locations (see configuration reference further down this page).
- Install and start the service by running ServiceInstall.vbs. The service can be uninstalled using ServiceUninstall.vbs.
- Check the service status in the Windows Application Event log. Events will be marked with the name "IisLogHousekeeper".
The standard disclaimer: The program is provided 'as is' without warranty of any kind. I have done my best to incorporate graceful exception handling and to test the code in different scenarios, so it shouldn't be able to do anything bad or unintended. But I guarantee nothing.
This IIS log housekeeper service is a further development of my old VBScript automatic log housekeeping scripts. But they differ in functionality. If you also need archiving/compression of log files, they should be used instead.
IisLogHousekeeper.exe.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SimulationMode" value="False"/>
<add key="RunAt" value="03:00"/>
<add key="LogRetentionDays" value="30"/>
<add key="UseManualLogLocations" value="False"/>
<add key="ManualLogLocations" value="C:\inetpub\logs\LogFiles|C:\WINDOWS\system32\LogFiles"/>
</appSettings>
</configuration>
<configuration>
<appSettings>
<add key="SimulationMode" value="False"/>
<add key="RunAt" value="03:00"/>
<add key="LogRetentionDays" value="30"/>
<add key="UseManualLogLocations" value="False"/>
<add key="ManualLogLocations" value="C:\inetpub\logs\LogFiles|C:\WINDOWS\system32\LogFiles"/>
</appSettings>
</configuration>
IisLogHousekeeper.vb (for IIS 6.x):
Imports System
Imports System.DirectoryServices
Imports System.Text
Imports System.IO
Imports System.Configuration
Imports System.Threading
Imports System.ServiceProcess
Imports System.Diagnostics
Imports System.Reflection
<Assembly: AssemblyTitle("IisLogHousekeeper 1.1 IIS6x edition")>
<Assembly: AssemblyDescription("IIS log housekeeping service")>
<Assembly: AssemblyCompany("www.700c.dk")>
<Assembly: AssemblyProduct("IisLogHousekeeper")>
<Assembly: AssemblyCopyright("Creative Commons Attribution (CC BY 3.0) https://creativecommons.org/licenses/by/3.0/ Reference source https://www.700c.dk/?code-iis-log-housekeeper-service")>
<Assembly: AssemblyVersion("1.1.0.0")>
<Assembly: CLSCompliant(True)>
Public Class IisLogHousekeeper
Private Shared ServiceThread As Thread
Private Shared KeepRunning As Boolean = True
Protected Overrides Sub OnStart(ByVal args() As String)
WriteToEventLog("IisLogHousekeeper starting", 1110)
ServiceThread = New Thread(AddressOf RunWorkerThread)
ServiceThread.Start()
End Sub
Protected Overrides Sub OnStop()
KeepRunning = False
WriteToEventLog( _
"IisLogHousekeeper stopping. Please note: the worker process " & _
"will live on for up to 60 seconds before it terminates.", 1110)
End Sub
Public Sub RunWorkerThread()
Dim aFolders() As String = {}
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "true" Then
aFolders = Split(ConfigurationManager.AppSettings("ManualLogLocations"), "|")
End If
Dim sRunResult As String = ""
Do While KeepRunning
If ConfigurationManager.AppSettings("RunAt") = Date.Now.ToString("HH:mm") Then
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "false" Then
Try
aFolders = GetIisLogFoldersThroughADSI()
Catch e As Exception
WriteToEventLog("Could not get IIS log locations through ADSI. Error message: " & e.Message, 1112)
End Try
End If
Try
For i As Integer = 0 to UBound(aFolders)
sRunResult = sRunResult & _
DeleteLogFilesRecursive(aFolders(i), CInt(ConfigurationManager.AppSettings("LogRetentionDays")))
Next
If sRunResult <> "" Then
WriteToEventLog(sRunResult, 1111)
sRunResult = ""
End If
Catch e As Exception
WriteToEventLog("An error occurred while cleaning up logs: " & e.Message, 1112)
End Try
End If
Thread.Sleep(60000)
Loop
End Sub
Public Function WriteToEventLog(ByVal Entry As String, _
Optional ByVal EventID As Integer = 0, _
Optional ByVal AppName As String = "IisLogHousekeeper", _
Optional ByVal EventType As _
EventLogEntryType = EventLogEntryType.Information, _
Optional ByVal LogName As String = "Application") As Boolean
Dim objEventLog As New EventLog()
Try
If Not Diagnostics.EventLog.SourceExists(AppName) Then
Diagnostics.EventLog.CreateEventSource(AppName, LogName)
End If
objEventLog.Source = AppName
objEventLog.WriteEntry(Entry, EventType, EventID)
Return True
Catch Ex As Exception
Return False
End Try
objEventLog.Dispose()
End Function
Public Function GetIisLogFoldersThroughADSI() As String()
Dim sFolderList As String = ""
Dim deIisRootObject As New DirectoryEntry("IIS://localhost")
Dim deIisSubItems As DirectoryEntry
Dim deIisNodeObj As DirectoryEntry
For Each deIisSubItems in deIisRootObject.Children
If LCase(deIisSubItems.SchemaClassName) = "iiswebservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/W3SVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iiswebserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\W3SVC" & deIisNodeObj.Name & "|"
End If
Next
ElseIf LCase(deIisSubItems.SchemaClassName) = "iissmtpservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/SMTPSVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iissmtpserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\SMTPSVC" & deIisNodeObj.Name & "|"
End If
Next
ElseIf LCase(deIisSubItems.SchemaClassName) = "iisftpservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/MSFTPSVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iisftpserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\MSFTPSVC" & deIisNodeObj.Name & "|"
End If
Next
End If
Next
If Right(sFolderList, 1) = "|" Then
sFolderList = Left(sFolderList, Len(sFolderList) - 1)
End If
Return Split(sFolderList, "|")
End Function
Public Function DeleteLogFilesRecursive(ByVal sLogPath As String, ByVal iDelAge As Integer) As String
Dim sReturn As String = ""
If Directory.Exists(sLogPath)
Dim dInfo As New DirectoryInfo(sLogPath)
Dim fInfo as FileSystemInfo
Dim sTempString As String = ""
For Each fInfo In dInfo.GetFileSystemInfos()
If fInfo.Attributes = FileAttributes.Directory Then
sReturn = sReturn & DeleteLogFilesRecursive(fInfo.FullName, iDelAge)
Else
If (InStr(fInfo.FullName, "ex") > 0) And (Right(fInfo.FullName, 4) = ".log") Then
If DateDiff("d", fInfo.LastWriteTime, Now) > iDelAge Then
Try
sTempString = fInfo.FullName & " deleted." & VbCrLf
If LCase(ConfigurationManager.AppSettings("SimulationMode")) = "false" Then
File.Delete(fInfo.FullName)
sReturn = sReturn & sTempString
Else
sReturn = sReturn & "[Simulation mode enabled] " & sTempString
End If
Catch e As Exception
sReturn = sReturn & fInfo.FullName & " could not be deleted. Error message: " & e.Message & VbCrLf
End Try
End If
End If
End If
Next
End If
Return sReturn
End Function
End Class
<System.ComponentModel.RunInstaller(True)> _
Public Class ProjectInstaller
Inherits System.Configuration.Install.Installer
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer
Private Sub InitializeComponent()
Me.ServiceProcessInstaller1 = New ServiceProcessInstaller
Me.ServiceInstaller1 = New ServiceInstaller
Me.ServiceProcessInstaller1.Account = ServiceAccount.LocalSystem
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
Me.ServiceInstaller1.ServiceName = "IisLogHousekeeper"
Me.ServiceInstaller1.StartType = ServiceStartMode.Automatic
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
Friend WithEvents ServiceProcessInstaller1 As ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As ServiceInstaller
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class IisLogHousekeeper
Inherits System.ServiceProcess.ServiceBase
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
ServicesToRun = New System.ServiceProcess.ServiceBase() {New IisLogHousekeeper}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.ServiceName = "IisLogHousekeeper"
End Sub
End Class
Imports System.DirectoryServices
Imports System.Text
Imports System.IO
Imports System.Configuration
Imports System.Threading
Imports System.ServiceProcess
Imports System.Diagnostics
Imports System.Reflection
<Assembly: AssemblyTitle("IisLogHousekeeper 1.1 IIS6x edition")>
<Assembly: AssemblyDescription("IIS log housekeeping service")>
<Assembly: AssemblyCompany("www.700c.dk")>
<Assembly: AssemblyProduct("IisLogHousekeeper")>
<Assembly: AssemblyCopyright("Creative Commons Attribution (CC BY 3.0) https://creativecommons.org/licenses/by/3.0/ Reference source https://www.700c.dk/?code-iis-log-housekeeper-service")>
<Assembly: AssemblyVersion("1.1.0.0")>
<Assembly: CLSCompliant(True)>
Public Class IisLogHousekeeper
Private Shared ServiceThread As Thread
Private Shared KeepRunning As Boolean = True
Protected Overrides Sub OnStart(ByVal args() As String)
WriteToEventLog("IisLogHousekeeper starting", 1110)
ServiceThread = New Thread(AddressOf RunWorkerThread)
ServiceThread.Start()
End Sub
Protected Overrides Sub OnStop()
KeepRunning = False
WriteToEventLog( _
"IisLogHousekeeper stopping. Please note: the worker process " & _
"will live on for up to 60 seconds before it terminates.", 1110)
End Sub
Public Sub RunWorkerThread()
Dim aFolders() As String = {}
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "true" Then
aFolders = Split(ConfigurationManager.AppSettings("ManualLogLocations"), "|")
End If
Dim sRunResult As String = ""
Do While KeepRunning
If ConfigurationManager.AppSettings("RunAt") = Date.Now.ToString("HH:mm") Then
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "false" Then
Try
aFolders = GetIisLogFoldersThroughADSI()
Catch e As Exception
WriteToEventLog("Could not get IIS log locations through ADSI. Error message: " & e.Message, 1112)
End Try
End If
Try
For i As Integer = 0 to UBound(aFolders)
sRunResult = sRunResult & _
DeleteLogFilesRecursive(aFolders(i), CInt(ConfigurationManager.AppSettings("LogRetentionDays")))
Next
If sRunResult <> "" Then
WriteToEventLog(sRunResult, 1111)
sRunResult = ""
End If
Catch e As Exception
WriteToEventLog("An error occurred while cleaning up logs: " & e.Message, 1112)
End Try
End If
Thread.Sleep(60000)
Loop
End Sub
Public Function WriteToEventLog(ByVal Entry As String, _
Optional ByVal EventID As Integer = 0, _
Optional ByVal AppName As String = "IisLogHousekeeper", _
Optional ByVal EventType As _
EventLogEntryType = EventLogEntryType.Information, _
Optional ByVal LogName As String = "Application") As Boolean
Dim objEventLog As New EventLog()
Try
If Not Diagnostics.EventLog.SourceExists(AppName) Then
Diagnostics.EventLog.CreateEventSource(AppName, LogName)
End If
objEventLog.Source = AppName
objEventLog.WriteEntry(Entry, EventType, EventID)
Return True
Catch Ex As Exception
Return False
End Try
objEventLog.Dispose()
End Function
Public Function GetIisLogFoldersThroughADSI() As String()
Dim sFolderList As String = ""
Dim deIisRootObject As New DirectoryEntry("IIS://localhost")
Dim deIisSubItems As DirectoryEntry
Dim deIisNodeObj As DirectoryEntry
For Each deIisSubItems in deIisRootObject.Children
If LCase(deIisSubItems.SchemaClassName) = "iiswebservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/W3SVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iiswebserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\W3SVC" & deIisNodeObj.Name & "|"
End If
Next
ElseIf LCase(deIisSubItems.SchemaClassName) = "iissmtpservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/SMTPSVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iissmtpserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\SMTPSVC" & deIisNodeObj.Name & "|"
End If
Next
ElseIf LCase(deIisSubItems.SchemaClassName) = "iisftpservice" Then
Dim deIisService As New DirectoryEntry("IIS://localhost/MSFTPSVC")
For Each deIisNodeObj in deIisService.Children
If LCase(deIisNodeObj.SchemaClassName) = "iisftpserver" Then
sFolderList = sFolderList & _
deIisNodeObj.Properties("LogFileDirectory").Value.ToString() & _
"\MSFTPSVC" & deIisNodeObj.Name & "|"
End If
Next
End If
Next
If Right(sFolderList, 1) = "|" Then
sFolderList = Left(sFolderList, Len(sFolderList) - 1)
End If
Return Split(sFolderList, "|")
End Function
Public Function DeleteLogFilesRecursive(ByVal sLogPath As String, ByVal iDelAge As Integer) As String
Dim sReturn As String = ""
If Directory.Exists(sLogPath)
Dim dInfo As New DirectoryInfo(sLogPath)
Dim fInfo as FileSystemInfo
Dim sTempString As String = ""
For Each fInfo In dInfo.GetFileSystemInfos()
If fInfo.Attributes = FileAttributes.Directory Then
sReturn = sReturn & DeleteLogFilesRecursive(fInfo.FullName, iDelAge)
Else
If (InStr(fInfo.FullName, "ex") > 0) And (Right(fInfo.FullName, 4) = ".log") Then
If DateDiff("d", fInfo.LastWriteTime, Now) > iDelAge Then
Try
sTempString = fInfo.FullName & " deleted." & VbCrLf
If LCase(ConfigurationManager.AppSettings("SimulationMode")) = "false" Then
File.Delete(fInfo.FullName)
sReturn = sReturn & sTempString
Else
sReturn = sReturn & "[Simulation mode enabled] " & sTempString
End If
Catch e As Exception
sReturn = sReturn & fInfo.FullName & " could not be deleted. Error message: " & e.Message & VbCrLf
End Try
End If
End If
End If
Next
End If
Return sReturn
End Function
End Class
<System.ComponentModel.RunInstaller(True)> _
Public Class ProjectInstaller
Inherits System.Configuration.Install.Installer
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer
Private Sub InitializeComponent()
Me.ServiceProcessInstaller1 = New ServiceProcessInstaller
Me.ServiceInstaller1 = New ServiceInstaller
Me.ServiceProcessInstaller1.Account = ServiceAccount.LocalSystem
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
Me.ServiceInstaller1.ServiceName = "IisLogHousekeeper"
Me.ServiceInstaller1.StartType = ServiceStartMode.Automatic
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
Friend WithEvents ServiceProcessInstaller1 As ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As ServiceInstaller
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class IisLogHousekeeper
Inherits System.ServiceProcess.ServiceBase
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
ServicesToRun = New System.ServiceProcess.ServiceBase() {New IisLogHousekeeper}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.ServiceName = "IisLogHousekeeper"
End Sub
End Class
IisLogHousekeeper.vb (for IIS 7.x and 8.x):
Imports System
Imports System.DirectoryServices
Imports System.Text
Imports System.IO
Imports System.Configuration
Imports System.Threading
Imports System.ServiceProcess
Imports System.Diagnostics
Imports System.Reflection
Imports Microsoft.Web.Administration
<Assembly: AssemblyTitle("IisLogHousekeeper 1.1 for IIS 7.x / 8.x")>
<Assembly: AssemblyDescription("IIS log housekeeping service (IIS 7/8 edition)")>
<Assembly: AssemblyCompany("www.700c.dk")>
<Assembly: AssemblyProduct("IisLogHousekeeper")>
<Assembly: AssemblyCopyright("Creative Commons Attribution (CC BY 3.0) https://creativecommons.org/licenses/by/3.0/ Reference source https://www.700c.dk/?code-iis-log-housekeeper-service")>
<Assembly: AssemblyVersion("1.1.0.0")>
<Assembly: CLSCompliant(True)>
Public Class IisLogHousekeeper
Private Shared ServiceThread As Thread
Private Shared KeepRunning As Boolean = True
Protected Overrides Sub OnStart(ByVal args() As String)
WriteToEventLog("IisLogHousekeeper starting", 1110)
ServiceThread = New Thread(AddressOf RunWorkerThread)
ServiceThread.Start()
End Sub
Protected Overrides Sub OnStop()
KeepRunning = False
WriteToEventLog( _
"IisLogHousekeeper stopping. Please note: the worker process " & _
"will live on for up to 60 seconds before it terminates.", 1110)
End Sub
Public Sub RunWorkerThread()
Dim aFolders() As String = {}
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "true" Then
aFolders = Split(ConfigurationManager.AppSettings("ManualLogLocations"), "|")
End If
Dim sRunResult As String = ""
Do While KeepRunning
If ConfigurationManager.AppSettings("RunAt") = Date.Now.ToString("HH:mm") Then
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "false" Then
Try
aFolders = GetIisLogFolders()
Catch e As Exception
WriteToEventLog("Could not get IIS log locations through the IIS API. Error message: " & e.Message, 1112)
End Try
End If
Try
For i As Integer = 0 to UBound(aFolders)
sRunResult = sRunResult & _
DeleteLogFilesRecursive(aFolders(i), CInt(ConfigurationManager.AppSettings("LogRetentionDays")))
Next
If sRunResult <> "" Then
WriteToEventLog(sRunResult, 1111)
sRunResult = ""
End If
Catch e As Exception
WriteToEventLog("An error occurred while cleaning up logs: " & e.Message, 1112)
End Try
End If
Thread.Sleep(60000)
Loop
End Sub
Public Function WriteToEventLog(ByVal Entry As String, _
Optional ByVal EventID As Integer = 0, _
Optional ByVal AppName As String = "IisLogHousekeeper", _
Optional ByVal EventType As _
EventLogEntryType = EventLogEntryType.Information, _
Optional ByVal LogName As String = "Application") As Boolean
Dim objEventLog As New EventLog()
Try
If Not Diagnostics.EventLog.SourceExists(AppName) Then
Diagnostics.EventLog.CreateEventSource(AppName, LogName)
End If
objEventLog.Source = AppName
objEventLog.WriteEntry(Entry, EventType, EventID)
Return True
Catch Ex As Exception
Return False
End Try
objEventLog.Dispose()
End Function
Public Function GetIisLogFolders() As String()
Dim sFolderList As String = ""
Dim mgr As New ServerManager()
For Each oWebsite As Site In mgr.Sites
sFolderList = sFolderList & oWebsite.LogFile.Directory & "\W3SVC" & oWebsite.Id.ToString() & "|"
Next
If Right(sFolderList, 1) = "|" Then
sFolderList = Left(sFolderList, Len(sFolderList) - 1)
End If
' Yes, the following replacement is an ugly hack. The later file handling functions don't like the environment variable format the IIS API returns:
sFolderList = Replace(sFolderList, "%SystemDrive%", "C:")
Return Split(sFolderList, "|")
End Function
Public Function DeleteLogFilesRecursive(ByVal sLogPath As String, ByVal iDelAge As Integer) As String
Dim sReturn As String = ""
If Directory.Exists(sLogPath)
Dim dInfo As New DirectoryInfo(sLogPath)
Dim fInfo as FileSystemInfo
Dim sTempString As String = ""
For Each fInfo In dInfo.GetFileSystemInfos()
If fInfo.Attributes = FileAttributes.Directory Then
sReturn = sReturn & DeleteLogFilesRecursive(fInfo.FullName, iDelAge)
Else
If (InStr(fInfo.FullName, "ex") > 0) And (Right(fInfo.FullName, 4) = ".log") Then
If DateDiff("d", fInfo.LastWriteTime, Now) > iDelAge Then
Try
sTempString = fInfo.FullName & " deleted." & VbCrLf
If LCase(ConfigurationManager.AppSettings("SimulationMode")) = "false" Then
File.Delete(fInfo.FullName)
sReturn = sReturn & sTempString
Else
sReturn = sReturn & "[Simulation mode enabled] " & sTempString
End If
Catch e As Exception
sReturn = sReturn & fInfo.FullName & " could not be deleted. Error message: " & e.Message & VbCrLf
End Try
End If
End If
End If
Next
End If
Return sReturn
End Function
End Class
<System.ComponentModel.RunInstaller(True)> _
Public Class ProjectInstaller
Inherits System.Configuration.Install.Installer
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer
Private Sub InitializeComponent()
Me.ServiceProcessInstaller1 = New ServiceProcessInstaller
Me.ServiceInstaller1 = New ServiceInstaller
Me.ServiceProcessInstaller1.Account = ServiceAccount.LocalSystem
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
Me.ServiceInstaller1.ServiceName = "IisLogHousekeeper"
Me.ServiceInstaller1.StartType = ServiceStartMode.Automatic
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
Friend WithEvents ServiceProcessInstaller1 As ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As ServiceInstaller
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class IisLogHousekeeper
Inherits System.ServiceProcess.ServiceBase
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
ServicesToRun = New System.ServiceProcess.ServiceBase() {New IisLogHousekeeper}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.ServiceName = "IisLogHousekeeper"
End Sub
End Class
Imports System.DirectoryServices
Imports System.Text
Imports System.IO
Imports System.Configuration
Imports System.Threading
Imports System.ServiceProcess
Imports System.Diagnostics
Imports System.Reflection
Imports Microsoft.Web.Administration
<Assembly: AssemblyTitle("IisLogHousekeeper 1.1 for IIS 7.x / 8.x")>
<Assembly: AssemblyDescription("IIS log housekeeping service (IIS 7/8 edition)")>
<Assembly: AssemblyCompany("www.700c.dk")>
<Assembly: AssemblyProduct("IisLogHousekeeper")>
<Assembly: AssemblyCopyright("Creative Commons Attribution (CC BY 3.0) https://creativecommons.org/licenses/by/3.0/ Reference source https://www.700c.dk/?code-iis-log-housekeeper-service")>
<Assembly: AssemblyVersion("1.1.0.0")>
<Assembly: CLSCompliant(True)>
Public Class IisLogHousekeeper
Private Shared ServiceThread As Thread
Private Shared KeepRunning As Boolean = True
Protected Overrides Sub OnStart(ByVal args() As String)
WriteToEventLog("IisLogHousekeeper starting", 1110)
ServiceThread = New Thread(AddressOf RunWorkerThread)
ServiceThread.Start()
End Sub
Protected Overrides Sub OnStop()
KeepRunning = False
WriteToEventLog( _
"IisLogHousekeeper stopping. Please note: the worker process " & _
"will live on for up to 60 seconds before it terminates.", 1110)
End Sub
Public Sub RunWorkerThread()
Dim aFolders() As String = {}
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "true" Then
aFolders = Split(ConfigurationManager.AppSettings("ManualLogLocations"), "|")
End If
Dim sRunResult As String = ""
Do While KeepRunning
If ConfigurationManager.AppSettings("RunAt") = Date.Now.ToString("HH:mm") Then
If LCase(ConfigurationManager.AppSettings("UseManualLogLocations")) = "false" Then
Try
aFolders = GetIisLogFolders()
Catch e As Exception
WriteToEventLog("Could not get IIS log locations through the IIS API. Error message: " & e.Message, 1112)
End Try
End If
Try
For i As Integer = 0 to UBound(aFolders)
sRunResult = sRunResult & _
DeleteLogFilesRecursive(aFolders(i), CInt(ConfigurationManager.AppSettings("LogRetentionDays")))
Next
If sRunResult <> "" Then
WriteToEventLog(sRunResult, 1111)
sRunResult = ""
End If
Catch e As Exception
WriteToEventLog("An error occurred while cleaning up logs: " & e.Message, 1112)
End Try
End If
Thread.Sleep(60000)
Loop
End Sub
Public Function WriteToEventLog(ByVal Entry As String, _
Optional ByVal EventID As Integer = 0, _
Optional ByVal AppName As String = "IisLogHousekeeper", _
Optional ByVal EventType As _
EventLogEntryType = EventLogEntryType.Information, _
Optional ByVal LogName As String = "Application") As Boolean
Dim objEventLog As New EventLog()
Try
If Not Diagnostics.EventLog.SourceExists(AppName) Then
Diagnostics.EventLog.CreateEventSource(AppName, LogName)
End If
objEventLog.Source = AppName
objEventLog.WriteEntry(Entry, EventType, EventID)
Return True
Catch Ex As Exception
Return False
End Try
objEventLog.Dispose()
End Function
Public Function GetIisLogFolders() As String()
Dim sFolderList As String = ""
Dim mgr As New ServerManager()
For Each oWebsite As Site In mgr.Sites
sFolderList = sFolderList & oWebsite.LogFile.Directory & "\W3SVC" & oWebsite.Id.ToString() & "|"
Next
If Right(sFolderList, 1) = "|" Then
sFolderList = Left(sFolderList, Len(sFolderList) - 1)
End If
' Yes, the following replacement is an ugly hack. The later file handling functions don't like the environment variable format the IIS API returns:
sFolderList = Replace(sFolderList, "%SystemDrive%", "C:")
Return Split(sFolderList, "|")
End Function
Public Function DeleteLogFilesRecursive(ByVal sLogPath As String, ByVal iDelAge As Integer) As String
Dim sReturn As String = ""
If Directory.Exists(sLogPath)
Dim dInfo As New DirectoryInfo(sLogPath)
Dim fInfo as FileSystemInfo
Dim sTempString As String = ""
For Each fInfo In dInfo.GetFileSystemInfos()
If fInfo.Attributes = FileAttributes.Directory Then
sReturn = sReturn & DeleteLogFilesRecursive(fInfo.FullName, iDelAge)
Else
If (InStr(fInfo.FullName, "ex") > 0) And (Right(fInfo.FullName, 4) = ".log") Then
If DateDiff("d", fInfo.LastWriteTime, Now) > iDelAge Then
Try
sTempString = fInfo.FullName & " deleted." & VbCrLf
If LCase(ConfigurationManager.AppSettings("SimulationMode")) = "false" Then
File.Delete(fInfo.FullName)
sReturn = sReturn & sTempString
Else
sReturn = sReturn & "[Simulation mode enabled] " & sTempString
End If
Catch e As Exception
sReturn = sReturn & fInfo.FullName & " could not be deleted. Error message: " & e.Message & VbCrLf
End Try
End If
End If
End If
Next
End If
Return sReturn
End Function
End Class
<System.ComponentModel.RunInstaller(True)> _
Public Class ProjectInstaller
Inherits System.Configuration.Install.Installer
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer
Private Sub InitializeComponent()
Me.ServiceProcessInstaller1 = New ServiceProcessInstaller
Me.ServiceInstaller1 = New ServiceInstaller
Me.ServiceProcessInstaller1.Account = ServiceAccount.LocalSystem
Me.ServiceProcessInstaller1.Password = Nothing
Me.ServiceProcessInstaller1.Username = Nothing
Me.ServiceInstaller1.ServiceName = "IisLogHousekeeper"
Me.ServiceInstaller1.StartType = ServiceStartMode.Automatic
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
Friend WithEvents ServiceProcessInstaller1 As ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As ServiceInstaller
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class IisLogHousekeeper
Inherits System.ServiceProcess.ServiceBase
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Shared Sub Main()
Dim ServicesToRun() As System.ServiceProcess.ServiceBase
ServicesToRun = New System.ServiceProcess.ServiceBase() {New IisLogHousekeeper}
System.ServiceProcess.ServiceBase.Run(ServicesToRun)
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.ServiceName = "IisLogHousekeeper"
End Sub
End Class
Tags: software
Page last updated 2013-04-12 21:18. Some rights reserved (CC by 3.0)