如何从FAKE -F#MAKE执行powershell脚本

时间:2017-03-31 11:38:39

标签: f# f#-interactive f#-3.0 f#-data f#-fake

我正在将MSBuild代码迁移到FAKE - 我无法从fake执行powershell脚本,下面是要用FAKE写的MSBuild文件的代码:

<Target Name="VersionConfig"> 
    <Exec IgnoreExitCode="false" LogStandardErrorAsError="true" StandardErrorImportance="high" Command="powershell -File &quot;$(BuildRoot)\DeployScripts\scripts\AdminScripts\VersionUpdateFile.ps1&quot;  -path &quot;$(BuildSolutionVersioningConfig)&quot; -majorVersion &quot;$(BuildNumberMajor)&quot; -minor &quot;$(BuildNumberMinor)&quot; -build &quot;$(BuildNumber)&quot; -revision &quot;$(BuildNumberRevision)&quot;"/>
</Target>

如何在FAKE中写这个,我是FAKE的新手并且没有多次使用F#,所以请原谅我,如果这应该是显而易见的。

如果有人可以提供帮助,那将非常有帮助。

谢谢。

2 个答案:

答案 0 :(得分:3)

您可以在任何.NET应用程序中使用Powershell pipeline命名空间的类创建System.Management.Automation。您可以使用该管道在本地或远程计算机上执行命令。

以下目标检索进程列表并打印它们。它是PowerShell类的文档示例的F#等价物:

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)
)

这是一个快速的&amp;我用来在远程服务器上执行命令(特别是巧克力命令)的脏模块。要使它在本地计算机上运行,​​唯一需要的是删除 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" )

管道由PowerShell类表示。构建它的步骤是:

  1. 使用PowerShell.Create()
  2. 创建PowerShell管道
  3. 使用您要执行的命令创建ScriptBlock。所有命令都不需要ScriptBlock。在这种情况下,ScriptBlock包含我想远程执行的脚本。
  4. 添加您要执行的内容。就我而言,我想运行一个invoke-command命令
  5. 添加参数。在这种情况下,执行块的是-ComputerName myServer-ScriptBlock ...
  6. 使用PowerShell.Invoke()
  7. 运行管道
  8. 将可能的警告消息的结果解析为错误流
  9. PowerShell错误会发送到Error流,这样可以更轻松地处理错误。

    在本地计算机上执行命令可以简单得多:

    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" )
    

答案 1 :(得分:1)

FAKE中的Fake.ProcessHelper namespace是您正在寻找的。文档不会告诉您这一点,但Fake.ProcessHelpermarked with the AutoOpen attribute,这意味着您链接的API参考页中列出的所有函数都可以从您的FAKE构建脚本中获得,而无需任何明确的open语句来使用它们。你这样使用它:

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)
)

一对夫妇注意到: