About UsCommunityTrainingContent DevelopmentContact

Blogs
Pluralsight
Course Schedule
Scott Allen
Craig Andera
Mark Baciak
Don Box
Keith Brown
John CJ
Tim Ewald
Jon Fancey
Jon Flanders
Vijay Gajjala
Kirill Gavrylyuk
Ian Griffiths
Martin Gudgin
Jim Johnson
John Justice
Mike Henderson
Joe Hummel
Matt Milner
Ted Neward
Fritz Onion
Brian Randell
Jeffrey Schlimmer
Aaron Skonnard
Dan Sullivan
Herb Sutter
Doug Walter
Jim Wilson
Mike Woodring

My Links
Home
Contact
Login

Blog Stats
Posts - 278
Stories - 0
Comments - 902
Trackbacks - 183

Keith's books
Effective COM
PWS
The Guide

Misc
Hall of Shame
My Wiki(rss)

Recent Articles
Security Briefs
Username Tokens

Archives
Apr, 2008 (2)
Mar, 2008 (4)
Feb, 2008 (1)
Jan, 2008 (14)
Dec, 2007 (8)
Nov, 2007 (5)
Oct, 2007 (5)
Aug, 2007 (1)
Jul, 2007 (1)
Jun, 2007 (4)
May, 2007 (7)
Apr, 2007 (3)
Mar, 2007 (1)
Feb, 2007 (3)
Jan, 2007 (2)
Dec, 2006 (2)
Oct, 2006 (1)
Sep, 2006 (1)
Aug, 2006 (2)
Jul, 2006 (5)
Jun, 2006 (13)
May, 2006 (7)
Apr, 2006 (2)
Mar, 2006 (3)
Feb, 2006 (7)
Jan, 2006 (4)
Dec, 2005 (15)
Nov, 2005 (14)
Oct, 2005 (14)
Sep, 2005 (11)
Aug, 2005 (7)
Jul, 2005 (9)
Jun, 2005 (13)
May, 2005 (5)
Apr, 2005 (3)
Mar, 2005 (6)
Feb, 2005 (12)
Jan, 2005 (9)
Nov, 2004 (5)
Oct, 2004 (14)
Sep, 2004 (5)
Aug, 2004 (7)
Jul, 2004 (10)
Jun, 2004 (8)
May, 2004 (3)

Post Categories
42(rss)
ASP.NET(rss)
Geek talk(rss)
GUI(rss)
Identity(rss)
PowerShell(rss)
Security(rss)


by Keith Brown

Saturday, April 12, 2008

This is a minor update. Here's what was changed (from the readme file):

      Incorporated a patch from Richard Howells to give
      you the option to turn on/off the "Always On Top" behavior
      of the main form. I still recommend not keeping PWM in
      memory all the time - only run it when you need it to keep
      your master key safe. I also used adjusted the Auto-gen
      password dialog to be more reasonable: it now by default
      specifies a 12-char password, not the 20 it used to - most
      websites can't handle a password that long. I also removed
      the lower case 'l' and punctuation, with a button that allows
      you to add back in the puncutation marks if you want.
      One last minor thing - I added AcceptsReturn=true to the
      notes editor so it won't disappear when you press Enter :)

You can access the latest version from our tools page.

posted @ 3:49 PM | Feedback (5)

Friday, April 04, 2008

This is new; J.D. and crew are hosting it on CodePlex to get feedback. From J.D.'s blog:

Our patterns & practices WCF Security Guidance Project is in progress on CodePlex.  This is our first release of prescriptive guidance modules for WCF Security. 

How Tos
Our How Tos give you step by step instructions for performing key tasks:

Videos
Our videos step you visually through key guidance:

posted @ 6:09 AM | Feedback (0)

Friday, March 14, 2008

Thanks to all of YOU who attended my claims-based identity postconference here at DevWeek. Grab the demos from here.

Updated (20 Mar 2008) with new link.

posted @ 9:15 AM | Feedback (0)

Thursday, March 13, 2008

Thanks to all who attended this DevWeek talk today. Here's a link to the demos I did, along with the tamper-detection code I showed you. Enjoy!

Updated (20 Mar 2008) with new link.

posted @ 3:44 AM | Feedback (0)

Friday, March 07, 2008

In a recent post, I talked about my experience enabling continuous integration for the internal builds here at Pluralsight. I recently worked with Craig to restructure our nant build. As part of that, I wanted to ensure that I could run the build from anywhere in the source tree. We use a typical hierarchical build where each project has a build script that knows how to compile, test, deploy, etc. based on the specified target. Then at the top of the tree, there's a build script that runs all the other ones. That root build script is what gets run automatically by Cruise Control.

My root script defines a bunch of properties, like where the output directories for the overall build live, where the tools live, and so on. And that works fine when I run the build from the root. The properties get defined, all the child scripts are run with <nant/> tasks, and they see those properties. But if I want to drill down into the tree and run one of the build scripts lower down, suddenly there's problems because it depends on properties that are only defined in the root script. I really like being able to run builds from anywhere in the tree for perf - if I'm trying to fix a particular project, I don't necessarily want to wait for unit tests on the entire tree to run in order to see if mine passed.

Craig made a great suggestion. Put the properties into a separate script (we named it properties.nant) and <include/> that script. Then to enable hierarchical builds, we'd create a properties.nant file for each folder in the tree, which would <include/> its parent. That way I could define properties anywhere in the tree, and they would be "inherited" by anything below it.

I took that idea one step further, because I didn't want to maintain a bunch of property scripts with nothing in them but an <include/> for the parent. I wrote an <includefromparent/> nant task that walks up the directory tree looking for the target file. So now I can do this:

<includefromparent buildfile="properties.nant"/>

This worked great! But now I ran into a problem. Many of my properties are defined like so in the root properties.nant file:

<property name="libraryOutputDir" value="${project::get-base-directory()}\artifacts\libraries"/>

Do you see the issue? If I run the build with the root script, everything works fine, because it's the root nant project I'm building, and get-base-directory() refers to the root of the project, where the artifacts folder lives. But if I run from lower in the tree, it's a different project, and get-base-directory() refers to a subfolder, where the artifacts folder definitely should NOT be.

I needed a way to find the root of the project tree. So I build a second really simple nant task:

<findmarkeddir markerfile="filetolookfor.txt" property="root"/>

This task simply looks up the directory hierarchy until it finds the specified marker file, then puts the name of that directory (the "marked" directory) into a designated property (here I've called it root). With that in place, I rewrote my property definitions in terms of the base directory:

<property name="libraryOutputDir" value="${root}\artifacts\libraries"/>

VoilĂ ! I can now run builds from any of my build scripts. They inherit properties hierarchically like you'd expect, and the system is quite easy to maintain. If you'd like to use these tasks, I've included the code for them below (not much code, really). And if you've never written a nant task yourself before, here's the article I used to figure out how it's done (it's super easy). Here's what you should read to learn about the various options for deploying your custom task assembly so nant recognizes it.

Enjoy!

Here is FindMarkedDirTask.cs

using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using System.IO;

namespace PluralsightNantTasks {

[TaskName("findmarkeddir")]
public class FindMarkedDirTask : Task {

  [TaskAttribute("markerfile", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string MarkerFileName { get; set; }

  [TaskAttribute("property", Required = true)]
  [StringValidator(AllowEmpty = false)]
  public string PropertyName { get; set; }

  protected override void ExecuteTask() {
    string searchDir = this.Project.BaseDirectory;
    do {
      if (MarkerFileExistsIn(searchDir)) {
        this.Project.Properties[PropertyName] = searchDir;
        return;
      }
      searchDir = ParentOf(searchDir);
    } while (!IsRootDirectory(searchDir));
  }

  private bool IsRootDirectory(string path) {
    return Path.GetPathRoot(path) == Path.GetFullPath(path);
  }

  private string ParentOf(string directory) {
    return Path.GetFullPath(Path.Combine(directory, ".."));
  }

  private bool MarkerFileExistsIn(string directory) {
    return File.Exists(Path.Combine(directory, MarkerFileName));
  }
}
}

And here is IncludeFromParentTask.cs (note I derive from the built-in include task):

using System;
using System.Collections.Generic;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using System.IO;
using System.Globalization;

namespace PluralsightNantTasks {

[TaskName("includefromparent")]
public class IncludeFromParentTask : IncludeTask {

  protected override void Initialize() {
    string fileName = BuildFileName;
    if (fileName.Contains("/") || fileName.Contains(@"\\"))
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "buildfile attribute must only be a filename"));

    string relativePathToFoundFile = SearchParentDirectory(
      Project.BaseDirectory, fileName, 0);
      
    if (null == relativePathToFoundFile)
      throw new BuildException(string.Format(
        CultureInfo.CurrentCulture,
        "Couldn't find a file named {0}" +
        " in a parent directory of {1}",
        fileName, Project.BaseDirectory));

    // have to use a relative path here
    // because  task uses
    // Path.Combine(projectDir, BuildFileName)
    // to get the full path
    BuildFileName = relativePathToFoundFile;

    base.Initialize();
  }

  private string SearchParentDirectory(string directory,
                        string fileName, int searchDepth) {
    ++searchDepth;
  
    // see if we've traversed all the way to the root
    string currentPath = Path.GetFullPath(directory);
    if (currentPath == Path.GetPathRoot(currentPath))
      return null;

    // recurse until we find the file
    string parentDir = Path.GetFullPath(
      Path.Combine(currentPath, ".."));
    string path = Path.Combine(parentDir, fileName);
    if (File.Exists(path)) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < searchDepth; ++i)
        sb.Append(@"..\");
      return Path.Combine(sb.ToString(), fileName);
    }
    else return SearchParentDirectory(parentDir,
                          fileName, searchDepth);
  }
}
}
posted @ 5:49 AM | Feedback (4)

Wednesday, March 05, 2008

For the last few years, I've owned a couple of different optical mice. I started with a Logitech mouse and recently switched to a Microsoft mouse (Wireless Laser Mouse 6000). During the time I've owned these mice I've been frustrated by how they would jump around from time to time.

In the old days, I knew that to fix a standard mouse, you'd simply open the undercarriage, pop out the little ball, and scrape the crap off the rollers that accumulates over time. Voila! Your mouse would run like new. But there's no moving parts on the optical mouse, and it sure looked clean to me.

Invariably when my optical mouse would start to act up, I'd start switching surfaces, which sometimes seemed to help for awhile, but nothing really solved my problem, and I was about to go back to using a wired mouse.

Well, I feel pretty stupid, because I figured out how to fix the damn thing this morning. A bit of googling lead me to an article which said that sometimes a little hair (or a piece of dust, I'd imagine) gets trapped in with the optical sensor.

The solution?

Blow out the little hole where the optical sensor lies.

A quick puff of air cleared up my problem. Tada, new mouse. God I feel stupid. I think later today I'll pick up a dark, nonreflective mousepad to use, since this seems to be the recommended surface.

posted @ 6:19 AM | Feedback (1)

Thursday, February 14, 2008

The cool new wsHttpContextBinding and friends silently manage a workflow instance id for you under the covers. The first time you make a request through one of these bindings, a workflow is created, and the instance id is sent back to the client via a SOAP header. It's then stored in the channel and sent back with every subsequent request so that further requests can be routed back to the same workflow instance.

That's all well and good, but what if you want to contact an *existing* workflow? You'll need to communicate the workflow instance id to the channel manually. This is possible by querying the channel's context. You'll need to add a reference to System.WorkflowServices (if you've not already got one). Once you do that, you can use this code to get the InstanceId guid from the channel:

This code was tested with Visual Studio 2008 RTM.

// note if you're using a code-generated proxy, you'll need to use channel.InnerChannel
IContextManager contextManager =((IChannel)channel).GetProperty();
IDictionary ctx = contextManager.GetContext();

// read the instance ID from the context...
Guid instanceId = new Guid(ctx["instanceId"]);

// or, maybe you need to update the context of a new channel...
ctx["instanceId"] = instanceId.ToString();

// ...and set it back on the channel (or a new channel)
contextManager.SetContext(ctx);

Hope this helps - I'm recording this mainly for my own recall :)

posted @ 1:35 PM | Feedback (0)

Wednesday, January 30, 2008

I managed to get this recipe manager installed last night. The instructions for Windows users are pretty old and out of date (the primary audience for this software is in the linux world). But I managed to get it installed and running nevertheless, and if you're reasonably technical, you should be able to do it as well. Once I got the app running for the first time, it immediately appeared to download a boatload of data, which I think was a database of nutritional information for ingredients as well as ingredient/category mappings, and probably other stuff that I've not figured out yet.

From the little I've seen of this app, it looks pretty impressive. I'll keep experimenting and post my findings here.

Here are some hopefully helpful hints if you want to give it a try along with me. I installed all of the items on the "Required Packages" list:

  1. I already had Python 2.5 installed.
  2. The Glade runtime environment was trivial to install.
  3. PyGTK was a little more complicated. Since these instructions were written, it looks like the project was split into three parts, and I think you need all three (which are trivial to install). I installed the latest versions of each for Python 2.5. Once you get all three installed, add the bin/ directory from the GTK into your path and bring up a python command shell (just run python.exe to do this) then type 'import gtk' and if you don't get any errors, you're probably good.
    1. PyCairo
    2. PyGObject
    3. PyGTK
  4. PyWin32 install was trivial.
  5. PIL was also trivial.
  6. PyRTF is python sources, which you'll need to install. Copy the directory to a drive somewhere, then bring up a command shell and CD into the directory you just created. You should find a setup.py file there. Run 'python setup.py install' to install. This is what I'll call a "python install" from now on.
  7. ReportLab also requires a "python install", so do the same thing.
  8. PySqlite2 - the website is down as I write this, so I don't recall what type of install it requires, but I don't remember having trouble with it...
  9. Metakit - this one I couldn't quite figure out how to install, but it appears to be an optional thing.

Once you've installed all of the prerequisites, it's easy to install Gourmet Recipe Manager. It's also a python install, and once you've run the setup.py script, you can launch the program as described in section 3 of the instructions.

posted @ 2:02 PM | Feedback (0)

Tuesday, January 29, 2008

So I'm a divorced father who cares for his three sons 50% of the time. It's a challenging but tremendously fun task. Since the separation, I've been spending much more time with my kids than I ever did before, and I'm loving it. But I'm still a geek at heart, and I hate doing clerk-like work to figure out what to buy at the grocery store. I'd rather automate much of this menial work so that I have more time to spend with my kids or with my work.

My first step in my quest for automation was to find a program that helped me create shopping lists. I bought a copy of SimplyShopping, which has worked pretty well for what it does. What I like about this program is that it helps you print aisle-by-aisle shopping lists, which really speed grocery shopping up tremendously. What I dislike about it is that there's no end-to-end workflow where I can simply list the recipes I want to make for the week and have it print out a shopping list.

I thought of taking the concepts that I like in SimplyShopping and writing a new app that does everything I want it to do. I think I'll eventually do this. But the first thing I need to do is figure out a good data model for a recipe. And once I enter the recipe into my app, I'd like to be able to share it with other people. And what better way to do that then to start with a community-accepted XML format for recipes?

I searched for XML Schema Recipe and happened upon RecipeML, which, based on its copyright, appears to have been around since 1999. They have a DTD but no schema, and the last time the DTD was updated was Nov 2000. Their gallery of applications links to a single app, whose web page no longer exists.

Another search for Recipe Sharing XML lead me to the Recipe Sharing Protocol Specification, which talks a lot about exchanging data, but very little about how to model a recipe in XML. They refer to something called RSPML, but I can't find that documented anywhere.

Then there's RecipeBook XML, which has a DTD and several sample recipes. This format uses mixed content, which makes me wonder how easy it'd be to program against.

Beyond finding an acceptable data model for sharing recipes, the next problem would be to agree on a vocabulary for units of measure. I don't think it'll be possible to come up with a list of ingredient names that everyone would agree upon, so the software processing the recipes would have to deal with that.

What do you think? Is this an intractable problem? If not, does anyone want to work on this with me? I think it'd be a fun project.

posted @ 9:17 AM | Feedback (10)

Wednesday, January 23, 2008

This is one of my favorite places, and I've been away for quite awhile. During the week of February 12, I'll be teaching our Applied .NET 3.0 course, and covering some of the new stuff in 3.5 as well. This class is an introduction to the 3.x platform: four day's of lectures, demos, and labs covering WCF, Workflow, WPF, and one of my favorite topics, the new claims-based identity model (which ADFS and CardSpace use). The course runs Tuesday through Friday.

If this sounds intriguing, sign up today!

posted @ 12:44 PM | Feedback (0)


 
   
 
© 2004 Pluralsight.
Visual Design by Studio Creativa
Privacy Policy