Creating Powershell pre-build and post-build events for Visual Studio projects

I had a need to create a cab file containing the files from two project folders, plus a file at the root. Instead of learning Visual Studio addins, I created a PowerShell script that ran on Visual Studio’s pre-build event.  Using the post-build would have meant that the cab file was created after the SharePoint wsp package. The pre-build event is the way to go here.  So, first thing I did was create a PowerShell script that in turn, created a cab file. This script makes use of the makecab utility that ships with Visual Studio. To create a cab with this utility, one needs a Diamon Directive File, or ddf. This file contains a set of instructions followed by a list of files.  I’ll post the script at the end of this article, but it’s not really my focus. What really got me tripped up was (1) getting powershell to run and (2) getting parameters into the script correctly – as it turns out, a space makes a difference!  Here are the steps:

First, to do this, you’ll need PowerShell v2 (or better). Version 2 contains the -File cmdlet, which lets you run a script (*.ps1 file) from a powershell prompt. If you run Windows Server 2008 R2, then you have PowerShell v2. Otherwise, you may need to download it.

 Second, you’ll need to set the execution policy. Assuming you are on a dev box (Visual Studio and all), you can set the execution policy to unrestricted, via set-executionpolicy unrestricted. To check your current policy, use get-executionpolicy.

Third, keep in mind Visual Studio is 32-bit, while powershell has both, 32 and 64-bit versions with their own policies. The 32-bit VS should call the 32-bit version of PowerShell. Here is a screenshot showing the different powershell prompts and different execution policies.

Fourth, here is my script that will render arguments to the console. Yep, that’s all it needs to do.

Finally, the passing of parameters from Visual Studio is quirky. When I used “($ProjectDir)” “($ProjectDir)\bin”  Visual Studio passed that to PowerShell as one parameter. When I added a space  “($ProjectDir) ” “($ProjectDir)\bin”  Visual Studio passed that as 2 parameters. Here are the screenshots.

Finally, here is the script that will make the cab file. It’s all about making the ddf file. Enjoy!!

Note: If changing the execution policy at a powershell prompt does not seem to work (ie, Visual Studio still returns an error such as:

------ Rebuild All started: Project: SPProject, Configuration: Debug Any CPU ------

Compile complete -- 0 errors, 1 warnings
  File C:\MakeHCCab.ps1 cannot be loaded because the execution of scripts is disabled
  on this system. Please see "get-help about_signing" for more details.
      + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordE
      + FullyQualifiedErrorId : RuntimeException

 then you can use

powershell -command "set-executionpolicy unrestricted" 

in the prebuild event before the -file command.


9 responses to “Creating Powershell pre-build and post-build events for Visual Studio projects”

  1. Dale Smith says :

    Found this blog post via Google. I am using VS 10.0.40219.1 SP1Rel. I didn’t use quotes around my arguments to my Powershell. I used

    Powershell -File “$(ProjectDir)scriptName.ps1” $(ProjectDir) $(SolutionName)

    Everything works fine, in fact, including quotes and the space just didn’t work properly. Perhaps there was a service pack that affected this?

  2. Jan David Narkiewicz says :

    I should have thought 32-bit for the execution policy! if it were a snake it would have bit me (to quote Buckaroo Banzia). You saved me time. Thank you muchly.

    But… In the prebuild event, how do you detect an error? To quote you — the following is an error but Visual Studio simply builds on merrily:
    File C:\MakeHCCab.ps1 cannot be loaded because the execution of scripts is disabled
    on this system. Please see “get-help about_signing” for more details.
    + CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordE
    + FullyQualifiedErrorId : RuntimeException

    Just food for thought…

  3. Gil says :

    Not sure if you’ve figured this out, but I ran into the same problem with quoted parameters being sent to powershell this week, particularly $(ProjectDir). In case others find this blog like I did in trying to find a solution I thought I’d explain what’s really happening and how to fix it. The reason what you described above happens is because $(ProjectDir) ends with a backslash (ex: …\SampleProject\), which is escaping the quote, thus the quote becomes part of your parameter. Notice in your first example how the first part ends SampleProject” instead of SampleProject\”. Now, why powershell isn’t complaining about mismatched quotes I don’t know. Anyway, what you’d have to do, instead of adding a space (which will add a space to $arg[0] that you’d have to trim) is to use “$(ProjectDir)\”. This way it will become “…\SampleProject\\” which will then become …\SampleProject\ without a trailing quote. Your ‘bin’ argument doesn’t need anything since it doesn’t end with a \.

  4. JanH says :

    Thanks for your post. Your comment about 32 bit PowerShell resolved my problem. I had all the right settings in 64 bit mode but did not understand why Visual Studio did not want to execute the script.

    I found that execution policy RemoteSigned is already enough if the PowerShell script is created locally, signed, or downloaded but unblocked.

  5. ozbob says :

    still useful in VS2013 thx

  6. BuildEvent says :

    Thank you, man!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: