PowerShell Script Examples for NuGet Packages

Here is a list of PowerShell examples taken right from the packages you might already be using, some have more detailed explanation or examples elsewhere on the webs. This list intends to be a quick reference for common operations when building install scripts for your NuGet packages.  Keep the list handy for writing install for your own packages.

2011.06.21 Updates

Import Modules (Using External Scripts for Commands) 

    Import-Module (Join-Path $toolsPath commands.psm1)

Going forward, the recommended convention (from David Fowler) for extending the package manager console is to put your scripts into seperate files (modules) in your tools directory, and to import them with a command similar to above in your init.ps1 file.

Insert Text into Current Document at Cursor

_from jQuery.Farbtastic
_        $dte.ActiveDocument.Selection.Insert($scriptTemplate)

Use this to write out text to the current cursor location in the active document. A little caution with this one: You might want to check the lenth of the selection first (write-host $dte.ActiveDocument.Selection.Text.Length) becuase this will overwrite any selected text. 

Copy Text to the Clipboard

_from _jQuery.Farbtastic
    $mystring | clip

In this snippet all we’re doing is ‘piping’ the string into the clipboard.  Be mindful that this would overwrite anything already there.

There are lots of interesting ways you can add functionality to your package and the package manager console.  I found, in exploring useful ways to get code to the user, that there may be scenarios where just pushing generated code to the clipboard may not be a bad option.

Discover IDE Manipulation and Automation Commands

    $dte | Get-Member

This ouputs the list of exposed properties and methods in the DTE object.  This is super handy for fiddling with the IDE from the Package Manager Console, even inside a test project, to figure out what is available.  Besides, self discovery is more interesting than reading the docs ;)  You can also try plugging around with the properties exposed, such as $dte.Solution | Get-Member, for example.


Read Properties from Visual Studio Objects

_from SqlServerCompact
_    $currentPostBuildCmd = $project.Properties.Item(“PostBuildEvent”).Value

This gets the post build command from the specified project item.

 

Loop Through All Installed Packages

from NuGetPackageUpdater
    foreach ($package in get-package) {
      write-host “Package $($package.Id) is installed”
    }

This loops through all packages that are installed on the currently targetted project.

 

Loop Through All Projects in the Solution

from NuGetPackageUpdater
    foreach ($proj in get-project -all) {
      write-host “Project $($proj.Name) is in this solution.”
    }

This outputs the name of each project in the solution in the package manager console. You can use get-project to retrieve the name of the currently targetted project.

 

Delete an Item in a Project

from MvcScaffolding
    Get-ProjectItem “foo.txt” | %{ $.Delete() }
 or
    Get-ProjectItem “InstallationDummyFile.txt” -Project $projectName | %{ $.Delete() }

This gets the specified file from the current project and ‘pipes’ it into the next command, which is a call to delete.  The “$_” is a token representing the passed-in object.  If you have the name of the project and want to target that project you can also use the -Project argument as in the second example.

Note: Get-ProjectItem was available when I tried this out because MvcScaffolding has a dependency on T4Scaffolding, which exposes a PowerShell cmdlet of the same name.  I will post on this later to show you how to get this to work in your own packages, but if you intend to use scaffolding anyways there’s no reason your package can’t depend on T4 for now.

 

Remove a Reference from a Project

from Machine.Specifications

    $project.Object.References | Where-Object { $_.Name -eq 'NameOfReference' } | ForEach-Object { $_.Remove() }

If you’re looking to purge references that you know are safe to do so when you’re uninstalling, you can do so as above. This uses a filter to selectively remove a reference from the project in question.  You could also use a foreach at the project level and remove the reference from each project (rather than using the $project param that NuGet feeds you when uninstall is executed).

Alternatively, rather than assuming your user hasn’t taken on the dependency in another fashion in their project, you could simply use Write-Host and let them know that if they aren’t using the references you’ve added (during your install) that it is now safe to remove them from the project in question.

 

Loop Through All Project Items

from MisterJames

    ForEach ($item in $project.ProjectItems) { Write-Host $item.Name } 

This will print out the list of all items in the specified project. You can use $item for project item operations per the VS automation docs (see link at bottom), here, I’ve just output the name.

 

Open a File from the Tools Folder

from EfCodeFirst (note that this is a legacy package no longer used)

    $dte.ItemOperations.OpenFile($toolsPath + ‘\EFCodeFirstReadMe.txt’)

This one is pretty straightforward.  $toolsPath is passed into our script and is available as a parameter throughout.  Here, we’re simply calling $dte.ItemOperations.OpenFile to open the file specified.

 

Opening a File from the Content Folder

from Glimpse.Mvc3
    $path = [System.IO.Path]
    $readmefile = $path::Combine($path::GetDirectoryName($project.FileName), “App_Readme\glimpse.mvc3.readme.txt”)
    $DTE.ExecuteCommand(“File.OpenFile”, $readmefile)

In this example there are two variables at play, an System.IO.Path reference  and a string being built to open a file.  In the final line, $DTE.ExecuteCommand is called to invoke Visual Studio’s “open file” command in a different way from EFCodeFirst, with the filename passed in as a parameter.  Note that you could also use [System.IO.Path]::Combine directly; $path is just a reference/alias to access the static method in a more readible manner.

 

 

Calling Other Scripts in the Current Scope

 _from SqlServerCompact
_    . (Join-Path $toolsPath “GetSqlCEPostBuildCmd.ps1”)

PowerShell will execute the specified file in the context of the current script when you do a “dot-space-brackets”.  In this example, we need to concatenate the name of our script, which is located in the package tools directory, to the tools path and then make the call.  At this point, any vars you set up will be available to you in the current script.  If you want to break out and build a list of files or - in this case - set up a variable with post-build information, this is your vehicle.

 

Exploring On Your Own

If you want to accomplish something that you don’t see here but have seen in another package it’s pretty easy to see what they’ve done.  You need to get yourself a copy of the NuGet Package Explorer – also a great tool for building your own packages – and just start pulling down the work that’s out there.

image

The best part about using this for exploratory purposes is that it can connect directly to a repository feed.  Just pull up File –> Open from Feed… to search or browse packages. The NuGet.org package repository load by default, but you can specify your own.

image

References

You can dive much deeper, of course, as you have PowerShell in your hands here, controlling the IDE.  If you want more information on specifics of any of the ideas at play here, check out the following links:

 

Wrapping Up

Know any other good samples?  A more straight-forward way to pull something off? Feel free to send me a note so I can add them here, or send questions my way.

CodeProject

Naming the Database Created by EF Code First

If you don’t want to have a database name like:
holy.crap.this.is.a.long.name.with.my.whole.namespace.contextname
…then you simply need to name the database.  To do this, we need to create the class that inherits from DbContext and call the base constructor to pass in the name.
    public class FamilyContext :

DbContext        {        public FamilyContext (): base(“FamilyContext”) {}        }

 

Sweet.  So, one other thing to pay attention to then, especially if you’re using MvcScaffolding or other similar tools.  If you’ve named your context you’ll need to tell it where you want your entity collections to manifest.  For MvcScaffolding in particular, you can use the –DbContext switch and pass in your context name.  That looks something like this:
Scaffold Controller Family -DbContext Family

The result is that MvcScaffolding will now look for that type in the target project and add the appropriate code.


    public class FamilyContext : DbContext
{
public FamilyContext (): base(“FamilyContext”) {}
public DbSet<MyProject.Models.Family> Families { get; set; }
}


Hope this helps!

Real World Scenarios Working with NuGet

If you’re working with ASP.NET and haven’t made the jump to MVC yet, you have to admit it’s getting harder and harder to not commit.  We’ve got some pretty juicy tools on this side of the fence with MVC3, especially when coupled with NuGet and some of the 1600+ open source packages that are already available free of charge.

Installation, Adding and Upgrading Packages

When you use an “Install-Package” command to install a package NuGet runs off first to grab the lastest version of the package from the repository. It “installs” it in the packages folder under your solution:

image

It adds entries to your packages.config file in your target project:

image

It may modify your web.config files…

image

…add project references…

image

…or files…

image

…before completing.  And if there are other dependencies in the package, those are downloaded and installed as well.  You will be notified if there are any conflicts.

Updating is a little more tricky because there is no auto-resolution from the console to force all required dependencies to upgrade.  To see what I mean, try installing Ie9ify to a new MVC3 project.  You have to go through:

  • an error and rollback on the ie9ify package install…it’s requesting jQuery 1.5.2
  • you attempt to update jQuery, but it fails because of dependencies
  • you have to update each package separately (jQuery UI, Validation and vsdoc)
  • then you update jQuery
  • then you can install ie9ify

Now, you can pass in an –IgnoreDependencies flag, but that doesn’t really help get you out of the water; you’ll still need to update all the other packages and resolve the conflicts manually.

Multiple Projects

Note that if you have more than one project on a solution that NuGet has to have a target for where its action will play out, and I’ve found that this will be the first project added to the solution.  So, for example, if you create a blank solution, add a models project and then add an MVC project, you’ll need to retarget your Package Manager Console.

image

So, not always a necessity, but worth looking at if a package install/update goes south.  You will notice this blatantly if you try to update or uninstall a package when you are targeting the wrong project.

There are legitimate reasons to target different projects at different times, so this is a great feature to have.  It is confusing, however, to have NuGet autocomplete package names for you when you try to tab them out; all packages installed in the solution will appear in the list.

Cleaning Up Post-Uninstall

Actually, I’m surprised at how good a job NuGet does at cleaning up.  For instance, if the package adds entries to the project’s app.config or web.config files it will properly remove them for you as well.  Same goes if it adds files to your project; they, too, will be removed.  Binary references, same deal.

There are some instances where an uninstall will report a clean job, but you’ll still need to do a little work.  Here are a few examples:

  • If you rename a file that’s been added by a package, it will remain in your project
  • You can change the value component of web.config and app.config files and NuGet will still remove them cleanly, but if you change the name/key of the entry, it’ll stick around
  • Dependencies aren’t removed when you remove a package, even if they were installed with the package in the first place.

Rounding Up

While there is still some room to grow, NuGet has become quite the little workhorse in the last few builds.  With the power of Power Shell behind the scenes most third party integration can be automated by package contributors.  Not only is there a growing library of community-sourced packages out there, but you create your own as well, or even create your own repository internally and take advantage of easy project setup company wide.

Questions about NuGet? Just ask! I’d be happy to help work through anything you’re trying to tackle.

CodeProject

Best Links to Getting Started in ASP.NET MVC3

If you want to spend an afternoon (or weekend) getting your head around what it means to move to ASP.NET MVC3, I’ve compiled a great list of resources that should get you on your way, sprinkled with the odd shameless plug. ;o)

Great Web Resources

Bloggers

It wouldn’t be right to start off a list like this without links to the people and places that host the most valuable content and resources on the web for ASP.NET MVC 3. If you’ve worked in MVC before and are comfortable catching up on your own these are the folks you want to be reading.

 

Community Sites

And, of course, here are the sites that keep the content rolling.

 

Getting Started

First timer? No problem. Dive into these guys here and find your way around your first few topics and projects.

The Razor View Engine

Get a better understanding of the new Razor View Engine and wrap your ahead around unwrapping the complexity of notation in views.

Custom HTML Helpers

Lego building blocks for site developers. You can use other folks’ code or build your own.

 

Deeper Dives

Walkthroughs

See how some of the finer details work and build some sample applications.

Videos and Video Tutorials

Get some pop corn, a pop and sit back.  Caution: The “Stack of Love” session might require a week of abdominal warm-up exercises to make sure you have appropriate laughing capabilities prior to viewing.  Try to avoid taking sips whenever you sense an incoming joke.

 

Other Resources

Did I miss something critical? Is there a blogger out there that helped get you through a bind? Let me know and I’ll keep the list updated.

MvcScaffolding Joy Ride with EF Code First

Okay, so here’s the situation: you are creating a web-based application that contains a series of tables, one of which has multiple one-to-one relationships with another table.

In your view, you’ll obviously have a series of drop downs that let you pick entities from the second table. This ensures data integrity, but is a bit of a PITA to wire up.

How do we put it all together?

A Quick Overview

All this work is really not that bad with the latest tools refresh, and only takes a few lines of code.  Let’s get there step by step and see how to make it happen.  I’m going to make a Movie entity and a FavoriteMovieProfile entity.  Here’s how she goes:

  1. Create a new ASP.NET MVC3 Internet Application.
  2. Use NuGet to install MvcScaffolding.
  3. Create a Movie class. POCO here, nothing special.
  4. Create a FavoriteMovieProfile class, with a bit of EF flavor.
  5. Scaffold our controllers with the repository pattern from the Package Manager Console.
  6. Extend the MoviesContext and create our own initializer for the database.
  7. Rescaffold the controllers.

Let’s Get Started – Project Setup

Okay, fire up Visual Studio 2010 and make sure you have the latest bits. Create a new project and select the type ASP.NET MVC 3 Web Application. I named my project Movies.Web and called the solution Movies.

image

Create an Internet application, Razor view engine and HTML5, because that’s the in thing to do.

image

Go to the Package Manager Console and type the following:

Install-Package MvcScaffolding

This goes out to the interwebs and grabs the latest version of this toolkit, along with the required bits to generate the scaffolding.  Going about its business, the Package Manager copies the packages to your project directory, updates your packages.config file and executes the required integration steps to light up the new references in your project.

Sweet.

Creating the Classes

Okay, right click on your Models folder and create a new class called Schema. When the file opens, delete the class definition (I just want the file named schema). Add the following using statement at the top of the file:

using System.ComponentModel.DataAnnotations

We’re going to add two classes to the namespace, the first is Movie:

public class Movie
{     
public int MovieID { get; set; }     
public string Title { get; set; }     
public string LeadActor { get; set; }     
public string Director { get; set; }
}

Next, add in the FavoriteMovieProfile class like so:

public class FavoriteMovieProfile 
{    
 public int FavoriteMovieProfileID { get; set; }     
public string Name { get; set; }     
public int ComedyID { get; set; }     
public int HorrorID { get; set; }     
public int DramaID { get; set; }     
public int SciFiID { get; set; }     
public int FlickWithHalleBerryID { get; set; }     

[ForeignKey("ComedyID")] public virtual Movie Comedy { get; set; }     
[ForeignKey("HorrorID")] public virtual Movie Horror { get; set; }     
[ForeignKey("DramaID")] public virtual Movie Drama { get; set; }     
[ForeignKey("SciFiID")] public virtual Movie SciFi { get; set; }     
[ForeignKey("FlickWithHalleBerryID")] public virtual Movie FlickWithHalleBerry { get; set; }
}

You’ll notice a little bit of funkiness going on there, but it’s really not that bad once you get your head around it. Let me explain what’s going on.

EF Code First and the MvcScaffolding bits are good and smart, but they still need to know stuff.  If we want our Views to light up correctly, MvcScaffolding needs to know how to render the model you’re trying to express.

You can boil the insanity down to a sort of key-pair model here. We need to store the id of the movie in the database but we also want to have the benefit of a rich model that knows about the movie entity being referenced.

Let’s look at just one key-pair sequence isolated from the rest:

public int ComedyID { get; set; }
[ForeignKey("ComedyID")] public virtual Movie Comedy { get; set; }

See, that’s not so bad, right!?

The ComedyID will be persisted to the database, while the Comedy movie object will not. We add the ForeignKey attribute for MvcScaffolding to clear up any confusing it might have mapping the object in its duties. Marking it virtual is a way of saying, “Hey, Mr. EF Code First groovy bits, please keep track of this object for me using the integer field I gave you, but when you load up my model, please include the full movie entity and not just a numerical field. K, thanks!”

Thanks, indeed, Mr. EF Code First groovy bits. Thanks, indeed.

Scaffold Intending to Fail

The only reason I want to fail here is to illustrate a current limitation of Code First. We can build up our project very quickly here, so make sure you have a good feel around the solution if you’re new to this so that you understand what’s going on.

Back in the Package Manager Console, type the following:

Scaffold Controller Movie -Repository

This little gem treats you to a coffee break while it creates your CRUD capable controller, your repository, the DB context object you want and fleshes out your views.  We’re going to do the same with FavoriteMovieProfile class now:

Scaffold Controller FavoriteMovieProfile -Repository

This does the same thing, but it respects that you already have a context in place and it just updates it as required.

Let’s run the project now and once it’s up, add a /Movies to your URL. The project will seem to run fine at first, but once you hit that movies view you should see this:

image

The database creation succeeded, but the creation of the database objects did not. See InnerException for details.

And when we check the inner exception for details…

Introducing FOREIGN KEY constraint ‘FavoriteMovieProfile_Drama’ on table ‘FavoriteMovieProfiles’ may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.

Ah, yes, that failure I was talking about.  So, here’s the deal. EF Code First doesn’t really have an elegant solution for several one-to-one mappings, or at least, not one that can be expressed with the fluent API or attributes alone. SQL Server will whine about trying to create the constraints, so we need to spoon feed it a bit.

I understand that spoon feeding in the future will be baked into EF Code First. Thankfully it’s not that big of a deal.

A Side-Step to Clean Up

Code First means that we get our data model for free, without having to create a database. The schema is implied through our object definitions, the attributes we provide, and any additional directions we throw at it through the fluent API.

For me, because I’m not using an SDF, the database was created (or at least, it was attempted to be created) in SQL Server Express, which I have running locally. We need to clean that up a bit.

While we’re about to employ a method that will clean up the database independently and automatically, we had a fail here and the metadata required to track changes was not correctly written to the database. You will need to manually delete the database at this time. If you’re looking, it’ll be named ProjectName.Models.DataContext (with appropriate nomenclature, mine was Movies.Web.Models.MoviesWebContext).

Go ahead. I’ll wait for you here to finish.

Extending our Movies Data Context

Once you remove the comments and add a little brevity to the model names, our MoviesWebContext class (found in the models folder) should look like this:

public class MoviesWebContext : DbContext
{     
public DbSet<Movie> Movies { get; set; }     
public DbSet<FavoriteMovieProfile> FavoriteMovieProfiles { get; set; }
}

We inherit from DbContext and define a couple of entity sets, each containing the models that we’ve scaffolded so far.  To this class, we’re going to override a method from our base class and put in a bit of our own helpers to get that database created more smoothly.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // …
}

In this method, we’ll add five lines like the following:

modelBuilder.Entity<FavoriteMovieProfile>()
   .HasRequired(m => m.Comedy)
   .WithMany()
   .HasForeignKey(m => m.ComedyID)
   .WillCascadeOnDelete(false);

You can see the mapping and likely get the idea. We mark the field as required and want to set up the foreign key, which requires the WithMany() call. This sets up a one-to-many relationship (which I mentioned above and will fix below) and also takes care of the cascade error with the false flag.  All five lines are as follows:

![image](http://oldblog.jameschambers.com/Media/Default/Windows-Live-Writer/MvcScaffolding-Joy-Ride-with-EF-Code-Fir_A43C/image_10.png "image")

Great, now that that’s out of the way, we have two small things to take care of: creating our own initializer and making sure it’s getting called at the appropriate time by our application.

Initializing the Database the Cool Way

Well, not so cool if you actually have real data in there, I suppose, but I digress.

What we’re going to do now is to add one more class to our application (you can just put it in the dbcontext file for now) that inherits from DropCreateDatabaseIfModelChanges. This is a class that can automatically detect changes to the schema. When it does, it proceeds to drop the DB and recreate it. In this class we override the Seed method and clean up our one-to-one mappings.

The entire class looks like this:

public class MoviesDbInitializer : DropCreateDatabaseIfModelChanges<MoviesWebContext>
{     
    protected override void Seed(MoviesWebContext context)     
    {         
    context.Database.ExecuteSqlCommand("ALTER TABLE FavoriteMovieProfiles ADD CONSTRAINT unique_Drama UNIQUE(DramaId)");
    context.Database.ExecuteSqlCommand("ALTER TABLE FavoriteMovieProfiles ADD CONSTRAINT unique_Comedy UNIQUE(ComedyId)");
    context.Database.ExecuteSqlCommand("ALTER TABLE FavoriteMovieProfiles ADD CONSTRAINT unique_HalleBerry UNIQUE(FlickWithHalleBerryId)");         
    context.Database.ExecuteSqlCommand("ALTER TABLE FavoriteMovieProfiles ADD CONSTRAINT unique_Horror UNIQUE(HorrorId)");         
    context.Database.ExecuteSqlCommand("ALTER TABLE FavoriteMovieProfiles ADD CONSTRAINT unique_SciFi UNIQUE(SciFiId)");     
    }
}

Basically, we’re just executing some SQL commands that take care of the part that EF can’t do on it’s own, creating our unique constraints.

Finally, drill into your Global.asax.ca file and add the following line of code in Application_Start():

Database.SetInitializer(new Movies.Web.Models.MoviesDbInitializer());

(You’ll also need to add System.Data.Entity to your using statements.)

Press F5 and add the /movies to your URL to play along.

image

Add a couple of movies, then switch up your url to /FavoriteMovieProfiles for kicks. When you create a new one it’ll look like this:

image

…and when you save it and return to the grid, it’ll look like this:

image

Very nice.  Only thing missing is “melo” in front of “Drama”.

Wrapping Up

This wasn’t hard at all, once we had the bits in place we needed.  We are talking about less than 30 lines of code here, and this isn’t the simplest of models. Powerful stuff.

The ASP.NET MVC Framework is getting better with each iteration as it continues to add functionality, convention and integration points with external libraries, even those from the open source community.

The addition of NuGet to our toolkit, while not yet perfect, is still a huge help and makes adding third-party resources a breeze.

The Swiss Army Knife of this trip is obviously the MvcScaffolding, which kicks out that boiler plate code that we’ve all come to be able to write in our sleep (but, obviously, it’s much more fun to have a tool do it).

And hey, I’m no tool.

To read more on this, visit:

These guys all have MVC coverage and infos on MvcScaffolding.

Cheers.