Since working with EnterpriseServices (ES), I have found some of the nicer features that are available through COM+ 1.5 (on Windows XP and Windows Server 2003 ONLY). A couple of noteworthy options:
1. COM+ Services without Components. I can implement select features of COM+ (such as transactions) without all the overhead of invoking a full-blown .Net class derived from ServicedComponent. I am still determining how useful and viable this is in a large distributed environment.
2. IsPrivateComponent. A property (attribute) that allows me to mark a component as private (within a Server application). This private component is only callable within the Server application. Previously, in COM+ 1.0 (Windows 2000), all components had to be public to have access to COM+ services, which meant that these components could be activated from other applications.
Some other COM+ 1.5 specific features are noted in the .NET Enterprise Services and COM+ 1.5 Architecture article.
Over Christmas break, I spent a lot of time experimenting with EnterpriseServices (ES)/COM+, in particular with Distributed Transactions. Within our team, there were some questions that came up last week regarding ES:
1. Tim Ewald, in his excellent COM+ book, describes the ideas of “configured” components and “nonconfigured” components. It would seem that a configured component (installed in the COM+ catalog) can call a non-configured component and can (possibly??) enlist the nonconfigured component within a COM+ transaction. How does this work with ES? Answer: In testing with ES, you don't necessarily need to have a class implementing the ServicedComponent interface, but you do need to reference the System.EnterpriseServices namespace in order for the Context, Activity, and Transaction to flow to the “nonconfigured” .Net component. Noting Tim Ewald's follow-up article, I did find this:
It is interesting to note that CLR objects behave exactly the opposite of how COM objects behave with respect to COM+ context. With COM, calls to an object are always intercepted by default; all objects are context-bound. A COM object can only be context-agile if it aggregates the freethreaded marshaler (FTM) and is not the first object created in a new COM+ context (that is, it is not the distinguished object), in which case, calls to it will not be intercepted. The benefit of this new approach is that it reduces interception overhead by ensuring that calls will be pre- and post-processed only when absolutely necessary. Specifically, if an instance of a configured class returns a reference to an instance of a nonconfigured class (an ADO. NET DataSet object, for example), calls to that object will not be intercepted. And the DataSet object doesn't have to do anything special, it just works this way.
What I saw was that when I referenced System.EnterpriseServices in the assembly metadata, then I could “reach up“ and grab the ContextId, ActivityId, and TransactionId within a class method that was not deriving ServicedComponent. Was that method in a transaction at that point or not?
2. Is it possible that a method could opt in or out of a distributed transaction? Answer: Yes. Distributed transaction enlistment can be automatic depending on the root of the transaction (with declaritive transaction support). But, within the connection string, the option “Enlist=false” can make sure enlistment doesn't happen. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconenlistingindistributedtransaction.asp for more interesting details.
These are just a couple of items. I plan on writing more regarding some of the gotchas we have found plus problems we are still puzzling through.
Am I alone in thinking that there NEEDS to be a "Effective C#" and "Effective VB.NET", maybe just a "Effective .NET" series?
As far as I can tell, among the MSDN Patterns and Practices books and articles, DevelopMentor .Net books, the Addison-Wesley .Net series books, and many other excellent .Net resources, there are some very noteworthy tidbits of .Net advice. But, no one has yet put together a concise "Effective-style" book for .Net like Scott Meyers did for C++ and STL.
I, for one, have been keeping a collection of notes on the various bits of information I find in these resources. I keep it in a standard notebook of notes, noting where I found the reference, when I found it, and if something else I have read or found through experimenting has now nullified that information. It would be nice, though, to have a concise collection of this information in book form.
Sam points to NAnt 0.84 Final being released. Along with that, I found that the latest NAntContrib Project has been released as well. For tips on getting started with NAnt, check out a previous post where I describe my own experiences with the pre-release of NAnt 0.84.
Update: One follow-up to that post is that I found you do have point to explicit drive/file locations for GAC'd assemblies -- NAnt (really, its csc.exe that NAnt is using, so this applies to the limitations of csc instead of NAnt) is unable to reference assemblies stored in the GAC directly (unless they are also stored, as some System assemblies are, in the \WINDOWS\Microsoft.NET\Framework\v1.0.3705 area).
If you have previously been a C++ wonk, you probably know Scott Meyers as a household name. He wrote excellent books on Effective C++ and Effective STL in the 90s, and his writing style has influenced others, including Don Box who wrote Effective COM. Now, Scott has written a great article on his own experiences in writing and getting books published titled Advice to Prospective Book Authors. Even if you are an armchair book author (“one day, someday, I will write a book!”), you owe yourself a read.
Last night, I had the opportunity to speak to the New Hampshire .Net Users Group about .Net Security, in particular speaking about User (Role-Based) Security and Code Access Security. My emphasis was on how .Net addresses these important issues in security:
Authentication: Who are you?
Authorization: What are you permitted to do?
While doing some research for this presentation, I found this nice little book from the Microsoft Patterns and Practices Group called Designing Application-Managed Authorization (you can download the PDF here). This book details some of the ideas I spoke about last night regarding use of the Principal and Identity objects to validate a user (Authentication above) as well as various methods to enforce what that user is able to do (Authorization above).
6:00PM Thursday, December 18th, 2003
Wang Auditorium - Boston University Corporate Education Center
Featured Guest: Robert Hurlbut
Topic: .NET Security Best Practices
MSDN: Code Access Security in Practice
MSDN: Code Access Security...Enhance Client-Side Apps
MSDN: Security in .NET: Enforce Code Access Rights with the CLR
MSDN: Unify the Role-Based Security...with .NET
I will be speaking to the New Hampshire .Net Users Group, Tyngsborough, MA next Thursday (December 18, 2003) on the topic .Net Security Best Practices. A big thank you to Sam for recommending me to Jim for this opportunity. Here is a summary of what I will be covering:
Within the .Net Framework, two complementary forms of security are present: User (Role-Based) Security and Code (Access) Security. User security answers the questions,
“Who is the user and what can the user do?” while code security answers the questions “Where is the code from, who wrote the code, and what can the code do?”. This presentation will give a practical overview of both forms of .Net Security as well as best practices for using .Net Security.
If you are in the area, stop by and say hello.
My friend Andrew has been doing a lot of research lately to find more information on Rotor beyond the excellent Rotor book (Shared Source CLI Essentials). Yesterday, he posted a wiki link to a great architectural resource for Rotor: Software Architecture of 'Rotor' CLR.
I've said it before, and I will say it again, one of the BEST ways to learn what's going on under the CLR is look at Rotor code.
Lars Bergstrom wrote an article for MSDN a few months ago called “Developing Software in Visual Studio .NET with Non-Administrative Privileges” and it looks like it has been updated this month. Do yourself a favor, and read this article.
Over the last few years, I have been a big believer in developing software as a non-Administrator. I followed Keith Brown's excellent advice on how to set up your machine correctly, and have continued to do so with each new OS or machine. The key is to only run as Administrator (using the “Run As“ feature) when you need to install software or various other administrative (hence, the reason why the user is called “Administrator”) tasks.
On my laptop, I run two OSs, Windows 2000 Server and Windows Server 2003, plus a Virtual PC with Windows XP Pro, and in all cases, I set up strong passwords, rename the Administrator, and run with an everyday normal, non-privileged user. With this mode, I have found, like Lars and Keith above, interesting ways to do secure tasks, especially with distributed .Net application development lately.
As Keith mentions, its a “lifestyle choice“ to develop this way. You make a decision to run as a normal, non-privileged user to help yourself learn about security on the platform as well as how to write better, secure code. Most users who work with our software are usually running as non-Admins, and can hit the security wall hard if we are not careful.
Plus, a big question for developers I always want to ask: “Do you need to be an Administrator to check email in Outlook?”.
Michael Howard points to an MSDN article he wrote about the Windows Application Verifier (better known as AppVerifier), a tool that helps developers verify their code is running correctly. Michael's slant on the tool is that it can help verify security issues as well, as the tool has been greatly updated to look for these issues (buffer overruns, etc.). Definitely a must-have tool as his article mentions:
Developers are urged to always use the SecurityChecks in the AppVerifier to test their applications before shipping them because end users have access to the AppVerifier and are able to find any security holes that it exposes.
Another task I am working on is extensive performance and scalability testing for a large Distributed .Net project. Our approach is to set up tests early to determine load, stress, and scalability metrics, and to test often as work progresses. This helps us to quickly know if our assumptions are correct or if we need to rethink some architectural issues early on rather than later (which can be more costly).
This weekend, I have spent a lot of time with a soon-to-be-released (March, 2004, I believe) gem from the Microsoft Patterns and Practices group, headed by Ron Jacobs, called Improving .NET Application Performance and Scalability. This is the same group that brought a couple of my other favorite Patterns and Practices books: Volume I, Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication and Volume II, Improving Web app security: Threats and Countermeasures.
As I mentioned, this book has not been released on the Patterns and Practices site yet as it is still a Beta 1 version. But, the content is excellent so far. There are sections on general performance guidelines for Managed Code, and specific performance information for Interop, Remoting, Enterprise Services, ASP.NET, Web Services, and Data Access. Plus, like the other books above, there are extensive How-To articles such as how to use the CLR Profiler, ACT (Application Center Tester), EIF (Enterprise Instrumentation Framework), SQL Profiler and various other testing tools and tuning parameters.
There is also a WebCast from late November that describes the book and the top 10 performance issues with .Net (highly recommended).
As Sam mentioned, I have converted our projects from using VS.Net 2003 as the build tool to NAnt as the build tool for all our Distributed .Net projects. (I mentioned this task way back in late October, and finally got a chance to do it.)
I am using the latest NAnt 0.84 Release Candidate 1, and I am already making changes to my build scripts from last week because of deprecated properties in the 0.83 version.
I have a few questions though, and so far, I haven't been able to find any good answers. One assembly I am referencing for our builds is the Oracle Data Provider for .Net, which is GAC'd as Oracle.DataAccess. I would like to refer to this assembly by the assembly name, but so far, I can only get my project to compile successfully if I point to the explicit file name/location. That file location may be different depending on the machine the build scripts will reside. Any ideas on how to set this up correctly? Is it possible to reference a GAC'd assembly?
I have also tried to use the “gac”
task to uninstall and install my GAC'd assemblies for prebuild/postbuild targets. This seems to work great for installing, but when I use [ gac assembly=“AssemblyName.dll” uninstall=”true” /] (per the documentation, replace  with angle brackets), the assembly is re-installed rather than uninstalled. For now, I have removed the prebuild/postbuild targets and placed them into a script file/batch file. Not the best solution, but it works for now because is not a completed task for NAnt yet, and I have to do a gacutil and regsvcs for any COM+/Enterprise Services components. Any clues on what I am missing regarding the “gac“ task, though? Is there a setting, perhaps, in the NAnt.exe.config file? Update: Actually, the “gac“ task is part of NAnt Contrib, which is a set of tasks that have not been placed into NAnt yet, or don't belong in NAnt. NAnt Contrib is now a separate install from NAnt starting with the 0.84 Release Candidate 1.
Update 2: I found my own error. The correct syntax is: [ gac assembly=“AssemblyName.dll“ action=“uninstall“ ] (replace  with angle brackets). To install, use “install“ for the action. Now, I can place this back into my build scripts.
Update 3: I found that the “regsvcs“ task IS now part of the 0.84 release. Great! Scripts have been updated.
Speaking of the NAnt.exe.config file, according to the documentation, NAnt should use the 1.0 Framework by default, unless it finds both 1.0 and 1.1, in which case it uses 1.1. I am testing the latest NAnt scripts on my Windows Server 2003, and it does not have 1.0 installed. Instead of using 1.1, it tried to run csc.exe from the 1.0 Framework directory. By changing the default Framework version in the NAnt.exe config file to use 1.1, everything built correctly. On another note, I noticed (not sure how long this has been there) that NAnt can also use the 1.2 Framework (Whidbey), Mono 0.28, and Rotor 1.0 for building.