Thursday, October 30, 2008

JTemplates template file cached workaround

I've been using a lot of JQuery and JTemplates after reading a couple really helpful JQuery and MVC posts at Encosia.com. One problem I ran into while doing some development on a new .Net MVC Project that was using JQuery extensively was that my template files were being cached by my browser. I tried clearing the cache but that wasn't helping, so here's a workaround I came up with.


If you take a look at how JQuery's $.ajax(...) function handles the caching problem you can see that they append a random query string parameter to each request.




So that is what I basically did to workaround the caching problem with the template files. I created a function called cacheBust() that just returned the current times milliseconds value and used that to generate my random query string. Here's some sample code:





function cacheBust() {return new Date().getMilliseconds().toString();}

function GetTimeEntries(day) {
// Show the loady
showLoady();

$.ajax({
type: "GET",
cache: false,
url: "/TimeEntry/" + day.replace(/\//g, "-"),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// This method loads the HTML template and
// prepares the container div to accept data.
$('#TimeWrapper').setTemplateURL('/scripts/timeentry.vw?_=' + cacheBust());

// This method applies the JSON array to the
// container's template and renders it.
$('#TimeWrapper').processTemplate(msg);

// Hide the loady.
hideLoady();
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info, I'm not using either.
hideLoady();
$('#TimeWrapper').empty();
$('#TimeWrapper').append("<p class='errord'>There was a problem loading the data from the server. Sorry I got nothing else.</p>");

}

});
}


And now we get the most up to the second versions of our templates. Once I'm done with development it will be beneficial to have the templates be cached. I figure once that happens I'll change my cacheBust() function to return a constant (something like, "ItCompilesSoShipIt").



Now Playing: Snow Patrol - Open Your Eyes

Monday, October 6, 2008

Powershell Count Files By Regex Match on Content

Being a Powershell Winter Scripting Games Top Scorer for both the 2007 and 2008 Scripting Games I have to keep my skills fresh. Never know when you need to whip out an extra dirty little script to count how many T's are in a text file.

Scripting languages always give me a dirty feeling when I get done and look at my code. I'm a fan of what Code Complete describes as the Primary Imperative of Software Engineering; Managing Complexity. Solving something with a scripting language always makes we want to write something using the least amount of characters possible. Comments, descriptive variable names and consistent formatting usually go right out the window along with the ability to come back a month later and figure out what is going on in the script, let alone try and tell a co-worker what is going on.

That being said, here is a tiny powershell script to count files based on a Regex match of their content. Don't worry, I took the time to comment it a little bit and even have some pretty descriptive variable names. It originally was just one line for the specific task I needed to get done. I was looking for the number of xml files with a specific value in a set of directories.


# Create Parameters for our script.
# TODO: Make a helpful usage reply when no parameters supplied.
Param( [String]$path="./",
[String]$filter="*.txt",
[String]$match=$(throw "Regex Pattern required."),
[switch]$searchSubs)

$reg = [regex]$match;

if ( $searchSubs )
{ # Get the files matching the passed in path/filter
dir -path $path -filter $filter -recurse
# Loop through each and look for a match of the Regex.
% {
$in = gc $_.FullName; $reg.Match($in).Groups[1].Value
} group #Group the Values.
}
else
{ dir -path $path -filter $filter
% {
$in = gc $_.FullName; $reg.Match($in).Groups[1].Value
} group
}

Here is some sample usage:

./FileMatch.ps1 -path c:\somewebsite\fileUpload -filter *.xml -match 'field value="(.*?)" name="blah' -searchSubs

You can even mix up the parameters if you want. Powershell Rocks!

Now Playing: Jason Mraz - Curbside Prophet

Tuesday, September 23, 2008

What the Buddha Taught: Meditation as Concentration and Attention to Detail

As part of the wonderfully useful (I'm not being sarcastic) major in philosophy during my college years I had the pleasure of reading a book called What the Buddha Taught by Walpola Rahula. Of course, being a philosophy major I was especially susceptible to the kind of books that stir up what some might call "Deep Thoughts", also "Navel Gazing".

Interestingly, I found out later after a course in Elementary Logic, taught by Dr. Cassandra Pinnick, that there was more to this whole philosophy thing than sensational ideas about religion and boring lectures about the business ethics of companies who are, IMHO, just trying to help factories by selling glue in Guatemala (see H.B. Fuller Glue Sniffing). I mean seriously why would it be my companies fault if some retard kid in Guatemala uses my product in an illegal and reasonably unforeseeable way.



Anyway, the point of this post is to bring a little bit of clarity to your life by way of one of the most misunderstood concepts in modern religion, Meditation (specifically the Buddhist concept of Meditation). I know what you are thinking, "There's not enough room in my cubicle to cross my legs" and besides that, "The weird guy Wesley who sits in the cubicle across the aisle doesn't even like it when I play my new Enya CD more than a whisper; there is no way he will listen to me 'Hummmm' to myself for 15 minutes while I get in the 'Zone'".

As are most actual Buddhist followers, you are probably mistaken about the definition of Meditation. Here is Meditation as described by Walpola Rahula,

"It is unfortunate that hardly any other section of the Buddha's teaching is so much misunderstood as 'meditation', both by Buddhists and non-Buddhists. The moment the word 'meditation' is mentioned, one thinks of an escape from the daily activities of life; assuming a particular posture, like a statue in some cave or cell in a monastery, in some remote place cut off from society; and musing on, or being absorbed in, some kind of mystic or mysterious thought or trance. True Buddhist 'meditation' does not mean this kind of escape at all."
Of the various acts that can involve meditation (Nearly every task can, from eating to reading to coding) the one that has been brought to my mind recently is the act of concentrating fully on a given concept to gain insight. We have a sort of open-ended question that we ask during interviews, "Tell me everything you can about what happens from the time a user enters an address in a web browser to the time the page is displayed."

To me, this is an excellent concept to Meditate on. You see Meditation is really better described as 'Mental Development'; and all exercises/disciplines that cultivate that 'Mental Development' are forms of Meditation. I'm sure you have certain situations where you are forced to sit around with nothing to do; maybe you have a long ride to work in the morning, a weekly 3 hour conference call where you only participate for 5 minutes (right in the middle) or a monthly company meeting where they talk about keeping the damn kitchen counters clean for an hour (I mean seriously, we got it, keep the counters clean, check that one off the list, lets move on for the love of....). Why not try and think deeply about some concept related to your work during that time.

As programmers, we're lucky. There are abstractions all around us that we never really think deeply about. I know I can spend at least 30 minutes thinking about what is really happening when you join two strings together in a simple C# statement like;



var blah = "Miss Piggy loves " + "Kermit";


(Pseudo)Dynamic-typing, operator overloading, memory allocation, character pointers, null terminated strings, character encoding, registers and ALU's have been neatly and nicely stowed away so as to not require too much mental heavy lifting. Don't get me wrong, it makes us extremely productive (Think about having to know internal combustion engines inside and out just to be able to drive to work, not productive).

I think you'll find that concentrating on something specific with as much detail as possible, like the two strings or the HTTP request/response life cycle, will give you a sort of 'enlightenment' when it comes to how you write code, drive to work, cook a meal or even shave your face.

Now Playing: Jimmy Eat World - Futures

Monday, September 8, 2008

Dare Obasanjo's 3 Laws of Platform Adoption: A DotNetNuke Perspective

Dare Obasanjo has an informative post up about the 3 Laws of Platform Adoption, which got me thinking about DotNetNuke as a platform for developers. The first competitor that comes to most peoples minds when thinking about DotNetNuke is Sharepoint but there are other Content Management Systems out there that are viable alternatives to small and medium businesses looking to step up their website in a cost efficient and functionality rich way. Joomla! seems to be getting a lot of attention among developers on the LAMP stack as a hip new replacement for phpNuke.

When it comes to using the 3 Laws of Platform Adoption as a metric I think DotNetNuke stacks up pretty well for your small to medium business. Lets take a look at the condensed version of the 3 Laws.


1. Developers adopt a platform when it offers differentiation from competitors


2. Developers adopt a platform when it reduces the cost of software development


3. Developers adopt a platform when it provides reach and/or better distribution


So, starting with the obvious number 1, what differentiates DotNetNuke from its competitors? For me, DotNetNuke is different than its competitors in that it is designed to run atop your existing Microsoft software without adding any licensing fees. Small business clients running *nix servers are few and far between, so the ability to leverage your existing technology resource investments gives people a warm and fuzzy feeling. As far as Sharepoint as a competitor is concerned, it just doesn't make sense for small businesses because of the licensing fees. I know that Sharepoint Services 3.0 is free to download for Windows Server 2003, but most of the cool features are only available by ponying up extra for MOSS.

In the world of providing custom solutions for small businesses, Cost = Time = Money. This is why DotNetNuke also has a good footing for number 2. From a developers standpoint DotNetNuke runs on very familiar, some would say it's even cheap (as in inexpensive), technology (Visual Studio Express, IIS, Windows Server, Vista, even XP), which means less setup, implementation, deployment and maintenance time. Developers can use the .Net language they are most comfortable in (C# all the way!) and utilize the functionality that DotNetNuke comes with right out of the box. Functionality like user profiles, role based security, multiple authentication providers, secure file access, and rich content editing.

DotNetNuke also has a strong and innovative community of users. The DotNetNuke Marketplace allows developers a place to distribute their products and services to a wide range of customers (current registered user base on DotNetNuke.com. The DotNetNuke core team has made it easy for users of DotNetNuke to find products in this marketplace by way of a link to the "Solutions Explorer" that is standard in all DotNetNuke installations. DotNetNuke acts like an open source community with a business mind. Along with the Marketplace, the introduction of Service Level Agreements that are competitively priced give other businesses the opportunity to make profits on helping users with their DotNetNuke problems.

Sunday, September 7, 2008

DotNetNuke Search Engine Optimizing - Step 7 Good HTML

I found an interesting post in a blog written about a year ago from Tom Kraak, owner of Seablick Consulting. The post gives a good list of SEO tips to consider when using the DotNetNuke framework which I think is helpful for all the people involved in creating a web site. Your modern day web developer simply has to be cognizant about the SEO ramifications of their implementation details.

The one that comes to mind first when thinking about my role, as developer (see previous post about "Three D's", I'm the one with the halo ), is number 7.


Write well-formed, standard compliant HTML to improve accessibility and "crawlability." Consider excessive in-page JavaScript, HTML layout tables and frames junk food for search engines spiders. I'm well aware that strict XHTML remains a challenge with DNN, but let's make an effort to move away from quirks mode by adhering at least to XHTML transitional.


Number 7 is one of several good reasons why I am an advocate of DIV's over Tables. Regardless of the fact that all the cool kids seem to be using div's these days, I still like to be able to answer the question "Why do people use div's over tables?" when occasionally asked by the seasoned developer (aka Old Fogey) and ordinary Dreamweaver adept (aka Graphic Designer). Here is my basic response: Tables were meant for tabular data, that is what they should be used for. Now to add to that, tables are incredibly helpful in some situations; I'm not an advocate of throwing them completely under the bus for all layout handling.

The problem with using tables for layouts (that I personally have found) is that they are very frequently rendered differently in every browser. As a corollary (albeit slightly contrived) to this problem, I like to also point out that it often takes more HTML to do the same layout with tables. One single 120 x 120 block of glorious green background is done in one div tag and some CSS, whereas if it were done with tables it becomes 3 tags and some CSS. The increase in the number of tags means an increased surface area for rendering problems with the browser, not to mention the increase in the amount of code to maintain.



Glorious Green


Now Playing: T.I. - Swagger Like Us

Sunday, August 31, 2008

Dare Obasanjo Makes Me Want To Work At Microsoft

I've been reading a lot of Dare Obasanjo's Blog (aka Carnage4Life) over at 25hoursaday.com. I came across the blog through some posts on the CodingHorror blog a while back and have been a subscriber since setting up my Google Reader about a month ago. I've read about the drama before and the previous hiatus on postings, I'm glad he is still around for me to find.

There are a couple of things I have to say about the blog. The first is that I like the content because it provides a good mix of technical information and programming/software commentary. Sometimes the technical details (especially when talking about different protocol RFC's) get a bit above my head, but that is probably a good thing because I end up learning more because of the helpful links that he supplies.

I like that someone like Dare is still getting excited about new language features even though he obviously has a lot of things on his plate. My earlier posts on functional programming (including my "Sexy" Aggregate function in Leveraging the DNN Event Logging API) came out about the time that his posts did, but I was just recently looking through the archives and came across them.

The other thing about the blog that I like, which may or may not be a good thing for Dare, is that it makes me want to work for Microsoft. If a person like Dare is having a good time there, at least most of the time, then it probably is an okay place. For Microsoft recruiters, it's kind of like what Shaq called Homeboy Marketing:

'Homeboy Marketing’

Marketers refer to it as guerrilla marketing, but O’Neal calls it “homeboy marketing… . Most people spend $2 million, $3 million for a commercial. With homeboy marketing, it’s all for free. When these TV stations want to interview me, I wear a FreeInternet hat. When consumers see me on TV, they also see all this stuff.”



Dare gets to do "Slam Dunk" technical posts about topics that interest him, and along the way readers (probably pretty technical readers) find out that Dare works for Microsoft. In this instance, it's me, a 26 year-old programmer on the come up. Maybe somewhere else it's the genius that gives Microsoft a winning search solution that takes out the feet of one of their competitors.

Anyway, this blog was originally started as a way to indirectly market the super-cool company I work at and I'm not currently looking for a job. But if I were...

P.S. I gotta make me some kind of blogspot widget that does that "Now Playing" thing at the bottom of Dare's Blog Posts. Maybe something that can pull information from Amazon and link there (I'm not a big fan of Apple right now, don't get me wrong I'm not one of those guys with a stick yelling "Get Off My Lawn" because all the cool kids are using Macs, I'll have to elaborate in another post). For now, I'm totally ripping it off, sorry:

Now Playing: Augustana - Boston

Tuesday, August 26, 2008

Your Website - The Key Players Involved

So you want/need/gotta have a new website? Maybe you're the young and feisty new marketing manager in a small/medium sized company, maybe you're the graphic designer in a small/medium sized company and you're manager wants you to put together a new website. The fact is, you're trying to figure out how to get a website up, or update your current one, without looking like an idiot to the other stake holders in the business.

The first place to start is to know who is going to be involved in the website development process. This is where we introduce the Three D's of the simplified web development life cycle.



(Sorry I couldn't make you a little WeePerson also, but you can at their website)

You may think that the first person you are going to need is a developer, but as important as we are :) you don't want us to pick what colors go on your website. This is where the uber-cool hippie designer chic... or dude... comes in. What you're looking for in a designer is someone who has done some websites before, they should ask you things like; how many pages are you going to have on your site? What do you want visitors to your site to be able to accomplish? How do you want visitors to feel? And all those softy questions that the development people aren't going to want to talk about.

In the design phase you want to get everything mapped out, drawn up, reviewed and approved. At the end of the design phase you want to come away with an approved design file. At my company, Adaptive InfoSystems, we like to have layered PhotoShop files to work with. Most of the time, the designers we work with don't like to write HTML. If you can find a designer that does HTML (Designers Should Know HTML), well I mean Good HTML, then they may be able to supply that to your developers.

At a minimum, your design file should contain all distinctive layouts you want to use on your websites pages. For example, if your home page has a different layout than your internal pages, you need to show at least 2 page designs. You can separate them into two different files, or layer one file in such a way that both designs can be viewed by hiding a group of elements related to one or the other layouts.

After you review the design and approve it, it's time to turn the design into code. Here we move from the Design Phase, to the Development Phase. Your designer delivers the design document (hopefully a layered PhotoShop file) to the developer. The developer starts by laying out the structure of your site. We like to use Div's and CSS instead of tables for layout, it makes it a little bit easier to change the site in the future because we separate the style from the layout. Once the structure is in place, we make a template of the design without content (In .Net this is called a Master Page, in DotNetNuke it's called a Skin).

After the template is made, the developers start entering content. To speed up things in this stage, it helps to have your content already approved and ready to put up on the web. To do this, we recommend you start creating copy for your pages with word documents. A one page Word Document for each page on your site is recommended, but if it has to be more the page usually will grow to accommodate the expanded content.

While the content is being entered onto the site, the other special programming tasks like "Contact Us" forms, your product search that ties into your database, and even that cool little Google Maps thing that helps your customers find out where their orders are coming from are all being created by the developers.

By the end of the development phase you should have had several reviews of the content and designs that are being created on your site. A sign that something might be going wrong with your development is when developers "Go Dark". Essentially, if you're developer doesn't do a couple different rounds of reviews to give you a little taste of what is going on and where they are at in the project, it's a bad sign. Regular updates keep you in the loop and allow you to catch small problems before they get too big and waste every one's time.

At the end of the project is the Deployment Phase. The Deployment Phase is done when your website goes live. This is usually handled by a combination of your developer and your hosting company. The hosting company is responsible for setting up the things that let people get to your site; things like servers, DNS, network connection, etc. The developer uploads your web files and maybe your database to the hosting company and verifies it still works the same as it did when it was in development.

Well, that is the Semi-Brief introduction to the Simple Web Development Life Cycle. I expect I'll elaborate a bit more on each of the roles in coming posts. What developers like to see from designers is usually a helpful topic.

Thursday, August 14, 2008

WPF Calendar Control

For our time entry here at the office we use the infamous NetTERD (.Net Time and Expense Reporting Database). I created the NetTERD as an extension of the existing Access Database that was distributed upon arrival at the company.


Anyway, to get to the point of this post, I've never been happy with the way we select dates in the NetTERD. We've decided to go with a WPF version of the NetTERD that will add alot of features that will be helpful for creating estimates and tracking revisions and changes. The WPF has a lot to offer when it comes to user interfaces, so I decided to take some time and make a stylish calendar control for selecting the date in the new WPFTerd (Codename Adept).


After reading some posts about WPF over at the Hanselminutes blog I did a quick google image search for a calendar. I found a pretty good set of them at some random Pocono vacation site; so I horked the image and opened up Photoshop for a little workout of my Photoshop-Fu.







Not too bad for a programmer with no design skills. So we have our background image, now we fire up our Visual Studio 2008 and do some XAML coding. I specifically wanted to not use Blend for this because I need to start getting more familiar with the XAML, I don't want to fall victim to the Law of Leaky Abstractions. All the coding here was done with the VS 2008 Source Editor, not the designer.



After getting the date to display on my background how I wanted, I needed a way to work in the traditional version of the DatePicker control. I found a nice WPF DatePicker control by Marlon Grech and decided I could bend it to my will. I changed the style of the DatePicker a little to make it work by clicking the bits of calendar on the upper right of the image. Just a couple Visibility="Collapsed" and changing the TriggerBox styles and Voila! we got something semi-respectable.

Check out the source if you are looking for something to hork as well. You'll need to download the AvalonControlLibrary and add a reference to it also. Fair warning, it is statically sized, I'm hoping to make it sizeable later. I'd also like to do some kind of sexy animation with the DatePicker popup. Suggestions welcome.

Jacob

Friday, August 8, 2008

Deck Construction - Final Result

Here is the final result of the deck project. Not so bad for a couple of programmers.








Friday, July 25, 2008

F# for beginners

I'm trying to get some more breadth to my programming knowledge, so I decided to start looking into F# for some functional programming exposure.

So far, I'm liking what I'm going to call the brevity of the language. I'm not one of those people who thinks that programming languages ought to be made for the "Everyone" programmer, at least not all programming languages. It gives me the impression of condensing the programming down into little mouth-puckering shots of power, akin to some condensed tomato soup or something.

Anyway, to dig a little deeper into the language and actually try and solve problems I decided to try and do the beginner Scripting Games Events from this year in F#. There is already at least one post on another F# blog where someone is doing the first event.

I decided to try and limp through the second event, and here is what I came up with.


#light
open System
open System.IO
open Microsoft.Win32

// Scripting Games Event 2, How many True Type Fonts installed.

// Open the registry key where fonts are stored, using .Net objects
(Registry)
let fontKey =
Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows
NT").OpenSubKey("CurrentVersion").OpenSubKey("Fonts")

// Get the font names, convert to list
let vals = fontKey.GetValueNames() > Seq.to_list

// Defining a recursive "function" that takes a string to match and a list
of strings, returns num of matches
let rec matchEnd (srch : string) (list :
string List) =
match list with
[] -> 0 // Empty list
// The x and xs refer to the head(x) and tail(xs) of the list.
x::xs
when x.Trim().EndsWith(srch) -> (1 + (matchEnd srch xs))
x::xs ->
matchEnd srch xs

// Print the true type fonts, number of fonts, and total fonts.
List.filter (fun (b : string) -> b.Trim().EndsWith("(TrueType)")) vals
> printfn "%A"
printfn "True Type Fonts Installed: %A" (matchEnd
"(TrueType)" vals)
printfn "Total Fonts Installed: %A" vals.Length

// Pause for exit
Console.ReadKey(true)




Sorry for the lack of formatting (which is actually important for the #light syntax). So I think that does the job for Event 2. I'm sure it could be better, but it's just a learning exercise so far.

Friday, July 18, 2008

Deck Construction - Part 3 - Posts and Rails

We don't really have any pictures from the day we raised the posts and put the joists up. It was raining all day and it's just a blur now. Here is the current state of the deck.






So far, so good. Next steps, get the railings done and start the stair stringers.

Deck Construction - Part 2 - Solid Foundations

So the next phase of the deck is to put some solid foundations in place. After getting out some string and squaring everything up to the house, Brian and I rented a two-man Auger to drill 32" holes for our post bases. I don't really have any pictures of the holes, but here is the finished product with the concrete poured.

After getting the post holes dug and filling them with concrete, we attached to houseboard by using a hammer drill to drill 10" holes into the house. According to the inspectors, I couldn't just put lag screws into the board behind the brick, I had to go into the ends of the joists (dead-nuts so to speak). It was a pain in the butt, but we finally got all our holes lined up with the end of the joists and attached the board to the house with 10" Lag Screws.




Next step, putting up the massive 6x6 posts after we notch them for the beams.

Deck Construction - Part 1 - Destruction

So, in order to make a new deck, you have to get rid of the old one. Here is the old one.



Me (the flabby pale guy) and my brother (the skinny pale guy) decided to cut the joists that connect to the house board and pull the deck away from the house.


So far so good. Then we had to cut the pieces up into smaller more manageable pieces and haul them all to the dump to get rid of them. The Champagne Tacomastang made a pretty good wood wagon.

Tuesday, June 24, 2008

Deck Plans using Google Sketchup

I am undertaking a somewhat big home improvement project, for me anyway. I've convinced myself I can build a deck.

Here is a couple of screenshots of the plans I did using Sketchup.







Thursday, April 17, 2008

Leveraging DotNetNuke Event Logging

We recently worked on a project where we were faced with logging some events that a custom module was creating. I decided to take a look at the DotNetNuke EventLogging API.




Here is some hacked together code that implemented this… Check out the sexy aggregate function at the bottom… :)

DotNetNuke.Services.Log.EventLog.EventLogController lc = new DotNetNuke.Services.Log.EventLog.EventLogController();
// Check if the logtype exists.
List logs = new List(lc.GetLogTypeInfo().Cast());
if ( !logs.Any(x => x.LogTypeKey == "IPVideo_Links") )
{
// If Not, create the logtype.
LogTypeInfo lt = new LogTypeInfo();
lt.LogTypeCSSClass = "IPVideo_Links";
lt.LogTypeDescription = "Logging the IPVideo Links Module";
lt.LogTypeFriendlyName = "IPVideo Links";
lt.LogTypeKey = "IPVideo_Links";
lt.LogTypeOwner = "DotNetNuke.Logging.EventLogType";
lc.AddLogType(lt);
}

// Add a log entry.
lc.AddLog(new LogProperties{
new LogDetailInfo("Property1", "Some Value 1"),
new LogDetailInfo("Property2", "Some Value 2"),
new LogDetailInfo("TimeSubmitted", DateTime.Now.ToString())
},
this.PortalSettings,
this.UserId,
"IPVideo_Links", /* Should probably make this a enum value */
true);

// Retrieve the events for the log.
int total = 0;
List details = new List(((LogInfo)lc.GetLog("IPVideo_Links", 100, 0, ref total)[0]).LogProperties.Cast());

// Get the events properties.
// I know you like my sexy use of Aggregate, admit it, its sexy.
string props = details.Aggregate("",
(result, logInfo) =>
String.Format("{0}{1}: {2}\n", result, logInfo.PropertyName, logInfo.PropertyValue));

// Show the properties.
txtDetails.Text = "Got the details\n" + props;







Here are some links I found useful when coming up with this code.

DNN Core API - Logging (pdf)

MSDN Aggregate Documentation