My .NET web service – which wraps some legacy COM objects – wasn’t working. Development under VS2003 using .NET 1.1 worked fine in my dev environment, but in test env it just kept whinging:
InvalidCastException: QueryInterface for interface xxx.yyy failed
That’s a pretty basic failure – it couldn’t even obtain a xxx.yyy interface from the COM object. I figured it was a IIS security problem: a .NET desktop app using the same set of COM libraries worked fine.
The thing was, when I set the user account to operate annoymous web users under to local Administrator, it still didn’t help. Perhaps, I thought, this isn’t a permissions problem. Web users are now, after all, Gods.
Perhaps, Glen suggested, I was running .NET 2.0 and .NET 1.1 simultaneously?
No.
It turns out missing part was the
<identity impersonate="true" />
line out of the web.config file in the directory in which my webservice lived. Also, the lack of a web.config file in the directory in which my webservice lived caused a little bit of a problem. I didn’t realise that at the time, but found out that the impersonate setting can also go in one’s machine.config file also – but that has global implications. So I stepped back to putting it in my web service’s own web.config file.
Why does the Web Setup Project fail to include important little files, like my .asmx and web.config files? What is the point in having a wizard that just makes a installer that doesn’t install a working system? And the dependancies tree! God, just let me specify – or figure it out for yourself – the order in which to register the COM objects.
But guess what? All of that is unnecessary, if only your Installer derieved MyEventLogInstaller is set up thusly:
[RunInstallerAttribute(true)]
public class MyEventLogInstaller : Installer
{
private EventLogInstaller myEventLogInstaller;
public MyEventLogInstaller()
{
//Create Instance of EventLogInstaller
myEventLogInstaller = new EventLogInstaller();
// Set the Source of Event Log, to be created.
myEventLogInstaller.Source = "Josh's Web Service";
// Set the Log that source is created in
myEventLogInstaller.Log = "Application";
// Add myEventLogInstaller to the Installers Collection.
Installers.Add(myEventLogInstaller);
}
}
– with the RunInstallerAttribute being the super important part. Or perhaps it should read RunInstaller. But don’t worry, neither of them actually cause the installer to run them. As such, all you need do is issue the command
installutil "MyStupidWebService.dll"
after the installation program is done and you’ll be cooking with gas.
Simple, huh? No need for that nasty web.config file after all! Especially with it impersonating a dud security context.
Oh! And remember to issue a regsvr32 comcomponent.dll command also!
A dead giveaway that you haven’t run installutil is if you get an exception like this:
System.TypeInitializationException: The type initializer for "MyStupidWebService.Global" threw an exception. --->
System.InvalidOperationException: Cannot open log for source {0}. You may not have write access. --->
System.ComponentModel.Win32Exception: Access is denied
--- End of inner exception stack trace ---
at System.Diagnostics.EventLog.OpenForWrite()
at System.Diagnostics.EventLog.WriteEvent(Int32 eventID, Int16 category, EventLogEntryType type, String[] strings, Byte[] rawData)
at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category, Byte[] rawData)
at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID, Int16 category)
at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type, Int32 eventID)
at System.Diagnostics.EventLog.WriteEntry(String message, EventLogEntryType type)
because installutil will create an entry for Event Logging, if you’ve developed the appropriate installer. And because the person running installutil has decent privileges, it will actually work, as opposed to your web service trying to do it when it’s running in a securely locked down account.