Wednesday, June 11, 2008

LINQPad - not just for LINQ

I officially love LINQPad.  Joe Albahari has done a great job of introducing a light weight tool that is great for learning and prototyping LINQ queries.  From what I gather, Joe and Ben Albahari built this tool as part of their book offering.  It was so useful, it has taken on a life of its own.

It may not be entirely obvious, but it turns out don't have to use LINQPad solely for LINQ queries.  You can actually prototype any type of snippet of code.  I have been using it now instead of SnippetCompiler (another great quick snippet tool).

As an example, here is how to use System.DirectoryServices snippets inside of LINQPad:

Hit F4 to bring up the Advanced Query Properties Window

image

Add the System.DirectoryServices.dll reference in the Additional References window, and then add "System.DirectoryServices" in the Additional Namespace Imports window.

Now, just type your code normally and hit F5 when you are done:

image 

This is a great little tool to have as you can query databases, build LINQ expressions, and visually inspect the results that come back pretty easily.  Now, as you can see you can also execute arbitrary code snippets as well.  Highly recommended.

Monday, June 02, 2008

Continental Offers Million Miler Program

As a frequent flier and former Continental Platinum Elite member, I was always jealous of the American Airlines program where you got lifetime status on the airline whenever you achieved a million air miles with them.  However, I was browsing the FlyerTalk forum when I noticed this announcement.  I can't wait to see how far away I am on it (probably 600K or more away is my guess).

FlyerTalk Announcment

Wednesday, January 30, 2008

Internet Connection Sharing is Amazing

I am on the road this week, working from a hotel and Starbucks primarily.  My hotel provides a wireless connection throughout the building which is a great thing.  The downside is that it basically dies in the evening when everyone gets to the hotel and slows the pipe to a trickle.  The other major downside is that it is incompatible with Microsoft VPN software.  What to do?

I recently switched phone providers from T-Mobile to AT&T.  The reason for this was actually quite simple:  It was waaay cheaper to switch to AT&T, get a brand new Blackjack 2 phone along with the 3G network offered there (T-Mobile is GPRS only right now) than to remain a T-Mobile customer.

I remember reading from Omar about using ICS with the Blackjack 2, so I give it a try.

Wow, the AT&T 3G network is amazingly fast (~863 Kb/s down, ~281 Kb/s up) for a phone.  But more to the point, it is faster and more reliable that the hotel wireless, plus it lets me VPN into work to boot.  That feature alone is worth the price of admission.  It's a shame that the Blackjack 2 doesn't have any way of getting Hotmail into your messaging app or that they didn't include ICS by default.  But, using the hack that Omar pointed out goes a long way to fixing some of it.  Very nice...

Monday, November 12, 2007

IIS7 Remote Manager Access Denied Error

If you have been playing with the remote management capabilities in IIS7, you might run into an error where you are denied access to change anything from the remote client:

 

image

A quick investigation using ProcMon shows that "Local Service" is trying to modify the configuration file (web.config) in the managed directory and is being denied access.

Naturally, to fix this you need to give write access to "Local Service" for whatever application you are trying to manage.

Friday, September 14, 2007

Using SQLDependency objects with LINQ

A question came up the other day on how to get LINQ to SQL to participate in using the SQL Notification Services.  Of course, I didn't know, but Mike Pizzo from the ADO.NET team was kind enough to answer.  I figured it must be possible, and sure enough, it is.  Essentially, you have to create a SQL dependency context, which is very similar to a transaction context.  Any code that participates within that context will automatically be associated with the SQLDependency.  Create the dependency first, before any LINQ (or other data access technology).  Here is the relevant code (note: this code is not optimized, so you might want to do things like change the SQLDependency to static or pass it in so it won't be garbage collected).

    static class GlobalNotifications

    {

        public static event OnChangeEventHandler OnChange;

 

        public static void InitializeNotifications(string connectString)

        {

            // Initialize notifications

            SqlDependency.Start(connectString);

            // Create and register a new dependency

            SqlDependency dependency = new SqlDependency();

            dependency.OnChange += new OnChangeEventHandler(NotificationCallback);

            System.Runtime.Remoting.Messaging.CallContext.SetData("MS.SqlDependencyCookie", dependency.Id);

        }

 

        internal static void NotificationCallback(object o, SqlNotificationEventArgs args)

        {

            OnChange.Invoke(o, args);

        }

    }

There is also one major caveat to using this with LINQ: Beware of complex queries that can be easily generated using LINQ.  The Query Processor will invalidate the command and fire an error event saying it was too complex.  Since you can easily generate lots of complex queries using LINQ (part of its power really), you need to really be cognizant of this limitation.

Friday, March 30, 2007

IIS7 and 404.3 Error

Here is something that I am sure developers will run into as they start to create web sites on their local Vista boxes using IIS7.  I thought I would just put this out here to save people some time.  If you are like me, you will go to the 'Turn Windows features on or off' selection and simply check the IIS7 option like so:

If done correctly, this installs the ASP.NET environment and all the appropriate stuff.  If not, you get an interesting error when you browse to the first .aspx page on your site.  Specifically, you will get a nice 404.3 error similar to this:

The part that should tip you off that something is completely misconfigured  is the part of the the error message (which are sooo much nicer these days) where the module is being reported as the "StaticFileModule".  Static files are things like .html files, jpegs, etc. where we are not performing any server side logic.  We know that our .aspx files need to be processed by the .NET runtime, so we should see something else as the handler there.

Now, here comes the confusing part.  Bring up the IIS Manager (Windows Key > "Inetmgr"), and view the Handler Mappings for your site and you will see something similar to this:

Notice that all of the ASP.NET extensions are missing?  There are no handlers defined for the .aspx, .asmx, .ashx or any other .NET extensions.  If you bring up the handlers installed on the machine however, you will see that they are all just fine:

At this point, you may be like me and scratching your head asking, "why are my handlers not being inherited correctly"?  If you are like me, then you will probably try delete your web app and then re-add it back.  When that fails you will try to uninstall and reinstall IIS7 again.  When that doesn't work, you will try to reinstall ASP.NET manually from the command line using "aspnet_regiis -i" or something similar.  When that fails, you will spend hours on Google trying to see what other people have done.  It might also cross your mind to just add them manually to your configuration.  If you are like me, however, that seems dirty and you will keep trying.

To save you some time, it actually turns out it is pretty easy to fix.  Simply DELETE the "Default Web Site", and then ADD it back.  The Handlers will be re-applied correctly and your virtual directory or web site will have all the correct handlers installed.  It is confusing why this even happens with a fresh install, but it appears to be a frequent occurrence according to Google searches.  Coming from IIS 5.1 and 6, it might be counterintuitive to delete a site, but this is actually not a big deal in Vista since you can have as many of these as you like (no artificial limits anymore).  I hope this saves someone some time.

Note to the IIS7 teamman, it would really be nice if you had a button that said something like "apply inherited handlers" or something like that.

Tuesday, January 30, 2007

Vista through Remote Desktop

One word...awesome.  While you don't get Aero or anything like that, it properly scales the display to my 24" Dell monitor at home and looks fantastic through RDS.  I have been typing so much lately that I decided I needed my larger monitor and natural keyboard from home.  My wrists were killing me from typing on my laptop keyboard.  I didn't realize how much I needed the natural keyboard.

Monday, January 29, 2007

Free T-Mobile HotSpot Access

Users of Windows Vista (of which I am) are entitled to receive 90 free days of T-Mobile Wifi access at any HotSpot location starting today.  Since there are like 2.8 billion Starbucks locations in the US alone (all of which are HotSpots), this means you have pretty good chances of being able to redeem this offer (at least in Seattle where approximate 1.3 billion of those Starbucks are located).

I signed up today thinking there would be an elaborate process to confirm that I was running Vista.  I was imaging some applet like that horrid WGA (Windows Genuine pain-in-the-Ass) that keeps popping up everywhere.  Luckily, no such garbage.  In fact, it appears that T-Mobile is validating eligibility by a simple browser agent check.  While the average user might not know how to change that browser string, you can bet a number of users do know how (Firefox has some great ones).  I suppose T-Mobile doesn't really care too much at this point or they would have done it differently.

Friday, July 28, 2006

A Good FTP Program

Omar asks is anyone knows of a good FTP program in this post.  Similar to Omar, I was getting sick of the nagging that SmartFTP performed each time I started it.  Even more annoying was when it refused to launch (ala Reflector.NET) until I performed an upgrade.  I asked around and everyone and their brother recommended FileZilla.  I suppose I am the lone voice of dissent on this one.  I actually tried to like FileZilla, but had to uninstall it rather quickly.  It just didn’t do things like I expected.  I couldn’t drag items into windows and back, and other assorted quirks that I forget now.  I really wanted to like it, but just couldn’t.

I almost went back to SmartFTP until someone mentioned Novell’s NetDrive application.  I tried this and never looked back.  It is a simple idea really.  It maps a drive to a remote FTP location and you use Windows Explorer like you would anything else.  It works great.  If you were to type “Novell Netdrive” into your favorite search engine, you would find plenty of places that host this particular very handy app.

Monday, July 24, 2006

A Recursive Pattern For DN Syntax Attributes Part 2

I am revisiting this particular topic once again to finish it up.  Last time, we established a general pattern for searching any DN syntax attribute in Active Directory or ADAM and chasing down all the nested results in either direction (i.e. forward link to back link or vice versa).  The solution worked well with one caveat:  intermediate values.  We often do not want to capture the intermediate values, but only the end results.  As an example, if we were to expand the group membership for a group object (the ‘member’ attribute) to discover the users, we would not want to include the other nested groups as values in our results, but we would only want to include the users in those nested groups.  In other words, we would want to exclude the intermediate values.  This is different than another example, say of discovering an org chart by expanding the ‘directReports’ attribute where we would clearly want to know all the intermediate reports.

For the specific example of expanding a group object to get membership, I posted an example in the book that used recursion and specifically excluded the result if the ‘objectClass’ was ‘group’.  I posed the question, “was this necessary?”.  Or more specifically, “can we create a general solution that will deal with both cases for intermediate values?”

The answer, of course, is yes.  We can pretty easily create a solution that will allow us to keep the intermediate values or discard them if we want.  In the general case, we do not need to know the object types.  In our example in the book, I think it was more clear what was happening by putting knowledge of the object type.  However, it also could have been solved with a simple boolean and no knowledge of the objects themselves.  Here is the revised solution.  I am omitting the IADsPathname interface this time, but you can easily pull it from the last post.

public class RecursiveLinkPair

{

    DirectoryEntry entry;

    ArrayList members;

    Hashtable processed;

    string attrib;

    bool includeAll;

 

    public RecursiveLinkPair(DirectoryEntry entry, string attrib, bool includeIntermediate)

    {

        if (entry == null)

            throw new ArgumentNullException("entry");

 

        if (String.IsNullOrEmpty(attrib))

            throw new ArgumentException("attrib");

 

        this.includeAll = includeIntermediate;

        this.attrib = attrib;

        this.entry = entry;

        this.processed = new Hashtable();

        this.processed.Add(

            this.entry.Properties[

                "distinguishedName"][0].ToString(),

            null

            );

 

        this.members = Expand(this.entry);

    }

 

    public ArrayList Members

    {

        get { return this.members; }

    }

 

    private ArrayList Expand(DirectoryEntry group)

    {

        ArrayList al = new ArrayList(5000);

 

        DirectorySearcher ds = new DirectorySearcher(

            entry,

            "(objectClass=*)",

            new string[] {

                this.attrib,

                "distinguishedName",

                "objectClass" },

            SearchScope.Base

            );

 

        ds.AttributeScopeQuery = this.attrib;

        ds.PageSize = 1000;

 

        using (SearchResultCollection src = ds.FindAll())

        {

            string dn = null;

            foreach (SearchResult sr in src)

            {

                dn = (string)

                    sr.Properties["distinguishedName"][0];

 

                if (!this.processed.ContainsKey(dn))

                {

                    this.processed.Add(dn, null);

 

                    if (sr.Properties.Contains(this.attrib))

                    {

                        if (this.includeAll)

                            al.Add(dn);

 

                        SetNewPath(this.entry, dn);

                        al.AddRange(Expand(this.entry));

                    }

                    else

                        al.Add(dn);

                }

            }

        }

        return al;

    }

 

    //we will use IADsPathName utility function instead

    //of parsing string values.  This particular function

    //allows us to replace only the DN portion of a path

    //and leave the server and port information intact

    private void SetNewPath(DirectoryEntry entry, string dn)

    {

        IAdsPathname pathCracker = (IAdsPathname)new Pathname();

 

        pathCracker.Set(entry.Path, 1);

        pathCracker.Set(dn, 4);

 

        entry.Path = pathCracker.Retrieve(5);

    }

}

This simple class uses the AttributeScopeQuery option to enumerate the attribute and then uses the utility interface IADsPathname to reset the entry as we recurse the results.  So, we now finally have a generic solution that will work on all DN syntax attributes in both directions and with or without intermediate values.

Friday, March 31, 2006

DEC 2006 Wrap Up and Presentation Material

Joe and I had a great time on Wednesday presenting our talk on Directory Services Programming in .NET.  Being the first time that we have ever presented together, we did no know exactly how it would work out.  All in all, we felt it went pretty well.  Thanks to everyone that attended!

One of the cool parts for us was that our publisher sent over some draft copies of the book.  We knew our publisher was sending something, but we had thought it was a sample chapter or two.  It was quite surprising to open the box and find the full text!  Seeing your hard work in print for the first time almost gives you goose bumps.

As promised, I am attaching the presentation material to this post.  It includes the updated presentation that we used as well as all the samples that we used during it.  We actually did not get to one of the samples called Dirsync, which allows us to poll the directory periodically for updates, so check it out.

If anyone has questions on these samples or the topic itself, Joe and I can be reached through the MS newsgroups or the ASP.NET Forums.  I would also suggest checking out what I consider useful System.DirectoryServices resources.  I will try to keep that updated as I find more.

Thursday, December 22, 2005

The .NET Developer's Guide To Directory Services Programming

Keith beat me to it, but Joe and I have finally submitted the final manuscript.  We have some copy editing left, but the book is mostly baked.  It has been a long time in the making and we are very fortunate to have had some great reviewers like Keith giving us advice along the way.

There were a lot of things that we wished we could have covered (perhaps in another book) more in depth.  It was a balancing act between trying to dump everything in our brains and not publishing a 900 page book.  The final page count is around 450 pages right now, which is big, but not too intimidating.

All in all, this was a good experience.  I did not know Joe very well when we started, but needless to say, we know each pretty well at this point and are good friends.  I think the partnership worked pretty darn well for two first-time authors collaborating mostly over email and wiki.  Joe knows his Directory Services very well and it would not nearly be the same book without him.  Keith was slightly off in his description (it was over a year ago), but I knew about Joe from the newsgroups (where he was dropping some serious knowledge) and had suggested to Keith to contact him as the second author of this book.  It was a great decision and I am glad Joe took it.

So, what is in the book?  Pretty much all the basics for System.DirectoryServices, like binding, searching, reading and writing attributes.  We cover the more advanced searches and data type marshaling as well as schema considerations and a discussion of security as well.  Finally, we cover a more scenario, or ‘cookbook’ approach for the more popular topics like user and group management as well as authentication.  We know what problems most users have and we try to address them in the scenarios.

Most of the samples in the book are going to be using System.DirectoryServices, though we do cover in places how to do things using the .Protocols namespace.  Additionally, we have one chapter that gives developers a view of what is there in the .ActiveDirectory namespace that they might use (it is mostly for administrators).

It is important to know that this is truly a guide and we could not cover every single scenario.  As part of the book’s website (or this blog), we will be adding new scenarios and how they can be accomplished as well.  Additionally, we are going to release some very cool code that developers will be able to use in their own applications.

As always, we can be found in either the forums (http://forums.asp.net) or the newsgroups (microsoft.public.adsi.general).  I am not usually on the newsgroups, but Joe camps there.

 

Tuesday, November 01, 2005

A solution for loquacious co-workers

I subscribe to some internal mailing lists at work.  Oftentimes they are informative, sometimes amusings, but lately they have just become increasingly annoying.  I think I finally found the solution.  Essentially, it is a Do-Not-Disturb sign on the inane blatherings of a few mildly annoying individuals.

I am going to give it a shot as soon as Omar releases it to see how it works.  Right away I can think of another feature I would like it to have:

  • I want the ability to mark messages not only by thread, but by individual.  Certain individuals seem to have nothing better to do than spam the mailing lists and annoy everyone.  This way the thread could be killed regardless of subject if it was originated by someone.
Unfortunately for me, most of my email access during work hours is using OWA, so this won't help me there.  At least my hours in the evening will hopefully be less painful when using the full client.

Friday, October 14, 2005

More Gmail uses

I ran across this link today concerning a bunch of Gmail ‘hacks’.  It seems like Google does not care too much about people extending their system beyond its original uses.  A case of a very wise service provider, IMO.

http://www.extremetech.com/article2/0,1558,1871053,00.asp

 

Tuesday, September 20, 2005

Google as a spam filter

Skonnard points out that you can forward your personal email accounts to your Gmail account and then access Gmail via POP again to have it filter your spam out.  Additionally, you gain the benefit of long term email storage and better searchability (although Lookout does well for me).  This is probably an unintended use, but quite useful.