112

Is it possible to set up a .NET project with a post build event to execute a powershell script? I am using this script to generate some files.

Also can I pass whether it's a debug or release build to script. An example of this would be great.

double-beep
  • 5,031
  • 17
  • 33
  • 41
amateur
  • 43,371
  • 65
  • 192
  • 320
  • I don't have an example, but here are some links you may find useful: - https://stackoverflow.com/q/813003/402706 - https://stackoverflow.com/q/5006619/402706 - [Re: Running PowerShell from Post-Build event ignoring ExecutionPolicy](http://www.vistax64.com/powershell/205436-running-powershell-post-build-event-ignoring-executionpolicy.html) - [Creating Powershell pre-build and post-build events for Visual Studio projects](http://davidfrette.wordpress.com/2011/01/20/creating-powershell-pre-build-and-post-build-events-for-visual-studio-projects/) – Brandon Boone Jun 28 '11 at 01:12

5 Answers5

134

Here is an example :

First of all : you must be aware of the fact that PowerShell must be configure to execute scripts. The following line allow PowerShell to execute scripts :

Set-ExecutionPolicy RemoteSigned

Special mention here : if you are running a 64bits system you've got to take care of the fact that 'devenv.exe' the Visual Studio 2010 executable is a 32Bits exe, so you need to allow PowerShell 32 to execute scripts.

Once here you can go in your project properties and configure post build as shown here under (sorry in french) :

Post build in VS 2010

For example :

Example of postbuild with powershell

Here is the file 'psbuild.ps1', it creates a 'test.txt' in the target path with the configuration name inside. I put in comment different ways to debug your postbuild script (message box, sound, message on the output)

param ([string]$config, [string]$target)

#[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#[void][System.Windows.Forms.MessageBox]::Show("It works.")
#[Console]::Beep(600, 800)
#Write-Host 'coucou'
set-content $target -Value $config -Force
Peter Oehlert
  • 16,368
  • 6
  • 44
  • 48
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • 10
    Good answer. I would only add that you should not set the execution policy to unrestricted, but to remotesigned instead. Unrestricted lets any script execute, whereas remotesigned requires downloaded scripts to be signed with a trusted key. – beefarino Jun 28 '11 at 16:18
  • 2
    Hum do you test to download a .PS1 file on an Fat32 drive or tu use basic cmdline FTP to download a .PS1 file with "remotesigned" ? isn't it a kind of "smoky security" ? – JPBlanc Jun 29 '11 at 07:12
  • 4
    +1 for the special mention for 64bit systems - I was going mad until I read I also needed to allow execution in the 32bit PowerShell. Thanks! – Guðmundur H Nov 30 '12 at 08:00
  • unfortunatelly there is no image files: http://i.stack.imgur.com/gZoPi.png http://i.stack.imgur.com/VTIRW.png – Andrzej Martyna Oct 25 '13 at 07:31
  • Sorry but images are still there for me. – JPBlanc Oct 25 '13 at 09:47
  • 8
    If you use: c:\windows\sysnative\windowspowershell\v1.0\powershell.exe for the path, the 64 bit version of powershell will be invoked. %systemroot%\sysnative is a special alias to tell the redirector to stop redirecting, and allow real access to %systemroot%\system32. – Peter Oehlert Jul 05 '14 at 02:17
  • @Peter Oehlert You are right a good abstract is given [here](http://stackoverflow.com/a/10788092/608772) – JPBlanc Jul 05 '14 at 07:00
  • 1
    @Peter Oehlert - It should be noted that c:\windows\sysnative ONLY works from 32-bit processes. When building from a 64-bit command prompt w/ 64-bit MSBuild (as might be the case with a build server), that alias won't exist. – Joe the Coder Dec 10 '16 at 23:57
  • You can get your PS directory by running the $pshome command in Powershell – Danielh Jun 02 '21 at 06:35
20

command Set-ExecutePolicy will temporarily set execution policy under current session. If you set this in powershell and run post build command in vs you will still get not allowed. So set first then run your ps1 script like bellow

powershell -ExecutionPolicy Unrestricted $(ProjectDir)Deploy.ps1 -ProjectDir $(ProjectDir) -TargetPath $(TargetPath)
Ariwibawa
  • 627
  • 11
  • 23
15

Instead of messing with system-wide settings and having to differentiate between 32 and 64-bit environments, a much easier and more reliable approach is to specify the ExecutionPolicy in the call to PowerShell, as follows:

C:\Users\xyz>PowerShell -ExecutionPolicy Unrestricted

PS C:\Users\xyz> Get-ExecutionPolicy
Unrestricted

PS C:\Users\xyz> exit

C:\Users\xyz>PowerShell -ExecutionPolicy RemoteSigned

PS C:\Users\xyz> Get-ExecutionPolicy
RemoteSigned

Note in the above code how calling Get-ExecutionPolicy tells you the current mode. Also note how this mode is specified in the call to PowerShell itself, which can be combined with a script filename:

test.ps1 contents:

echo ('The current policy is ' + (Get-ExecutionPolicy)).ToString()

Calling test.ps1 with Unrestricted policy on a system having scripts disabled:

C:\Users\xyz>PowerShell -ExecutionPolicy Unrestricted -file test.ps1
The current policy is Unrestricted

Also note that the above call does not require admin rights, so it can be called in Visual Studio's Pre-Build Step or similar.

Michael
  • 2,268
  • 20
  • 24
12

Before calling power-shell script from visual studio, set the ExecutionPolicy to RemoteSigned from power-shell window like this...

Set-ExecutionPolicy -Scope CurrentUser;
ExecutionPolicy: RemoteSigned;

then call powershell script in the following manner...

(no need to pass full "powershell.exe" file path)

powershell.exe $(SolutionDir)Setup.ps1 -SolutionDir $(SolutionDir) -ProjectPath $(ProjectPath)

enter image description here

then in the script, you can always read the parameter like this...

param([string]$SolutionDir,
     [string]$ProjectPath);
#Write-Host ($SolutionDir +" Call this script with following aruments");
#Write-Host ($ProjectPath +" Call this script with following aruments");
orad
  • 15,272
  • 23
  • 77
  • 113
Narottam Goyal
  • 3,534
  • 27
  • 26
10

I made it with below command in post-build even command:

PowerShell -NoProfile -ExecutionPolicy unrestricted -file $(SolutionDir)AutomationScript\DBAutomationScript.ps1 -target $(SolutionDir)MUFG.SECMOD.Data\SqlScripts -generatedFileName $(SolutionDir)MUFG.SECMOD.Data\SqlScripts\DeploymentDBScript.sql

DBAutomationScript.ps1 contents:

param ([string]$target, [string]$generatedFileName)
jnm
  • 101
  • 1
  • 2