Monday, April 4, 2011

Rename all Unique Constraints in a SQL Server database

Quick and dirty script:

DECLARE @old sysname, @current sysname, @TABLE sysname, @COLUMN sysname,
    @this_old sysname
    SELECT AllUQs.name AS old_name, object_name(AllUQs.parent_obj) AS table_name,
            col.name AS column_name
        FROM dbo.sysobjects AS AllUQs
        JOIN dbo.sysindexes AS ix ON (ix.id = AllUQs.parent_obj)
                               AND (ix.name = AllUQs.name)
        JOIN dbo.sysindexkeys AS [KEY] ON ([KEY].id = ix.id) AND ([KEY].indid = ix.indid)
        JOIN dbo.syscolumns AS col ON (col.id = ix.id) AND (col.colid = [KEY].colid)
        WHERE AllUQs.xtype = 'UQ'
        ORDER BY old_name
OPEN uq_cursor
    FETCH NEXT FROM uq_cursor INTO @old, @TABLE, @COLUMN
    SET @current = 'UQ_' + @TABLE
    SET @this_old = @old
        IF (@this_old != @old)
            print @this_old + ' - ' + @current
            -- EXEC sp_rename @this_old, @current, 'OBJECT'
            SET @current = 'UQ_' + @TABLE + '_' + @COLUMN
            SET @this_old = @old
            SET @current = @current + '__' + @COLUMN
        FETCH NEXT FROM uq_cursor INTO @old, @TABLE, @COLUMN
    print @this_old + ' - ' + @current
    -- EXEC sp_rename @this_old, @current, 'OBJECT'
CLOSE uq_cursor
DEALLOCATE uq_cursor

This will rename all unique constraints to UQ_TableName_Column1Name_Column2Name (for a unique constraint on two columns.)

Hope this helps someone save themselves 15mins of SQL…

posted by Nick at 7:47 pm - filed in sql  

Saturday, October 2, 2010

Gendarme MSBuild task

I just wrote a quick MSBuild wrapper around the great Gendarme tool. It allows running Gendarme as part of an MSBuild task/project, and supports all the options that the command-line runner supports.

It also integrates with Visual Studio:

Visual Studio screenshot

The binary can be downloaded here: http://github.com/unintelligible/GendarmeMsBuild/downloads

The source code is available here: http://github.com/unintelligible/GendarmeMsBuild

posted by Nick at 1:14 am - filed in .net  

Monday, May 24, 2010

Resharper 4.5 inspection severity list

For some reason, I couldn’t find a list of the different Resharper code inspections and their severity anywhere on the web (not even in Jetbrains’ site); this is useful to go through the available inspections with team members to decide which we should enable across our team.

So, for convenience, I’m posting one here; this is for Resharper 4.5. Click to expand the table.

Settings entry name Section Definition Default severity
ClassCanBeSealed.Global Code Redundancies Class can be made sealed - Non-private accessibility DO_NOT_SHOW
ClassCanBeSealed.Local Code Redundancies Class can be made sealed - Private accessibility DO_NOT_SHOW
MemberCanBeInternal Code Redundancies Member or type can be made internal DO_NOT_SHOW
ConvertIfStatementToReturnStatement Code Redundancies ‘if-return’ statement can be re-written as ‘return’ statement HINT
ConvertIfStatementToSwitchStatement Code Redundancies Convert ‘if’ statement to ’switch’ statement HINT
ConvertToAutoPropertyWithPrivateSetter Code Redundancies Convert property to auto-property with private setter HINT
InvertIf Code Redundancies Invert ‘if’ statement to reduce nesting HINT
SimilarAnonymousTypeNearby Code Redundancies Similar anonymous type detected nearby HINT
SuggestUseVarKeywordEverywhere Code Redundancies Use ‘var’ keyword when possible HINT
ClassNeverInstantiated.Global Code Redundancies Class is never instantiated - Non-private accessibility SUGGESTION
ClassNeverInstantiated.Local Code Redundancies Class is never instantiated - Private accessibility SUGGESTION
ClassWithVirtualMembersNeverInherited.Global Code Redundancies Class with virtual members never inherited - Non-private accessibility SUGGESTION
ClassWithVirtualMembersNeverInherited.Local Code Redundancies Class with virtual members never inherited - Private accessibility SUGGESTION
ConverClosureToMethodGroup Code Redundancies Convert anonymous method to method group SUGGESTION
ConvertConditionalTernaryToNullCoalescing Code Redundancies ‘?:’ expression can be re-written as ‘??’ expression SUGGESTION
ConvertIfStatementToConditionalTernaryExpression Code Redundancies ‘if’ statement can be re-written as ‘?:’ expression SUGGESTION
ConvertIfStatementToNullCoalescingExpression Code Redundancies ‘if’ statement can be re-written as ‘??’ expression SUGGESTION
ConvertNullableToShortForm Code Redundancies Convert ‘Nullable‘ to ‘T?’ SUGGESTION
ConvertToAutoProperty Code Redundancies Convert property to auto-property SUGGESTION
ConvertToConstant.Global Code Redundancies Convert local variable or field to constant - Non-private accessibility SUGGESTION
ConvertToConstant.Local Code Redundancies Convert local variable or field to constant - Private accessibility SUGGESTION
ConvertToLambdaExpression Code Redundancies Convert to lambda expression SUGGESTION
ConvertToStaticClass Code Redundancies Convert to static class SUGGESTION
EventNeverInvoked.Global Potential Errors & Bad Practices Abstract or virtual event is never invoked SUGGESTION
EventNeverSubscribedTo.Global Code Redundancies Event is never subscribed to - Non-private accessibility SUGGESTION
EventNeverSubscribedTo.Local Code Redundancies Event is never subscribed to - Private accessibility SUGGESTION
FieldCanBeMadeReadOnly.Global Code Redundancies Field can be made readonly - Non-private accessibility SUGGESTION
FieldCanBeMadeReadOnly.Local Code Redundancies Field can be made readonly - Private accessibility SUGGESTION
InvokeAsExtensionMethod Code Redundancies Convert static method invocation to extension method call SUGGESTION
JoinDeclarationAndInitializer Code Redundancies Join local variable declaration and assignment SUGGESTION
MemberCanBeMadeStatic.Global Code Redundancies Member can be made static - Non-private accessibility SUGGESTION
MemberCanBeMadeStatic.Local Code Redundancies Member can be made static - Private accessibility SUGGESTION
MemberCanBePrivate.Global Code Redundancies Member can be made private - Non-private accessibility SUGGESTION
MemberCanBePrivate.Local Code Redundancies Member can be made private - Private accessibility SUGGESTION
MemberCanBeProtected.Global Code Redundancies Member can be made protected - Non-private accessibility SUGGESTION
MemberCanBeProtected.Local Code Redundancies Member can be made protected - Private accessibility SUGGESTION
MoreSpecificForeachVariableTypeAvailable Code Redundancies Iteration variable can be declared with a more specific type SUGGESTION
PublicConstructorInAbstractClass Code Redundancies Make constructor in abstract class protected SUGGESTION
ReplaceWithStringIsNullOrEmpty Code Redundancies Use ‘String.IsNullOrEmpty’ SUGGESTION
SuggestBaseTypeForParameter Code Redundancies Parameter can be declared with base type SUGGESTION
SuggestUseVarKeywordEvident Code Redundancies Use ‘var’ keyword when initializer explicitly declares type SUGGESTION
SuspiciousTypeConversion.Global Potential Errors & Bad Practices Suspicious type conversion or check SUGGESTION
TooWideLocalVariableScope Code Redundancies Local variable has too wide declaration scope SUGGESTION
UnaccessedField.Global Code Redundancies Unaccessed field - Non-private accessibility SUGGESTION
UnassignedField.Global Potential Errors & Bad Practices Unassigned field SUGGESTION
UnusedMember.Global Code Redundancies Unused declaration - Non-private accessibility SUGGESTION
UnusedMethodReturnValue.Global Code Redundancies Method return value is never used - Non-private accessibility SUGGESTION
UnusedParameter.Global Code Redundancies Unused parameter - Non-private accessibility SUGGESTION
UseObjectOrCollectionInitializer Code Redundancies Use object or collection initializer when possible SUGGESTION
VirtualMemberNeverOverriden.Global Code Redundancies Virtual member is never overriden - Non-private accessibility SUGGESTION
VirtualMemberNeverOverriden.Local Code Redundancies Virtual member is never overriden - Private accessibility SUGGESTION
AccessToModifiedClosure Potential Errors & Bad Practices Access to modified closure WARNING
AccessToStaticMemberViaDerivedType Potential Errors & Bad Practices Access to a static member of a type via a derived type WARNING
AssignNullToNotNullAttribute Value Analysis Possible ‘null’ assignment to entity marked with ‘Value cannot be null’ attribute WARNING
BaseMemberHasParams Potential Errors & Bad Practices Base member has ‘params’ parameter, but overrider hasn’t WARNING
BitwiseOperatorOnEnumWihtoutFlags Potential Errors & Bad Practices Bitwise operation on enum which is not marked by [Flags] attribute WARNING
CannotApplyEqualityOperatorToType Potential Errors & Bad Practices Compare with ‘==’ types marked by ‘CannotApplyEqualityOperatorAttribute’ WARNING
CharImplicitlyConvertedToNumeric Potential Errors & Bad Practices Char is implicitly converted to integral numeric type WARNING
CompareNonConstrainedGenericWithNull Potential Errors & Bad Practices Possible compare of value type with ‘null’ WARNING
ConditionIsAlwaysTrueOrFalse Value Analysis Expression is always ‘true’ or always ‘false’ WARNING
ConstantNullColescingCondition Value Analysis ‘??’ condition is known to be null or not null WARNING
ConstructorInitializerLoop Potential Errors & Bad Practices Possible cyclic constructor call WARNING
DoNotCallOverridableMethodsInConstructor Potential Errors & Bad Practices Virtual member call in constructor WARNING
DoubleNegationOperator Code Redundancies Double negation operator WARNING
EmptyConstructor Code Redundancies Empty constructor WARNING
EmptyDestructor Code Redundancies Empty destructor WARNING
EmptyGeneralCatchClause Potential Errors & Bad Practices Empty general catch clause WARNING
EmptyNamespace Code Redundancies Empty namespace declaration WARNING
EnumUnderlyingTypeIsInt Code Redundancies Underlying type of enum is ‘int’ WARNING
FormatStringProblem Potential Errors & Bad Practices Problems in format string WARNING
ForStatementConditionIsTrue Code Redundancies ‘true’ is redundant as ‘for’-statement condition WARNING
FunctionNeverReturns Potential Errors & Bad Practices Function never returns WARNING
InconsistentNaming Potential Errors & Bad Practices Inconsistent Naming WARNING
LocalVariableHidesMember Potential Errors & Bad Practices Local variable hides member WARNING
ParameterHidesMember Potential Errors & Bad Practices Parameter hides member WARNING
PartialMethodWithSinglePart Code Redundancies Redundant ‘partial’ modifier on method declaration WARNING
PartialTypeWithSinglePart Code Redundancies Redundant ‘partial’ modifier on type declaration WARNING
PossibleIntendedRethrow Potential Errors & Bad Practices Exception rethrow possibly intended WARNING
PossibleInterfaceMemberAmbiguity Potential Errors & Bad Practices Possible ambiguity while accessing member by interface WARNING
PossibleLossOfFraction Potential Errors & Bad Practices Possible loss of fraction WARNING
PossibleNullReferenceException Value Analysis Possible ‘System.NullReferenceException’ WARNING
RedundantAnonymousTypePropertyName Code Redundancies Redundant anonymous type property explicit name WARNING
RedundantAssignment Code Redundancies Assignment is not used WARNING
RedundantAttributeParentheses Code Redundancies Parentheses are redundant if attribute has no arguments WARNING
RedundantBaseConstructorCall Code Redundancies Redundant base constructor call WARNING
RedundantBaseQualifier Code Redundancies Redundant ‘base.’ qualifier WARNING
RedundantBoolCompare Code Redundancies Redundant boolean comparison WARNING
RedundantCaseLabel Code Redundancies Redundant ‘case’ label WARNING
RedundantCast Code Redundancies Redundant cast WARNING
RedundantCatchClause Code Redundancies Redundant catch clause WARNING
RedundantCollectionInitializerElementBraces Code Redundancies Redundant braces in collection initializer WARNING
RedundantDefaultFieldInitializer Code Redundancies Redundant field initializer WARNING
RedundantDelegateCreation Code Redundancies Explicit delegate creation expression is redundant WARNING
RedundantEmptyFinallyBlock Code Redundancies Redundant empty finally block WARNING
RedundantEmptyObjectCreationArgumentList Code Redundancies Redundant empty argument list on object creation expression WARNING
RedundantEmptyObjectOrCollectionInitializer Code Redundancies Redundant empty object or collection initializer WARNING
RedundantExplicitArrayCreation Code Redundancies Redundant explicit type in array creation WARNING
RedundantExplicitArraySize Code Redundancies Redundant explicit size specification in array creation WARNING
RedundantExplicitNullableCreation Code Redundancies Redundant explicit nullable type creation WARNING
RedundantExtendsListEntry Code Redundancies Redundant class or interface specification in base types list WARNING
RedundantIfElseBlock Code Redundancies Redundant ‘else’ keyword WARNING
RedundantLambdaParameterType Code Redundancies Redundant lambda parameter explicit type specification WARNING
RedundantLambdaSignatureParentheses Code Redundancies Redundant lambda signature parentheses WARNING
RedundantNameQualifier Code Redundancies Redundant name qualifier WARNING
RedundantOverridenMember Code Redundancies Redundant member override WARNING
RedundantParams Code Redundancies ‘params’ modifier is always ignored on overrides WARNING
RedundantStringToCharArrayCall Code Redundancies Redundant ’string.ToCharArray()’ call WARNING
RedundantThisQualifier Code Redundancies Redundant ‘this.’ qualifier WARNING
RedundantToStringCall Code Redundancies Redundant ‘object.ToString()’ call WARNING
RedundantTypeArgumentsOfMethod Code Redundancies Redundant type arguments of method WARNING
RedundantUnsafeContext Code Redundancies Unsafe context declaration is redundant WARNING
RedundantUsingDirective Code Redundancies Redundant using directive WARNING
ReferenceEqualsWithValueType Potential Errors & Bad Practices ‘Object.ReferenceEquals’ is always false because it is called with value type WARNING
RequiredBaseTypesConflict Potential Errors & Bad Practices Required base type conflicting another type WARNING
RequiredBaseTypesDirectConflict Potential Errors & Bad Practices Type specified in BaseTypeRequired attribute conflicts another type WARNING
RequiredBaseTypesIsNotInherited Potential Errors & Bad Practices Base type is required WARNING
SealedMemberInSealedClass Code Redundancies Sealed member in sealed class WARNING
UnaccessedField.Local Code Redundancies Unaccessed field - Private accessibility WARNING
UnsupportedRequiredBaseType Potential Errors & Bad Practices BaseTypeRequired attribute supports only classes and interfaces WARNING
UnusedAnonymousMethodSignature Code Redundancies Anonymous method signature is not necessary WARNING
UnusedAutoPropertyAccessor.Global Potential Errors & Bad Practices Auto-implemented property accessor is never used - Non-private accessibility WARNING
UnusedAutoPropertyAccessor.Local Potential Errors & Bad Practices Auto-implemented property accessor is never used - Private accessibility WARNING
UnusedMember.Local Code Redundancies “”Unused declaration - Private accessibility WARNING
UnusedMethodReturnValue.Local Code Redundancies Method return value is never used - Private accessibility WARNING
UnusedParameter.Local Code Redundancies Unused parameter - Private accessibility WARNING
UnusedTypeParameter Code Redundancies Unused type parameter WARNING
ValueParameterNotUsed Potential Errors & Bad Practices ‘value’ parameter is not used WARNING

Apologies for the formatting; you can also download the CSV.

posted by Nick at 6:54 pm - filed in .net  

Tuesday, October 20, 2009

Named Reader Writer Lock in C#

A while ago, I found an article about implementing a named lock class in C#, allowing for the following code:

private static NamedLock<string> namedLock = new NamedLock</string><string>();
public void DoSomethingConcurrent(string lockName)
    using (namedLock.Lock(lockName))
       //Do something concurrent

This is useful because it allows the same code block to be run concurrently, with locking occurring depending on the arguments being passed in. The author thought it might be useful to have some reader-writer type functionality added in too though; since I had a similar requirement, I wrote a named reader-writer lock, based partly on the NamedLock posted above but using a ReaderWriterLockSlim as the underlying lock rather than a simple Monitor.

I’ve posted the code to Github, including a unit test suite. The most interesting file is the class itself. Usage is almost identical to the NamedLock:

private static NamedReaderWriterLock<string> namedRWLock = new NamedReaderWriterLock</string><string>();
public void DoSomethingConcurrent(string lockName)
    using (namedRWLock.LockRead(lockName))
       //Do something concurrent that only requires 
       //read access to the resource
    using (namedRWLock.LockUpgradeableRead(lockName))
       //Do something concurrent that only requires 
       //read access to the resource, but that may require
       //upgrading to a Write lock later in the code
    using (namedRWLock.LockWrite(lockName))
       //Do something concurrent that requires 
       //write access to the resource

Performance-wise, the reader-writer functionality does seem to improve concurrent access over the named lock; here’s the output of the performance tests running on my machine:

Run 1 - finished NamedRWLock run in 3734.2794ms
Run 1 - finished NamedLock run in 5499.8592ms
Run 1 - finished Monitor run in 5468.61ms
Run 2 - finished NamedRWLock run in 3609.2826ms
Run 2 - finished NamedLock run in 5468.61ms
Run 2 - finished Monitor run in 5468.61ms
Run 3 - finished NamedRWLock run in 3609.2826ms
Run 3 - finished NamedLock run in 5468.61ms
Run 3 - finished Monitor run in 5515.4838ms
3 passed, 0 failed, 0 skipped, took 47.92 seconds.
Run 1 - finished NamedRWLock run in 6656.0796ms
Run 1 - finished NamedLock run in 8843.5236ms
Run 1 - finished Monitor run in 8812.2744ms
Run 2 - finished NamedRWLock run in 6562.332ms
Run 2 - finished NamedLock run in 8812.2744ms
Run 2 - finished Monitor run in 8812.2744ms
Run 3 - finished NamedRWLock run in 6562.332ms
Run 3 - finished NamedLock run in 8812.2744ms
Run 3 - finished Monitor run in 8812.2744ms
3 passed, 0 failed, 0 skipped, took 76.59 seconds.

These tests compare the performance of the NamedReaderWriterLock with the NamedLock, using a standard Monitor as a control value. The first set of tests balances reads and writes, whereas the second performs four times more reads than writes (and likely reflects real-life scenarios more closely.)

The NamedReaderWriterLock provided around 35% improvement over the NamedLock in the test where as many writes as reads are performed, and a 25% improvement in the test skewed towards reads. This is a reasonably figure, although in the greater scheme of things it’s likely to be a only a minor improvement compared to the cost of, say, making a DB call; still, it’s worth having.

The code is available under the BSD license.

posted by Nick at 10:17 pm - filed in .net  

Tuesday, July 28, 2009

Installing Selenium-RC as a Windows service

Installing Selenium as a Windows service is reasonably straightforward - based on the instructions for Fitnesse, which unfortunately seem to have been deleted from the Fitnesse wiki, but which have been reproduced here.

There are two parts to doing this - the first, registering the service using srvany.exe (which wraps any executable as a service), and the second, adding the keys to the registry to tell srvany.exe how to launch Selenium-RC. srvany.exe is a part of the Windows Resource Kit, if you don’t have it already you will need to download it from Microsoft.

The following will register the Selenium service - on the command line (all in one line):

"C:\Program Files\Windows Resource Kits\Tools\instsrv.exe" SeleniumRC
"C:\Program Files\Windows Resource Kits\Tools\srvany.exe" -a [myuser] -p [mypass]

This is assuming the Windows Resource Kit has been installed to its default location, “C:\Program Files\Windows Resource Kits”. Also, note that the user supplied needs to have the Log On As Service permissions assigned.

Now, add the following keys to the registry - this text can simply be copied-and-pasted to a .reg file, then double-clicked to add the entries to the registry:

Windows Registry Editor Version 5.00
"AppDirectory"="C:\\Program Files\\selenium-server-1.0.1"
"AppParameters"="-Xrs -jar selenium-server.jar"

You should now be able to start the service - if you get an error about the service failing to start due to a logon issue, make sure that the user you are using to run the service has been granted Log On As A Service permission (editing the service logon credentials in the Services MMC snap-in and saving the changes will cause this to happen automatically.)

posted by Nick at 10:08 pm - filed in testing, windows  

Sunday, March 8, 2009

Rubyists and Photographers, slight return

A few months ago, I posted an entry on how Rubyists sometimes get distracted by the power of the language, preferring lengthy debates on programming aesthetics to actually writing (efficient) code. I compared this to photography, in which aspiring photographers sometimes get lost in technical discussions rather than focussing on the work they produce. Then I came across this quote, which concisely expresses in 3 sentences what I hadn’t managed in an entire post:

Every medium suffers from its own particular handicap. Photography’s greatest handicap is the ease with which the medium as such can be learned. As a result, too many budding neophytes learn to speak the language too long before they have anything to say.

(Will Connell, 1949, via Brendan MacRae, via Tim Bray)

The point of my original post was that the same may apply to Ruby; the language’s power and accessibility makes everything seem so easy, that it becomes tempting to engage in discussions about the finer points of programming aesthetics rather than focussing what one has to say (i.e. the problems one chooses to solve.)

posted by Nick at 1:15 pm - filed in ruby  

Sunday, March 8, 2009

Adding a Windows service using sc

The ‘sc‘ utility can be used to create, delete or edit a Windows service. It can be used for any executables (as opposed to installutil, which can only be used for .Net services). Its help is available using sc /help (and is also available on MSDN); however, I found the output slightly confusing, so for my own reference here’s an example for creating a service for the Subversion server:

sc create svnserve binPath= "\"C:\Program Files\CollabNet Subversion Server\svnserve.exe\" 
  --service -r \"c:\svn_repository\" --listen-port \"3690\"" DisplayName= "Subversion Server"

This passes two parameters, the binPath and the DisplayName (the rest are the directives Subversion expects when running as a service). The trick here is the space between the ‘=’ sign after the parameter name and the parameter value; the service won’t be installed otherwise.

posted by Nick at 12:53 pm - filed in windows  

Monday, February 2, 2009

Mona Lisa image evolution in Ruby (JRuby)

Like several other people, I was fascinated by Roger Alsing’s post shortly before Christmas describing his program to evolve an image look like Leonardo’s Mona Lisa, using only semi-transparent polygons. This uses genetic programming (or perhaps more accurately, simulated annealing, a Monte Carlo method) to evolve an image, comparing each evolved image to its parent and deciding whether it is closer to the target image; if it is closer to the target, the image is retained and then evolved further.

Since Roger released his source code, there have been several other implementations in different languages, such as Javascript and Clojure. I thought that converting the program to another language would be an excellent way to understand how it works; so, I converted it to Ruby (actually JRuby, as Swing is used for drawing the images and the user interface).

I’ve uploaded the code to GitHub; my implementation is pretty much a straight port of Roger Alsing’s original code though, and generally speaking it’s a little quick and dirty; I may eventually spend a little time tidying and/or optimising it, but as of yet it isn’t either elegant or fast.

This short clip shows the evolution of the selected candidates over 75000 generations (around four hours on my machine).

posted by Nick at 8:50 pm - filed in java, ruby  

Saturday, January 10, 2009

Touch typing update - one year after

It’s been a year now since I switched to the Dvorak keyboard layout and learned to touch-type, so it seemed like a good time to assess progress so far.

I now consistently type between 60 and 70 WPM, depending on the day and the text I need to type. I’m reasonably happy with this, but when I originally switched, I was hoping that I would get up to 80-90WPM within a year. Also, I can’t really touch-type numbers, and I usually need to look at the keyboard to type some of the non alpha-numerical numbers that get used often when developing (e.g. ‘[', ']‘, ‘$’, ‘^’ etc.). Finally, typing still hasn’t really become as automatic as I’d hoped it would; to achieve high speeds, I still need to concentrate on typing, whereas I was hoping that I would have interned the typing to an extent that I didn’t really need to think about it anymore.

So, I think I’m going to start practicing again (in fact, I already started a little over Xmas). I’m kind of hoping to have resolved all of the above by June this year, so that I can finally stop thinking about typing :-)

posted by Nick at 3:20 pm - filed in dvorak  

Monday, December 1, 2008

Event Log access permissions for ASP.NET application pools

When running an application pool in IIS under a different user than the default, for an application that requires write access to the Event Log (for example, when trying to create a new event source in your application), it is necessary to grant that user sufficient access to the event log in the registry. Otherwise, you would receive the following error:

System.Security.SecurityException: Requested registry access is not allowed.

However, using Windows 2003 Server, I found that granting ‘read’ access to the event log wasn’t enough; the full set of permissions I ended up need to grant to the app pool user on the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog key in the registry is as follows:

Permissions for event log access in IIS

I hope that this helps someone.

posted by Nick at 7:43 pm - filed in windows  
Next Page