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.
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) :
For example :
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
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)
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.
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)
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");
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)
Related
When I tried to create dispatch-Model for my bot., I am getting following error - 'dispatch' is not recognized as an internal or external command, operable program or batch file.Before using dispatch command, I installed botdispatch using npm install -g botdispatch. But still I am getting this error.
Can you check your NPM folder to see if there is anything with dispatch there? Assuming you're on Windows, this is typically in AppData\Roaming\npm.
PowerShell:
dir $home\AppData\Roaming\npm
CMD:
dir %homepath%\AppData\Roaming\npm.
If dispatch (dispatch.cmd) is there, then it might be a pathing issue. Check your path variables to make sure that that path is there:
CMD:
echo %path%
PowerShell:
($env:path).Split(';')
So I was having this same issue, it turns out I needed to add the path of the NPM folder C:\Users\xxxxxx\AppData\Roaming\npm to my path for Powershell7.
$env:Path += ";C:\Users\xxxxxx\AppData\Roaming\npm"
Where xxxxxx is your userid. After adding this command to Powershell the npm modules began to work.
If you do not see this path by running this command below, then you need to add it with the one above.
($env:path).Split(';')
All of these should be ran inside of a PS7 window, I ran them with Administrator rights when I launched the Powershell 7 window.
I am running PowerShell Scripts from a C# Tool like this:
using (PowerShell pshell = PowerShell.Create())
{
pshell.AddCommand(scriptFullPath);
pshell.AddParameter("username", user);
pshell.AddParameter("password", pass);
PSDataCollection<PSObject> outputCollection = new PSDataCollection<PSObject>();
PSInvocationSettings settings = new PSInvocationSettings();
settings.ErrorActionPreference = ActionPreference.Stop;
pshell.Invoke(null, outputCollection, settings);
}
Almost everything works fine in the Script until I need special Cmdlets from other Assemblies. The Add-PSSnapin Command will always fail with:
Exception: The Windows PowerShell snap-in 'Microsoft.SharePoint.Powershell' is not installed on this computer.
Exception: Cannot bind parameter 'Path' to the target. Exception setting "Path": "Cannot find path 'D:\dev\tool\Microsoft.SharePoint.dll' because it does not exist."
when running
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq "Microsoft.SharePoint.Powershell"}
if ($snapin -eq $null)
{
Write-Host "Loading SharePoint Powershell Snapin"
Add-PSSnapin "Microsoft.SharePoint.Powershell"
Add-Type -Path "Microsoft.SharePoint.dll"
Add-Type -Path "Microsoft.SharePoint.Runtime.dll"
}
Everything works fine when running the Script directly in a PowerShell window, so I guess it has something to do with the PATH or Scope that is not forwarded from the C# Tool. Playing around with the Parameter useLocalScope of AddCommand or other Parameters did not yield any results (although I am not sure if this has anything to do with paths).
How can I make the Script work and find external Assemblies?
The SharePoint PowerShell snapin is available in 64bit only. Your C# tool may be running as an x86 process, and therefore would give you the error "not installed". Also you may have to run the program "as Administrator" as some of the commands need that to work.
The second error is, you're right, that there is no PATH variable set for SharePoint by default. The workaround is to specify the full path to the .dll, (and changing the version number for your install) e.g.
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.dll"
We're using System.Management.Automation.PowerShell for executing PowerShell scripts.
Everything worked fine for many scenarios until we need to set some properties of a web site on IIS (ServerAutostart etc.).
We made a PS1 script which works as we expected, however, after execution via C#, it crashes. After some exploration, I extracted the problematic part:
PS1 script:
# Set execution policy
Set-ExecutionPolicy Unrestricted -Scope Process -Force
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force
Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
# Import modules
Import-Module WebAdministration
Import-Module IISAdministration -MinimumVersion 1.1.0.0
# Getting IIS Sites
$iisSite = Get-IISSite
If ($iisSite)
{
Write-Host "$($iisSite.Count) IISSites were found"
}
else
{
Write-Error "IISSite was not found"
}
$webSite = Get-Website
# Getting Web Sites
If ($webSite)
{
Write-Host "$($webSite.Count) WebSites were found"
}
else
{
Write-Error "WebSites was not found"
}
If I run it via Windows PowerShell ISE, it works perfectly:
23 IISSites were found
23 WebSites were found
However, if the script is executed via C# and System.Management.Automation.PowerShell, it returns following:
23 IISSites were found
WebSites was not found
What is the difference? Why Get-IISSite works and Get-Website not? Permissions? Missing modules?
To set WebSite properties, we need to work with it via Get-WebSite. Unfortunately, it seems to be a conceptual problem...
Thank you for your help...
Problem was caused by prefering 32-bit mode in the Build tab in 64-bit system.
Prefering 32-bit mode
After uncheck, everything works well.
see Powershell Invoke method neither throwing exception nor returning result
I am getting following error when trying to build the solution.
Error The command "
copy "D:\Code\..\libs\xyz_ext.x64.dll" "D:\Code\bin\"
copy "D:\Code\..\libs\xyz.x86.dll" "D:\Code\bin\"
" exited with code 1. C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets 4714
MSBuild exited with code 1 error
First, just as nozzleman comment "is this the real command (including ..) from the post build event" If yes, this is the reason why you got this error. That because build events follow the same syntax as DOS commands, and DOS never supported wildcard * expansion and \..\ in the path by the shell. So you should specify the full path in the command line.
Besides, if you want to copy the file in all the subfolders of Code, you need some way using existing windows tools (cmd.exe), or powershell with wildcard *, for example, powershell:
This is code in the .ps1 file:
Get-ChildItem "D:\Code\*\libs" -Recurse -Include xyz_ext.x64.dll | Copy-Item -Destination D:\Code\bin
Then execute this PS script by post build event:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file D:\Code\Test.ps1
If \..\ is nor the real command from the post build event, just a shorthand expression. You should check the path of this command. According to the error log "code 1 error", it specify that this command is incorrect. And I have checked this command, the syntax of copy is correct, so the problem is the path is not incorrect, you should double check it.
I have an automation issue that I've tracked down to the following situation:
The PS script is being loaded via process.start in a C# program. If I run the script in the ISE, it runs fine. When running via process.start, it fails on the command:
Add-PSSnapin 'Microsoft.SharePoint.PowerShell'
With the error:
Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 4.
The command I'm using for process.start in .net is:
var Arguments #"-version 4.0 -ExecutionPolicy Bypass -noexit -file """ + filePath + #""" -XmlString """ + args + #""" -Verb RunAs"
var FileName = "powershell.exe"
var process = Process.Start(FileName, Arguments);
filePath is the path to the powershell script that is being executed.
This runs and attempts to run the script, but fails on the command shown above inside the script. The user account is the admin service account for the machine. The issue seems to be in how the .Net program is starting PowerShell, as I can run this script and these commands via the ISE and console if I do it manually (under the same service account). I just can't seem to find some combination of tricks to get the .Net program to be able to execute the PowerShell script under the correct profile, I guess.
Any thoughts?
PetSerAl's request was spot-on... when running the PowerShell script via the .Net program, it was running under x86, but when running it via ISE, it was running in x64. I re-compiled the .Net program against x64 and everything now works.
Thanks for the advice!