Windows PowerShell
Contents
PowerShell prebuild and postbuild scripts for Visual Studio projects
Tested with VS2015.
How
- Prepare (the macro list and) the ps1 boilerplate and event command line as directed below.
- Alternatively, try (at your own risk) the examples already prepared from my own configuration.
- Create
prebuild.ps1
andpostbuild.ps1
in the top level of the project and paste the ps1 boilerplate into each. - Go to the Properties of the project and open the Build Events tab.
- Click Edit Pre-build… and paste the pre-build event command line into the field. Replace
pxxbuild
withprebuild
. Confirm. - Click Edit Post-build… and paste the post-build event command line into the field. Replace
pxxbuild
withpostbuild
. Confirm.
- Click Edit Pre-build… and paste the pre-build event command line into the field. Replace
Finally, add scripting after the boilerplate in prebuild.ps1
and postbuild.ps1
as necessary. This saves some serious acrobatics later on when some actual processing has to happen in the event.
Prepare the macro list
- Go to the Properties of the project and open the Build Events tab.
- Click Edit Pre-build… (which opens the pre-build event command line for editing).
- In a text editor (or spreadsheet), create a list of all of the names seen in the Macro column of the macro list in the dialog.
There appears to be no way to directly copy this table. For your sanity, I've included the list from my setup below.
Prepare the ps1 boilerplate
The ps1 boilerplate is a param
list that makes it possible to pass all macros to the script by name and enable the rest of the file to refer to the macro values as variables.
Convert a copy of the macro name list into a ps1 boilerplate script by making the following changes:
- Prefix each line with
[string]$
and suffix each line except the last with,
.- Using a spreadsheet: Create a blank spreadsheet. Paste the macro names in column A. In B1, enter the formula
="[string]$" & A1 & ","
, then fill down to the rest of column B. Select the generated column B values, copy, and paste them into a plain text editor. Manually delete the comma at the end of the last line. - Using vim: Enter the command
:%s/\v(.*)/[string]$\1,/g
, then delete the comma at the end of the last line.
- Using a spreadsheet: Create a blank spreadsheet. Paste the macro names in column A. In B1, enter the formula
- Enter the line
param (
above the list. - Enter the line
)
below the list. - Indent as desired.
Prepare the event command line
The event command line is the command called by Visual Studio for the pre- and post-build commands. This generated command line in particular passes the values of all of the macros as named parameters.
Convert a copy of the macro name list into the event command line by making the following changes:
- Replace each line
NAME
with-NAME $('NAME')
.- Using a spreadsheet: Create a blank spreadsheet. Paste the macro names in column A. In B1, enter the formula
="-" & A1 & " $('" & A1 & "')"
, then fill down to the rest of column B. Select the generated column B values, copy, and paste them into a plain text editor. - Using vim: Enter the command
:%s/\v(.*)/-\1 $('\1')/g
.
- Using a spreadsheet: Create a blank spreadsheet. Paste the macro names in column A. In B1, enter the formula
- Enter the line
powershell -ExecutionPolicy ByPass "&'$(ProjectDir)pxxbuild.ps1'"
above the list. - Replace all newlines with a single space.
- Using a spreadsheet and Notepad: Create a blank spreadsheet. Paste the lines into column A (if the lines were copied from another spreadsheet, use Paste Values Only to avoid copying formulas). Re-copy the lines from A, then paste the transpose (usually under Paste Special) at B1. Select the cells that have been populated (B1, C1, etc.) and copy into Notepad. In the text that has just been pasted, select a tab character and copy it. Using the Replace… function, paste the tab character into Find what: and type a space in Replace with:. Run Replace All.
- Using Windows-native gvim: Enter the command
:%s/\n/ /g
- Using Visual Studio text editor: Create a new text file in Visual Studio. (This is temporary and should not be associated with the project or solution.) Paste the lines. Open Quick Replace for the current document. Use
\r\n
for the search term and
For my configuration
Macro list
ConfigurationName DevEnvDir OutDir PlatformName ProjectDir ProjectExt ProjectFileName ProjectName ProjectPath SolutionDir SolutionExt SolutionFileName SolutionName SolutionPath TargetDir TargetExt TargetFileName TargetName
Event command line
Substitute pre
or post
for pxx
.
powershell -ExecutionPolicy ByPass "&'$(ProjectDir)pxxbuild.ps1'" -ConfigurationName '$(ConfigurationName)' -DevEnvDir '$(DevEnvDir)' -OutDir '$(OutDir)' -PlatformName '$(PlatformName)' -ProjectDir '$(ProjectDir)' -ProjectExt '$(ProjectExt)' -ProjectFileName '$(ProjectFileName)' -ProjectName '$(ProjectName)' -ProjectPath '$(ProjectPath)' -SolutionDir '$(SolutionDir)' -SolutionExt '$(SolutionExt)' -SolutionFileName '$(SolutionFileName)' -SolutionName '$(SolutionName)' -SolutionPath '$(SolutionPath)' -TargetDir '$(TargetDir)' -TargetExt '$(TargetExt)' -TargetFileName '$(TargetFileName)' -TargetName '$(TargetName)'
ps1 Boilerplate
param (
[string]$ConfigurationName,
[string]$DevEnvDir,
[string]$OutDir,
[string]$PlatformName,
[string]$ProjectDir,
[string]$ProjectExt,
[string]$ProjectFileName,
[string]$ProjectName,
[string]$ProjectPath,
[string]$SolutionDir,
[string]$SolutionExt,
[string]$SolutionFileName,
[string]$SolutionName,
[string]$SolutionPath,
[string]$TargetDir,
[string]$TargetExt,
[string]$TargetFileName,
[string]$TargetName
)
PSModulePath
PowerShell's search path for the Import-Module command is in the PSModulePath
env var:
echo $env:PSModulePath
By default on one system it seems to be
- a user modules dir at
My Documents\WindowsPowerShell\Modules
- a global modules dir at
system32\WindowsPowerShell\v1.0\Modules\
PowerShell Community Extensions (pscx)
Get it from http://pscx.codeplex.com/. The directory structure in the ZIP file needs to be such that the path to Pscx.psm1
is
Modules/Pscx/Pscx.psm1
where Modules is one of the directories in $env:PSModulePath
.