How to execute powershell script from FAKE - F # MAKE
I am porting MSBuild code to FAKE - and I cannot execute powershell script from fake, below is the MSBuild file code written in FAKE:
<Target Name="VersionConfig">
<Exec IgnoreExitCode="false" LogStandardErrorAsError="true" StandardErrorImportance="high" Command="powershell -File "$(BuildRoot)\DeployScripts\scripts\AdminScripts\VersionUpdateFile.ps1" -path "$(BuildSolutionVersioningConfig)" -majorVersion "$(BuildNumberMajor)" -minor "$(BuildNumberMinor)" -build "$(BuildNumber)" -revision "$(BuildNumberRevision)""/>
</Target>
How to write this in FAKE, I'm new to FAKE and haven't used F # much, so forgive me if it's obvious.
If anyone can help it would be really helpful.
Thank.
source to share
Fake.ProcessHelper
namespace in FAKE is what you are looking for. The documentation will not tell you this, but is Fake.ProcessHelper
tagged with an attributeAutoOpen
, which means that all the functions listed in this API man page link are available to you from your FAKE script build without requiring any explicit instructions open
to use them. You use it like this:
let inQuotes s = sprintf "\"%s\"" s
Target "Sample" (fun _ ->
let retCode =
ExecProcess
(fun info ->
info.Name <- "powershell.exe" // Don't know if you need full path here
info.WorkingDirectory <- getBuildParam "BuildRoot"
info.Arguments <-
[ "-File"; getBuildParam "BuildRoot" + "\DeployScripts\scripts\AdminScripts\VersionUpdateFile.ps1" |> inQuotes;
"-path"; getBuildParam "BuildSolutionVersioningConfig" |> inQuotes;
"-majorVersion"; getBuildParam "BuildNumberMajor" |> inQuotes;
"-minor"; getBuildParam "BuildNumberMinor" |> inQuotes;
"-build"; getBuildParam "BuildNumber" |> inQuotes;
"-revision"; getBuildParam "BuildNumberRevision" |> inQuotes
] |> separated " "
)
(TimeSpan.FromMinutes 5.0)
if retCode <> 0 then
failwith (sprintf "PowerShell exited with non-zero exit code %d" retCode)
)
A few notes:
- Notice how I declared a custom helper function
inQuotes
to make the list lookinfo.Arguments
nicer. - More information on the function
separated
I was using . - More information on the function
getBuildParam
I was using .
source to share
You can create a Powershell pipeline in any .NET application with the System.Management.Automation namespace classes . You can use this pipeline to execute commands locally or on a remote machine.
The next object gets a list of processes and prints them. This is the F # equivalent of the sample documentation for the PowerShell class:
Target "ProcTest" (fun _ ->
PowerShell.Create()
.AddCommand("get-process")
.Invoke()
|> Seq.map(fun result->( result.Properties.["ProcessName"].Value,
result.Properties.["ID"].Value))
|> Seq.iter (fun (name,id)->printfn "%-24O %O" name id)
)
This is a quick and dirty module that I use to execute commands (chocolate commands in particular) on a remote server. The only thing you need to get it to work on your local machine is to remove the parameter ComputerName
:
#r "System.Management.Automation"
module MyPowershell =
let InvokeRemote server command =
let block = ScriptBlock.Create(command)
let pipe=PowerShell.Create()
.AddCommand("invoke-command")
pipe.AddParameter("ComputerName", server)
.AddParameter("ScriptBlock", block)
.Invoke()
|> Seq.map (sprintf "%O")
|> Seq.iter (fun line ->
let tracer=if line.Contains("not installed") then
traceError
else
trace
tracer line)
pipe.Streams.Error |> Seq.iter (traceError << sprintf "%O" )
The pipeline is represented by the PowerShell class . Steps to create it:
- Create a PowerShell pipeline with PowerShell.Create ()
- Create a ScriptBlock with the command you want to execute. For all commands, you don't need a ScriptBlock. In this case,
ScriptBlock
contains a script that I want to execute remotely. - Add what you want to accomplish. In my case, I want to run one command
invoke-command
- Add parameters. In this case, it is
-ComputerName myServer
, and-ScriptBlock ...
with the executable unit. - Start the pipeline with PowerShell.Invoke ()
- Parse the results for possible warning messages that didn't get caught in the error stream.
PowerShell errors are streamed Error
, making error handling easier.
Running the command on your local machine can be much easier:
let InvokeRemote command =
let pipe=PowerShell.Create()
.AddCommand(command)
pipe.Invoke()
|> Seq.map (sprintf "%O")
|> Seq.iter (fun line ->
let tracer=if line.Contains("not installed") then
traceError
else
trace
tracer line)
pipe.Streams.Error |> Seq.iter (traceError << sprintf "%O" )
source to share