OdeToCode IC Logo

The Pharmacist and .NET Performance

Friday, September 3, 2004 by scott
I listened to the .NET Rocks episode with Jeff Richter this week. At one point, Jeff made a comment about C# having an inherent performance benefit over VB.NET. About two beats after Jeff finishes the statement you hear Carl suck in air. I think he wanted to explode at this point but winced instead.

Carl is a fervent supporter of VB.NET and dispels all sorts of myths about the language. Carl told Jeff he didn’t agree, but didn't start a debate. Jeff commands a great deal of respect in the .NET community, as well he should, but I think the truth is somewhere in the middle.

I don’t think the C# code from a competent, professional programmer would show a noticeable difference when compared to the performance of the same implementation written by a competent pro in VB.NET. When it comes to the hobbyist who doesn’t know what “option strict” does, (and doesn’t care) however, this is where you see the spread.

About one year ago I met a pharmacist who wrote an application in ASP.NET. The application tracked drug-drug interactions for patient safety. It was a great implementation of the pharmacist’s domain knowledge. The application worked. Would I have shrink-wrapped the code and put up for sale? No. Was it scalable? No – but, the point is, this fellow was putting his expertise to work, and his expertise wasn’t in building a scalable web site.

If someone put this application through a stress test, they might conclude that the entire .NET platform isn’t scalable. Just like political sound bites – you sometimes have to put a piece back into context before making a judgment. Perhaps this perceived performance difference isn’t really because of the different compilers, but because there is a significant percentage of VB.NET developers who don’t change the default setting of option strict (off by default). Late binding is a drag.

I do think there will be a divergence in the future between C# and VB.NET if VB.NET continues to layer higher levels of abstraction on top of the base class library (like the My keyword in 2005). As long as you know the underlying framework, it still shouldn’t matter much in the time trails.

Source Control Pet Peeves

Wednesday, September 1, 2004 by scott
Here are a couple of my pet peeves in source control.

Let’s say the sales and marketing department has decided the company is about to build version 3.0 of an amazing product: FooBar. Sometime thereafter, someone checks in a file named FooBar3.cs into source control.

I see two problems here. First, source control software, also known as version control software, will manage versions all by itself. Instead of putting version numbers in the file name, leave version numbers to the tool. When it comes time to associate a file version with a specific product release, I use the tagging / labeling functionality of the tool, and avoid potentially confusing conversations like:

Is FooBar3.cs checked in to build FooBar 4.0?

Does FooBar 5.0 still have FooBar3.cs?

This reminds me of an RFC on machine naming conventions (which I can’t find now). It suggests not giving the computer a name like UP or DOWN, because technical support will get calls like:

Is DOWN up?

Is UP down?

The second problem is letting a product name into the source code. Product names belong to marketing and sales. Product names are subject to change with the phases of the moon. Today the product is “FooBar 3.0”, tomorrow the product is renamed “Fabio 2005”.

Code names - really cool code names - like “Death Star” and “Predator”, belong to engineering. No one can make you change a code name. Well, unless you are Apple. In 1993 somebody at Apple decided to use “Carl Sagan” as a code name. Sagan’s attorney sent a letter to Apple asking them to stop. Someone at Apple then decided to change the codename to BHA – short for ‘butt-head astronomer’. Sagan then filed suit for emotional distress.

My advice then is this: don’t use version numbers, product names, company names, or the names of humor-impaired scientists when naming your project artifacts. Still, you might want to check with your lawyer first.

When Authorization Is Not A Technical Problem

Wednesday, September 1, 2004 by scott
Designing an authentication and authorization scheme for a non-trivial web application is, in most cases, non-trivial. You need to minimize risks and always err on a safe side, while giving customers usable software. .NET provides useful mechanisms to implement a security design, including impersonation, delegation, role-based authorization, and a choice of authentication options. The technical part is sometimes the easy part.

Designing an authentication and authorization scheme for software in the healthcare market means sitting down with people and understanding their interpretations about the sticky pit of legal and regulatory goo they live in. Everyone has a different opinion about the U.S. Health Insurance Portability and Accountability Act of 1996 (HIPPA). One of the objectives of HIPPA was to guarantee the security and privacy of health information. The effectiveness of HIPPA on the privacy of a health record is debatable, but is has certainly been a boon to consultants and companies offering to bring a healthcare organization into compliance. Some places want software to audit every user move, others just want to disable USB ports so nobody walks out of the place with patient records on a jump drive.

I’m all for privacy, but I do find it frustrating from a professional angle when trying to sort out what people want and what the ‘right thing’ is. It’s also sadly amusing to watch to what happens when legislation and regulatory agencies collide.

For example, the Occupational Safety and Health Administration (OSHA) requires employers to keep a list of injury and illness reports with employee names, and to make the list available to employers, former employers, and employee representatives (like the AFL-CIO, a labor organization covering many industries). HIPPA leans towards hiding names, OSHA wants names on the logs. So what do you do? One solution is to ask for a clarification from the Director of the Directorate of Evaluation and Analysis at OSHA (via hippablog). Titles like these make me wonder who the libertarian candidate is this year…

CreateProcessWithLogonW

Wednesday, September 1, 2004 by scott
Don Kiely recently pointed to an article on CodeProject with C# code to run a process in a new security context. The code PInvokes CreateProcessWithLogonW, but doesn’t work under ASP.NET.

CreateProcessWithLogonW is one of those tricky APIs that doesn’t pick up and move well from one environment to the next. Unfortunately, there is no way with .NET 1.1 to start a new process under alternate credentials without PInvoke. A spawned process always inherits the token of the creator process, so even if a thread is impersonating when it calls Process.Start, the new process always has the same identity of the current process. The good news is that Microsoft makes it easy in .NET 2.0.

Always approach launching a process on the server with caution. Launching an interactive process or a process under different credentials from a service should usually be avoided. In addition to overcoming all the privilege checks, you also have to deal with windowstations and desktops – not an issue in WinForms programming.

One little note about the code: the call to CreateProcessWithLogonW will fill the ProcessInformation structure with two IntPtr members representing Windows HANDLE types - these should be properly cleaned up with CloseHandle.

The Dreaded “Aspnet_wp.exe Could Not Be Started” Error

Friday, August 27, 2004 by scott

This morning started on a bad foot. We officially designated one of our dev machines as “pooched”.

Inside the application log was the dreaded ‘Aspnet_wp.exe Could Not Be Started’ message. I cringe at the sight of this message because it could be the result of any number of security or permission related mis-configurations. One way to start troubleshooting the problem is by enabling auditing and getting some tools from sysinternals.com. See my post Security Whodunit and read Anil’s comment.

Going through all the KB articles (linked below) and trouble-shooting steps did not solve the problem. After four hours, the computer was one runtime error away from being placed into a charcoal picnic grill outside the building and set on fire. That’s when we realized a second machine was complaining about certificate errors and not being able to connect to SQL Server.

Both of these machines had something in common. Some of our client’s have moved to using VPN solutions over SSL, and both machines were setup to use this. The advantages to this type of VPN are the ability to tunnel over port 443 from just about anywhere, and (in theory) there is no need for client software deployment. In fact, everywhere I look the VPN over SSL vendors insist there is no need to deploy software on the client and make messy configuration changes. This white paper even claims the technology gives you “clientless access”. Isn't that an oxymoron?

You typically start a VPN over SSL session by browsing to a secure website outside the destination’s firewall and entering some credentials. The browser then asks if you want to install some signed ActiveX software onto your machine. I’m guessing since this is “clientless access” it doesn’t count as a software deployment. Nevertheless, after going into Add / Remove programs and instructing the software to uninstall from the clientless machine, ASP.NET worked perfectly again – even though the uninstall barfs on an access violation just before it completes.

The VPN software we were using was from Juniper networks. According to the signature, Neoteris wrote the ActiveX control. Neoteris, by the way, was bought by NetScreen, which in turn was bought by Juniper. You know when you are running an installation program and see signs of three different companies it’s going to be trouble. If this is a low cost deployment, then I want the Cisco IPSEC client back. Oh, I forgot, it's not really a deployment - it's clientless.

There are many other reasons you might see this error. It could be that the account for the ASP.NET worker process is disabled, missing, locked out, or you have the wrong password setup in machine.config. You might be trying to run ASP.NET on a domain controller. Alternatively, the ASP.NET process account might not have the permissions to access files that it needs, and woe to anyone who names their machine “SYSTEM”. These scenarios and fixes are described in the following KB articles.

FIX: ASP.NET Does Not Work with the Default ASPNET Account on a Domain Controller

PRB: "Aspnet_wp.exe Could Not Be Started" Error Message When You View an ASP.NET Page

You receive a "W3wp.exe could not be started" error message in the application event log when you view an ASP.NET page

FIX: Cannot Browse to ASP.NET Pages If Computer Name Contains Certain Words

A Friend In Need

Wednesday, August 25, 2004 by scott
Multiple choice question:

A friend in need is a ____.

A) Friend with a non-booting laptop.

B) Friend with a non-booting desktop.

C) A friend indeed.

D) All of the above.

I’m sitting here with not one, but two pieces of hardware from two different people I know. Everyone in this field is familiar with playing tech support occasionally, it’s my turn now and they've come in bunches.

At least I’m getting a few good meals for my efforts. I’ve already had a down payment made in the form of a sausage, shrimp, and red pepper jambalaya. It’s a shame I can’t help this person out much, it appears the hard drive has destroyed more files than an Enron paper shredder.

The problem I’m really having is with a Toshiba Satellite notebook. I did manage to get this machine running. The screen is large and crisp and clear. It’s fast. It’s sleek. It makes my aging Thinkpad look so bad.

I keep finding myself on the Dell homepage clicking “Customize It”. I almost get to the checkout when I think: “No, what I really want is a Tablet PC”, and I’m off browsing for a Tablet. Then I wonder if I will really make good use of the Tablet. How often will I use the Pen? What if I need to do some extended development work on the machine? It’s just so cool, but is it worth it?

Now I can find no middle ground. It either has to be the super-portable, battery friendly Tablet PC, or the desktop replacement monster laptop that will give my legs third degree burns if I use it on the couch.

Pen versus Pentium 4

Sexy versus Sledgehammer

Space versus Time

This is the last time I fix a computer for someone who has nicer hardware than I do.

A DBA's Dream - SQL 2005 DDL Triggers

Monday, August 23, 2004 by scott
I’ve never put a trigger into production. I’m not saying this is good or bad, it just hasn’t happened …. yet.

With all these new features in SQL 2005 it’s easy to overlook the new capability to use DDL triggers. I think they will become a DBA’s friend long before CREATE ASSEMBLY and stored procedures in managed code ever will.

DDL triggers fire when data definition language events happen. For instance, you can block DROP TABLE and ALTER TABLE statements in a database with the following trigger.

CREATE TRIGGER AuditTableDDL
ON DATABASE 
FOR DROP_TABLE, ALTER_TABLE 
AS 
   PRINT 'No DROP or ALTER for you!' 
   PRINT CONVERT (nvarchar (1000), EVENTDATA())
   ROLLBACK;

In SQL 2000, the only way to prevent an accidental table drop was by using CREATE VIEW to touch a table and add the WITH SCHEMABINDING clause. DDL triggers are more explicit about this, and give you auditing capability easily with EVENTDATA().

The EVENTDATA() function is what really makes DDL interesting. If you need to audit DDL activity, the XML return value will contain all of the pertinent information for you. For example, if I have table Foo, and try DROP TABLE Foo with the previous trigger in place, I’ll get the following response (with some formatting applied):

No DROP or ALTER for you!
 
<EVENT_INSTANCE>
  <EventType>DROP_TABLE</EventType>
  <PostTime>2004-08-22T22:54:37.377</PostTime>
  <SPID>55</SPID>
  <ServerName>SQL2005B2</ServerName>
  <LoginName>SQL2005B2\bitmask</LoginName>
  <UserName>SQL2005B2\bitmask</UserName>
  <DatabaseName>AdventureWorks</DatabaseName>
  <SchemaName>dbo</SchemaName>
  <ObjectName>Foo</ObjectName>
  <ObjectType>TABLE</ObjectType>
  <TSQLCommand>
    <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" 
                ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON"
                ENCRYPTED="FALSE"
    />
    <CommandText>DROP TABLE Foo</CommandText>
  </TSQLCommand>
</EVENT_INSTANCE>
 
Msg 3609, Level 16, State 2, Line 1
Transaction ended in trigger. Batch has been aborted.

SQL 2005 also has predefined event groups to make writing DDL triggers easier. In the following trigger, DDL_TABLE_EVENTS will catch CREATE TABLE, DROP TABLE, and ALTER TABLE:

CREATE TRIGGER AuditTableDDL
ON DATABASE 
FOR DDL_TABLE_EVENTS
AS   
   PRINT CONVERT (nvarchar (1000), EVENTDATA())
   ROLLBACK;

Likewise DDL_INDEX_EVENTS will fire on CREATE, ALTER, or DROP INDEX. These groups roll up into larger groups. DDL_TABLE_VIEW_EVENTS will fire on all table, view, index, or statistics DDL.

The above triggers operate at database scope, and only react to events in the current database. You can also apply triggers at a server scope to fire on CREATE, DROP, ALTER LOGIN, for instance.

And of course you could write the trigger in C# or VB.NET, but let’s not get ahead of ourselves just yet…