deploy tools: get a list of actions the tool will execute without executing the deploy script - deployment

We're in the process of evaluating MSBuild and Nant for deploys. We may roll our own tool. One thing that a different business unit -- let's call it DeptA -- would really like to have (as in it better have it) is the ability for someone in DeptA to read the script and see what it will do. Currently we do this with .bat files. We hates the bat files. Nasty nasty bat files's. But if we ask DeptA to learn a new script language (nant, msbuild) they may be resistant.
Ideally the build tool of choice would be able kick out a list of actions without doing anything else. Along the lines of:
Stop service ABC on server Z
Stop service DEF on server Z
Copy all files from
\server\dirA\dirB to \server2\dirC
Start service ABC on server Z
Start service DEF on server Z
Run all scripts in dir
\server\dirA\dirC
Is it possible to do this with MSBuild? NAnt? Without me re-learning XSL?

If I was you I would actually blend MSBuild and MSDeploy. You should have your MSBuild script perform the actions like start/stop service etc. Then let MSDeploy to the file copy. With MSDeploy you can use the -whatif switch to indicate that you only want a report of the actions to be executed instead of actually executing it. MSBuild unfortunately doesn't offer such an option out of the box you will have to "build" that into your scripts. You can do this with properties and conditions. For example it might look something like this:
<Project ...>
<PropertyGroup>
<!--
Create the property to use, and declare a default value.
Here I've defaulted this to true because it is better to force the
caller to explicitly specify when to perform the action instead of it
being the default.
-->
<SimulateExecution Condition= '$(SimulateExecution)'==''>true</SimulateExecution>
</PropertyGroup>
<Target Name="Deploy">
<Message Text="Deploy started" />
<Message Text="Stop service ABC on server Z"/>
<WindowsService ... Condition=" '$(SimulateExecution)'=='false' "/>
<Message Text="Stop service DEF on server Z"/>
<WindowsService ... Condition=" '$(SimulateExecution)'=='false' "/>
<!-- Call MSDeploy with the Exec task. -->
<PropertyGroup>
<MSDeployCommand>...\msdeploy.exe YOUR_OPTIONS_HERE</MSDeployCommand>
<!-- Append the -whatif to the command if this is just a simulation -->
<MSDeployCommand Condition= '$(SimulateExecution)'=='false' ">$(MSDeployCommand) -whatif</MSDeployCommand>
</PropertyGroup>
<Exec Command="$(MSDeployCommand)" />
... More things here
</Target>
</Project>
For the service actions you can use the WindowsService task from the MSBuild Extension Pack. You will have to fill in the blanks there.
When you call MSDeploy you should just use the Exec task to invoke msdeploy.exe with your parameters. If you pass the -whatif it will not actually perform the actions, just report what it would have done. These will be logged to the msbuild log. So if you invoke msbuild.exe with /fl you will get those actions written out to a file. The only issue that I've seen when taking this approach is that for msdeploy.exe you many times have to use full paths (those without ..) which can sometimes be tricky so be wary of such paths.

Related

Run a powershell script inside a windows service

I have a powershell script running very well ,
I'm calling this script within a power shelle command line :
PS C:> .\myscript.ps1 -var1 variable1 -var2 variable2
I need to mount this inside a service with a stupid sc create but i couldn't find a way to launch it
any help please ?
Thanks a lot.
Use Windows service wrapper. It's highly configurable and provides a lot of useful options, like log rotation, service account, on failure actions and so on. It even can automatically download resources from URL and place it locally as a file, so you can host your script somewhere and have it auto updated. Here is the basic steps to get your PowerShell service up and running:
Download\build winsw. Version 1.x binaries can be found here. To build latest winsw 2.x use Visual Studio Community 2013 (free for open-source projects). More detailed build instructions are here.
Create XML configuration file for your service. Example:
<service>
<id>MyPsSvc</id>
<name>My PowerShell Service</name>
<description>Does funny stuff with your PC</description>
<executable>PowerShell.exe</executable>
<logmode>reset</logmode>
<arguments>-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -File "myscript.ps1" -var1 variable1 -var2 variable2</arguments>
</service>
The configuration file must have the same basename as winsw executable, i.e.:
winsw.exe
winsw.xml
If you plan to use your service on the PC without internet connection, disable digital signature verification for winsw. To do this create file winsw.exe.config. Example:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
If you're running Windows Server 2012 or Windows 8 and and don't want to install .Net 2.0 support, specify .NET 4.0 runtime support in the abovementioned config file:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
<startup>
<supportedRuntime version="v2.0.50727" />
<supportedRuntime version="v4.0" />
</startup>
</configuration>
Install your service, running winsw.exe install from command line. Once the service is installed, you can start it from Windows service manager.

In MsBuild, how do I run something PowerShell and have all errors reported [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Any good PowerShell MSBuild tasks?
Powershell doesn't seem to have an easy way to trigger it with an arbitrary command and then bubble up parse and execution errors in a way that correctly interoperates with callers that are not PowerShell - e.g., cmd.exe, TeamCity etc.
My question is simple. What's the best way for me with OOTB MSBuild v4 and PowerShell v3 (open to suggestions-wouldnt rule out a suitably production ready MSBuild Task, but it would need to be a bit stronger than suggesting "it's easy - taking the PowerShell Task Factory sample and tweak it and/or becoming it's maintainer/parent") to run a command (either a small script segment, or (most commonly) an invocation of a .ps1 script.
I'm thinking it should be something normal like:
<Exec
IgnoreStandardErrorWarningFormat="true"
Command="PowerShell "$(ThingToDo)"" />
That sadly doesn't work:-
if ThingToDo fails to parse, it fails silently
if ThingToDo is a script invocation that doesn't exist, it fails
if you want to propagate an ERRORLEVEL based .cmd result, it gets hairy
if you want to embed " quotes in the ThingToDo, it won't work
So, what is the bullet proof way of running PowerShell from MSBuild supposed to be? Is there something I can PsGet to make everything OK?
You can use the following example:
<InvokeScript Condition="..."
PowerShellProperties="..."
ScriptFile="[PATH TO PS1 FILE]"
Function="[FUNCTION TO CALL IN PS1]"
Parameters="..."
RequiredOutputParams="...">
<!-- You can catch the output in an Item -->
<Output TaskParameter="OutputResults"
ItemName="Output" />
</InvokeScript>
This can be used in MSBuild.
Weeeeelll, you could use something long winded like this until you find a better way:-
<PropertyGroup>
<__PsInvokeCommand>powershell "Invoke-Command</__PsInvokeCommand>
<__BlockBegin>-ScriptBlock { $errorActionPreference='Stop';</__BlockBegin>
<__BlockEnd>; exit $LASTEXITCODE }</__BlockEnd>
<_PsCmdStart>$(__PsInvokeCommand) $(__BlockBegin)</PsCmdStart>
<_PsCmdEnd>$(__BlockEnd)"</PsCmdEnd>
</PropertyGroup>
And then 'all' you need to do is:
<Exec
IgnoreStandardErrorWarningFormat="true"
Command="$(_PsCmdStart)$(ThingToDo)$(_PsCmdEnd)" />
The single redeeming feature of this (other than trapping all error types I could think of), is that it works OOTB with any PowerShell version and any MSBuild version.
I'll get my coat.

Phing exec command to set environment variable

I'm trying to set an environment variable in a build script with phing.
This is normally done command line like this:
export MY_VAR=value
In Phing I did the following but it isn't working.
<exec command="export MY_VAR=value" />
I see that this is quite an old question, but I don't think it has been answered in the best way. If you wish to export a shell variable, for example say you are running phpunit from phing and want to do an export before invoking phpunit, try:
<exec command="export MY_VAR=value ; /path/to/phpunit" />
Simply do the export and invoke your command inside the same exec tag. Separate the export statement and the shell executable with a semicolon as shown. Your script will be able to access the value using the standard php function:
$myVar = getenv('MY_VAR');
Bold claim: There is no way to set/export a (Unix) shell variable in PHP so that it is visible inside the scope that started the php script.
php myfile.php (does putenv or shell_exec('export foo=bar');)
echo $foo
Will return nothing.
As PHP can not do it so neither can phing.
Accessing shell environment variables accross multiple script runs (if its that what you want) seems also like an unideal design decision, pretty stateful.
Apart from that I'd urge you to stick to phing and learn its lean lesson. Phing helps stateless thinking to some degree.
I'd never heard of phing before, but this looks very promising as a build tool. Thanks for posting! I looked through the doc on phing.info, I found the following possibility:
#0 I would like to clarify one point. Are you saying that
prompt$ > export MY_VAR=value
prompt$ > phing build.xml
doesn't set MY_VAR to value so it is visible inside the running phing processes? I'd be surprised, but I would understand if this is not how you want to run your build script.
#1 I think in the context of a build tool, a feature like exec is meant to run a stand-alone program, so, while the exec may run and set MY_VAR, this is all happening in a subprocess that disappears immediately as the exec finishes and continues processing the next task in the build.xml.
If you're just trying to ensure that your phing script runs with specific values for env_vars, you could try
Command-line arguments:
....
-D<property>=<value>
// Set the property to the specified value to be used in the buildfile
So presumably, you can do
phing -DMY_VAR=value build.xml
#2 did you consider using a properites file?
See http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixF-FileFormats.html
and scroll down for info on build.properties
#3 also ...
Phing Built-In Properties
Property Contents
env.* Environment variables, extracted from $_SERVER.
you would access them with something like
${env.MY_VAR}
#4 This looks closer to what you really want
<replacetokens>
<token key="BC_PATH" value="${top.builddir}/"/>
<token key="BC_PATH_USER" value="${top.builddir}/testsite/user/${lang}/"/>
</replacetokens>
I hope this helps.

Exception running powershell script from MSBuild Exec Task

i´m having a problem with MSBuild and Powershell. There is a PS-script that i want to execute within the MSBuild exec-Task.
The Problem: Running the Script direct from CMD works, but running the script within MSBuild I get an error.
Here the MSBuild script:
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<PathToSvnClient>C:\Program Files (x86)\CollabNet\Subversion Client</PathToSvnClient>
</PropertyGroup>
<ItemGroup>
<!-- set Folder to Svn Repository for svn info command-->
<SvnFolder Include="$(MSBuildProjectDirectory)\.."/>
</ItemGroup>
<Target Name="SvnInfo">
<!-- get SVN Revision and Repository Path -->
<SvnInfo LocalPath="%(SvnFolder.FullPath)" ToolPath="$(PathToSvnClient)">
<Output TaskParameter="Revision" PropertyName="Revision" />
<Output TaskParameter="RepositoryPath" PropertyName="RepositoryPath" />
</SvnInfo>
</Target>
<Target Name="SetProductVersion" DependsOnTargets="SvnInfo">
<Exec Command="powershell -file "Scripts\SetSth.ps1" -PARAM "$(PathToSth)" -SVNID $(Revision) -SVNFOLDER "$(RepositoryPath)"" LogStandardErrorAsError="true" ContinueOnError="false"/>
</Target>
The Command is executed exactly the same way as on CMD, but i get an exception from the Powershell Script for the SVNFOLDER param.
The Command that is executed looks like this:
powershell -file "Scripts\SetSth.ps1" -PARAM "C:\abc\cde" -SVNID 1234
-SVNFOLDER "https://domain/svn/rep/branches/xy%20(Build%2012)"
So from CMD it works, from within MSBuild not. I have no idea why. I hope you got an idea.
What about this approach playing with double and singles quotes:
<Target Name="SetProductVersion" DependsOnTargets="SvnInfo">
<Exec Command="powershell -command "& {Scripts\SetSth.ps1 -PARAM '$(PathToSth)' -SVNID '$(Revision)' -SVNFOLDER '$(RepositoryPath)'}"" LogStandardErrorAsError="true" ContinueOnError="false"/>
</Target>
Double check your paths.
Remember, powershell invoked in this way runs as Msbuild.exe under whatever user is executing the build. To msbuild.exe, a straight call to cmd.exe is going to start in the working directory where msbuild lives.
Assume -file "Scripts\SetSth.ps1" references C:\users\yourusername\Scripts\SetSth.ps1
So for you, calling cmd.exe and running that may work just fine, b/c your working directory is going to match C:\users\yourusername
For msbuild.exe, its likely unable to find that file, as its starting in something like *C:\Windows\Microsoft.NET\Framework\v4.0*
So it's looking for C:\Windows\Microsoft.NET\Framework\v4.0\Scripts\SetSth.ps1
I would try making that file path fully qualified. If that still doesn't work, have cmd.exe dump its results into a property and have msbuild log it. Then you can review the paths.

How do I use internal commands (Command.com) from NAnt? ("type" etc)

On windows systems, certain dos commands don't have executables that can be explicitly called via NAnt's exec task. (I'm talking specifically about commands that are part of Command.com)
A complete list can be found here. While some of the more useful commands can be achieved with NAnt or NAntContrib tasks (copy, move, rename etc), some (such as 'type') cannot.
How can you execute these commands as part of a build? For example, using a wildcard, how can I easliy display the contents of a log file from an external command executed by my build (so that the external command's log file contents will become echoed into the build's log file)
Internal commands can be called using the exec task in the following manner :
<exec workingdir="${dir}" program="cmd" commandline="/c <command/> <arguments/>" />
For the scenario in the question (where the log's filename is based on the current time, partway through the build), rather than parsing/scanning for the filename, loading it into a property and then echoing it, you could echo log contents with the following task :
<exec program="cmd" workingdir="${dir}" commandline="/c type *.log" />