2 people like it.

Run MsBuild 2015

runs msbuild using 2015 msbuild and fails if there is an error. All errors reported came across on the output stream instead of the error stream.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
open System
open System.Diagnostics
open System.IO

let delimit s (items:string seq) = String.Join(s,items)

let runProc filename args startDir = 
    let timer = Stopwatch.StartNew()
    let procStartInfo = 
        ProcessStartInfo(
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            FileName = filename,
            Arguments = args
        )
    match startDir with | Some d -> procStartInfo.WorkingDirectory <- d | _ -> ()

    let outputs = System.Collections.Generic.List<string>()
    let errors = System.Collections.Generic.List<string>()
    let outputHandler f (_sender:obj) (args:DataReceivedEventArgs) = f args.Data
    let p = new Process(StartInfo = procStartInfo)
    p.OutputDataReceived.AddHandler(DataReceivedEventHandler (outputHandler outputs.Add))
    p.ErrorDataReceived.AddHandler(DataReceivedEventHandler (outputHandler errors.Add))
    let started = 
        try
            p.Start()
        with | ex ->
            ex.Data.Add("filename", filename)
            reraise()
    if not started then
        failwithf "Failed to start process %s" filename
    printfn "Started %s with pid %i" p.ProcessName p.Id
    p.BeginOutputReadLine()
    p.BeginErrorReadLine()
    p.WaitForExit()
    timer.Stop()
    printfn "Finished %s after %A milliseconds" filename timer.ElapsedMilliseconds
    let cleanOut l = l |> Seq.filter (fun o -> String.IsNullOrEmpty o |> not)
    cleanOut outputs,cleanOut errors

let msbuild targetProject buildArgs = 
    let targetFolder = Path.GetDirectoryName targetProject
    let msbuildPath = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
    let errorCount outputs errors = 
        let regex = System.Text.RegularExpressions.Regex(@"^\s*([1-9][0-9]*)\s+Error\(s\)$|Build FAILED.")
        [ outputs;errors] |> Seq.concat  |> Seq.map regex.Match |> Seq.tryFind(fun m -> m.Success)

    let args = targetProject::buildArgs |> delimit " "
    let output,errors = runProc msbuildPath args (Some targetFolder)
    match errorCount output errors with
    | Some errorMatch -> 
        //printfn "%A" output
        //printfn "%A" errors
        let regex = System.Text.RegularExpressions.Regex("Build error", Text.RegularExpressions.RegexOptions.IgnoreCase)

        printfn "%A" (output |> Seq.filter regex.IsMatch |> List.ofSeq)
        let errorText = 
            let text = errorMatch.Groups.[1].Value
            if String.IsNullOrWhiteSpace(text) then errorMatch.Groups.[0].Value else text
        failwithf "ErrorsFound : %s" errorText
    | None -> ()
    if output |> Seq.exists (fun c -> c = "Build FAILED.") then failwithf "Build failed"
    output,errors
namespace System
namespace System.Diagnostics
namespace System.IO
val delimit : s:string -> items:seq<string> -> string

Full name: Script.delimit
val s : string
val items : seq<string>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.Join(separator: string, values: Collections.Generic.IEnumerable<string>) : string
String.Join<'T>(separator: string, values: Collections.Generic.IEnumerable<'T>) : string
String.Join(separator: string, [<ParamArray>] values: obj []) : string
String.Join(separator: string, [<ParamArray>] value: string []) : string
String.Join(separator: string, value: string [], startIndex: int, count: int) : string
val runProc : filename:string -> args:string -> startDir:string option -> seq<string> * seq<string>

Full name: Script.runProc
val filename : string
val args : string
val startDir : string option
val timer : Stopwatch
Multiple items
type Stopwatch =
  new : unit -> Stopwatch
  member Elapsed : TimeSpan
  member ElapsedMilliseconds : int64
  member ElapsedTicks : int64
  member IsRunning : bool
  member Reset : unit -> unit
  member Restart : unit -> unit
  member Start : unit -> unit
  member Stop : unit -> unit
  static val Frequency : int64
  ...

Full name: System.Diagnostics.Stopwatch

--------------------
Stopwatch() : unit
Stopwatch.StartNew() : Stopwatch
val procStartInfo : ProcessStartInfo
Multiple items
type ProcessStartInfo =
  new : unit -> ProcessStartInfo + 2 overloads
  member Arguments : string with get, set
  member CreateNoWindow : bool with get, set
  member Domain : string with get, set
  member EnvironmentVariables : StringDictionary
  member ErrorDialog : bool with get, set
  member ErrorDialogParentHandle : nativeint with get, set
  member FileName : string with get, set
  member LoadUserProfile : bool with get, set
  member Password : SecureString with get, set
  ...

Full name: System.Diagnostics.ProcessStartInfo

--------------------
ProcessStartInfo() : unit
ProcessStartInfo(fileName: string) : unit
ProcessStartInfo(fileName: string, arguments: string) : unit
union case Option.Some: Value: 'T -> Option<'T>
val d : string
property ProcessStartInfo.WorkingDirectory: string
val outputs : Collections.Generic.List<string>
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type List<'T> =
  new : unit -> List<'T> + 2 overloads
  member Add : item:'T -> unit
  member AddRange : collection:IEnumerable<'T> -> unit
  member AsReadOnly : unit -> ReadOnlyCollection<'T>
  member BinarySearch : item:'T -> int + 2 overloads
  member Capacity : int with get, set
  member Clear : unit -> unit
  member Contains : item:'T -> bool
  member ConvertAll<'TOutput> : converter:Converter<'T, 'TOutput> -> List<'TOutput>
  member CopyTo : array:'T[] -> unit + 2 overloads
  ...
  nested type Enumerator

Full name: System.Collections.Generic.List<_>

--------------------
Collections.Generic.List() : unit
Collections.Generic.List(capacity: int) : unit
Collections.Generic.List(collection: Collections.Generic.IEnumerable<'T>) : unit
val errors : Collections.Generic.List<string>
val outputHandler : ((string -> 'a) -> obj -> DataReceivedEventArgs -> 'a)
val f : (string -> 'a)
type obj = Object

Full name: Microsoft.FSharp.Core.obj
val args : DataReceivedEventArgs
type DataReceivedEventArgs =
  inherit EventArgs
  member Data : string

Full name: System.Diagnostics.DataReceivedEventArgs
property DataReceivedEventArgs.Data: string
val p : Process
Multiple items
type Process =
  inherit Component
  new : unit -> Process
  member BasePriority : int
  member BeginErrorReadLine : unit -> unit
  member BeginOutputReadLine : unit -> unit
  member CancelErrorRead : unit -> unit
  member CancelOutputRead : unit -> unit
  member Close : unit -> unit
  member CloseMainWindow : unit -> bool
  member EnableRaisingEvents : bool with get, set
  member ExitCode : int
  ...

Full name: System.Diagnostics.Process

--------------------
Process() : unit
event Process.OutputDataReceived: IEvent<DataReceivedEventHandler,DataReceivedEventArgs>
abstract member IDelegateEvent.AddHandler : handler:'Delegate -> unit
type DataReceivedEventHandler =
  delegate of obj * DataReceivedEventArgs -> unit

Full name: System.Diagnostics.DataReceivedEventHandler
Collections.Generic.List.Add(item: string) : unit
event Process.ErrorDataReceived: IEvent<DataReceivedEventHandler,DataReceivedEventArgs>
val started : bool
Process.Start() : bool
val ex : exn
property Exception.Data: Collections.IDictionary
Collections.IDictionary.Add(key: obj, value: obj) : unit
val reraise : unit -> 'T

Full name: Microsoft.FSharp.Core.Operators.reraise
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
property Process.ProcessName: string
property Process.Id: int
Process.BeginOutputReadLine() : unit
Process.BeginErrorReadLine() : unit
Process.WaitForExit() : unit
Process.WaitForExit(milliseconds: int) : bool
Stopwatch.Stop() : unit
property Stopwatch.ElapsedMilliseconds: int64
val cleanOut : (seq<string> -> seq<string>)
val l : seq<string>
module Seq

from Microsoft.FSharp.Collections
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val o : string
String.IsNullOrEmpty(value: string) : bool
val msbuild : targetProject:string -> buildArgs:string list -> seq<string> * seq<string>

Full name: Script.msbuild
val targetProject : string
val buildArgs : string list
val targetFolder : string
type Path =
  static val DirectorySeparatorChar : char
  static val AltDirectorySeparatorChar : char
  static val VolumeSeparatorChar : char
  static val InvalidPathChars : char[]
  static val PathSeparator : char
  static member ChangeExtension : path:string * extension:string -> string
  static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
  static member GetDirectoryName : path:string -> string
  static member GetExtension : path:string -> string
  static member GetFileName : path:string -> string
  ...

Full name: System.IO.Path
Path.GetDirectoryName(path: string) : string
val msbuildPath : string
val errorCount : ('a -> 'a -> Text.RegularExpressions.Match option) (requires 'a :> seq<string>)
val outputs : #seq<string>
val errors : #seq<string>
val regex : Text.RegularExpressions.Regex
namespace System.Text
namespace System.Text.RegularExpressions
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Text.RegularExpressions.Regex(pattern: string) : unit
Text.RegularExpressions.Regex(pattern: string, options: Text.RegularExpressions.RegexOptions) : unit
val concat : sources:seq<#seq<'T>> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.concat
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
Text.RegularExpressions.Regex.Match(input: string) : Text.RegularExpressions.Match
Text.RegularExpressions.Regex.Match(input: string, startat: int) : Text.RegularExpressions.Match
Text.RegularExpressions.Regex.Match(input: string, beginning: int, length: int) : Text.RegularExpressions.Match
val tryFind : predicate:('T -> bool) -> source:seq<'T> -> 'T option

Full name: Microsoft.FSharp.Collections.Seq.tryFind
val m : Text.RegularExpressions.Match
property Text.RegularExpressions.Group.Success: bool
val output : seq<string>
val errors : seq<string>
val errorMatch : Text.RegularExpressions.Match
type RegexOptions =
  | None = 0
  | IgnoreCase = 1
  | Multiline = 2
  | ExplicitCapture = 4
  | Compiled = 8
  | Singleline = 16
  | IgnorePatternWhitespace = 32
  | RightToLeft = 64
  | ECMAScript = 256
  | CultureInvariant = 512

Full name: System.Text.RegularExpressions.RegexOptions
field Text.RegularExpressions.RegexOptions.IgnoreCase = 1
Text.RegularExpressions.Regex.IsMatch(input: string) : bool
Text.RegularExpressions.Regex.IsMatch(input: string, startat: int) : bool
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val ofSeq : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.List.ofSeq
val errorText : string
val text : string
property Text.RegularExpressions.Match.Groups: Text.RegularExpressions.GroupCollection
String.IsNullOrWhiteSpace(value: string) : bool
union case Option.None: Option<'T>
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.exists
val c : string
Raw view New version

More information

Link:http://fssnip.net/sx
Posted:4 years ago
Author:ImaginaryDevelopment
Tags: process , msbuild