The Johnson Blog

Ramblings of a geek with a few hobbies…

Tag: .Net

  • More PowerShell – a Cmdlet

    This past weekend I spent some time reading up on and writing my first PowerShell cmdlet.   The cmdlet is an easy one, but replaces a PS function I have copy/pasted into several scripts here and there to handle cleaning out directories of old backups or other types of files.  One scenario is my RadioShark which I have setup to make daily radio recordings.  The software doesn’t have any settings for how long to keep the files, so up until now I have just been manually deleting a couple dozen at a time every month or so. 

    Enter Remove-OldItems, named after the built-in Remove-Item.

    Full Syntax: Remove-OldItems c:temp -pattern *.mp3 -KeepDays 7 -Leave 2 -Confirm -WhatIf

    That will remove all mp3 files in c:temp which are older than 7 days.  The Leave parameter is for when I use it for dealing with backup files and is a safeguard so that even if all of the files fall out of the date range, they won’t all be deleted. 

    I have put together 32-bit and 64-bit installers, feel free to download them.  If you run it on a 64-bit system, the install will register with both the 32 and 64bit PowerShells. I can make the code available if anyone’s interested.

    After installing the .msi, you can confirm the new Snapin is on the system by running get-pssnapin -registered. You should see EjiSnapin listed.After Install

    Now the Snapin containing the cmdlet(s) is there, but not loaded into the current PowerShell session.  Since I’m going to be running this from a Scheduled Task, I don’t want to have to explicitly run Add-PSSnapin EjiSnapin every time I want to use it.  One quick way around this is to add that command to the system-wide PowerShell Profile located at $pshomeprofile.ps1.  That’s easy enough, in an elevated PS prompt, just run notepad $pshome/profile.ps1 and add a single line Add-PSSnapin EjiSnapin and save the file.  Now every PS session will have the cmdlet ready to go.

    Here’s the final result, a scheduled task with a simple command being run to clear out old files in my RadioShark directory.

    task

    Overall it was fairly easy, the most difficult part came with getting the installers to work correctly between 32 and 64-bit installations.  Future enhancements, if I come into a situation where I need it, may be to add processing from the pipeline so a collection of files to be deleted could be passed to the cmdlet instead of a directory path.  Might be useful, might not.

    Here’s C# for doing the actual deletions.

    
        DirectoryInfo rootDir = new DirectoryInfo(Path);
    
        // anything older than Today minus KeepDays may be deleted
        DateTime protectionDate = DateTime.UtcNow.AddDays(-KeepDays);
    
        List candidates = rootDir.GetFiles(string.IsNullOrEmpty(Pattern) ? "*.*" : Pattern, SearchOption.TopDirectoryOnly)
            .OrderBy(f => f.LastWriteTimeUtc).ToList();
    
        if (Leave > 0)
        {
            // pop the last Leave files off the end (the most recent)
            candidates.RemoveRange(candidates.Count - Leave, Leave);
        }
    
        // now only keep those that are old enough
        candidates.RemoveAll(f => f.LastWriteTimeUtc >= protectionDate);
    
        // cycle and delete
        candidates.ForEach(f =>
            {
                if (ShouldProcess(f.FullName, "delete"))
                {
                    try
                    {
                        f.Delete();
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        WriteWarning(String.Format("Unable to delete '{0}', UnauthorizedAccess", f.FullName));
    
                        // IOException can also occur, but I want that to be a termanating exception
                    }
    
                }
                else
                {
                        // Nothing to do, ShouldProcess provided any errors/warnings/etc.
                }
            });

    In the process of writing this I learned that PowerShell V2 allows you to script cmdlets.  So this could have been greatly simplified (mostly on the deployment side), but that wouldn’t have been nearly as interesting, right? 

    That’s all folks. Thanks for reading.

  • iTunes is iAnnoying

    Too bad the iPhone makes you get sucked into the world if iTunes – because it sucks.  I knew this going in, but it still isn’t fun when the limitations smack you in the face.

    The limitation of which I speak is its inability to detect new files in its directories, automatically update its library database, and make it available for syncing and playing.  I spent a while fumbling around the UI looking for the option to turn it on, only to be ultimately disappointed by a few google searches. 

    My initial plan was to take home movie clips (btw, MediaCoder is pretty handy..) and drop them into a directory managed by iTunes so they’d automatically get sent to the phone, but now I was going to have to add additional steps of manually adding the new videos each time they get created.  That’s just too much work and I’m too lazy.

    I ran across an app or two that would do this updating for you, but instead decided to go a different route – creating a podcast that iTunes would auto-update and sync to the phone.  Tuesday night I whipped up an ASP.NET request handler (IHttpHandler) to generate feeds based on directory contents.  So now I’ve got the auto-updating capability I was initially looking for: after I create the video, I just drop it into a directory accessible by my webserver and iTunes will pick it up the next time it requests the feed.  As an added bonus, David now has a podcast for family and friends 🙂

    Some more details on the code below the break.

    (more…)

  • Chef 1.3.20

    I just released the latest version, 1.3.20, tonight.  A few new things include: recipe rating; cooking times; preparation times; better search capability; ingredient preparations; bug fixes; and more bug fixes.

    If you’re a user, go upgrade!  If you aren’t a user, give it a try!

    www.ejichef.com

    And now it’s midnight, time for bed.

  • Visual Studio 2008 Setup Projects

    This is going to be fairly heavy on the tech side, so you’ve been warned…

    A couple weeks ago I converted the Chef code to Visual Studio 2008 – not a new .net version, just upgraded the solution and project files to the new format so I could start using the new IDE. I ran into just one small problem that was easily fixed when the conversion ran, that being a namespace getting mangled in one of the .designer.cs files that kept the code from compiling clean. Like I said, no biggie.

    (more…)

  • Recipe Slideshows

    Chef has a feature called Recipe Slideshows which allow you to view a recipe fullscreen in a PowerPoint-like format that’s much easier to read while you’re cooking than the small text of a cookbook, or the regular view of a recipe in Chef for that matter. I’ve had that feature around for a while, but I noticed that Ana never uses it!

    Her main complaint was that the ingredients weren’t always displayed so she’d find herself constantly flipping between the directions and the ingredients, to the point where it was just much easier to deal with the small text of the regular recipe window. This past weekend I made a few changes – the ingredients are always displayed AND it highlights the ingredients that are used for the current step. Click for the full image:

    Chef Recipe Slideshow

    This is going into version 1.3 with a few other enhancements and fixes due sometime in January or February.

  • C# operator== overloading

    I recently came to a situation where operator overloading C# (specifically the == operator) would really be beneficial. Since I’ve typically steered away from this technique, for readability and maintainability, I hadn’t had much experience with it.

    My overloaded operator looks something like this:


    static bool operator==(Id<T> a, Id<T> b)
    {
    return a.Value == b.Value;
    }

    That has been working just as planned for a few months now, but today I hit a snag when trying to do a null test against a variable of that class type, like:


    Id<int> x;
    ...
    if (x == null)
    {
    ...
    }

    This causes a nice null reference exception at a.Value because a is null. My first thought was to test for null in the operator== method before I attempt accessing a.Value (or b.Value), like:

    if (a == null)
    {
    return b == null;
    }
    else
    {
    return a.Value == b.Value;
    }

    Thinking I had the problem fixed, I reran; and quickly hit a StackOverFlowException. What the? Ooooh, the if (a == null) was causing that method to be called over and over, recursively until it blew the stack! OK, now how the heck can I test against null without the operator== being called??

    After a moment of slight panic, I realized how to get around it. When doing just if (a == null), the Id class’ static overload is being called. The way out of this is to have the object class’ operator== explicitly called by making a simple change:


    if ((object)a == null)
    {
    return ((object)b == null);
    }
    else
    {
    return a.Value == b.Value;
    }

    And that’s it! I now have an overload that handles null checking.

  • Note to self: Another Software Idea

    In the same vain as another post, I or someone needs to write a Visual Studio 2005 add-in for managing the Break on Exception feature.  Specifically, be able to create profiles that can easily be switched between during debugging sessions that would enable/disable breaking into the deubber on certain types of exceptions but not other.

    As I’m sure anyone who has worked on a large .NET project has experienced, not having this capability built-in is a royal pain in the butt.

  • Chef and Vista

    As I mentioned last night, I made the 1.0.0 build of Chef and started doing some installation testing on Vista.

    It’s official – Vista’s UAC is kicking my ass.   It’s during the database setup that I’m having the problem.  Sql Server gets installed OK, it’s for some reason the database restore that times out.

    Kinda tired of running the sql express install at this point.

  • Visual Studio on Vista

    As mentioned I installed Vista on my new desktop, since I have been running it on my laptop with Visual Studio for a month now without any real problems. Go figure, I ran into an issue that has been bugging me for the past couple days.

    The symptoms are as follows:

    • Every time I start VS, it prompts me for which initial environment I’d like to use (C#, C++, etc).
    • If I look at Tools..Options..Import/Export Settings, the settings file path doesn’t include a drive and root directory – it’s just Visual Studio 2005/Settings/CurrentSettings.vssettings.
    • If I go to that Import/Export Settings screen and then try to leave it without changing anything, it blows up regarding the messed up path.
    • Each time I exit and re-enter VS and view that setting, it has appended a new number to the filename. Sure enough, I can see lots of those files being created.

    The problem?

    It turns out that VS didn’t like the fact that I changed the Location of my Documents folder to point to a network share. Pretty odd behavior though, glad I remembered I made that change.

  • Visual Studio followup

    Just a little follow-up regarding my issue with Visual Studio 2005 and Vista – I was able to make the problem go away by installing a hotfix for KB912019.