0 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
val s : string
val items : seq<string>
Multiple items
val string : value:'T -> string

--------------------
type string = String
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
Multiple items
type String =
  new : value:char[] -> string + 8 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool + 3 overloads
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 3 overloads
  member EnumerateRunes : unit -> StringRuneEnumerator
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  ...

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

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

--------------------
ProcessStartInfo() : ProcessStartInfo
ProcessStartInfo(fileName: string) : ProcessStartInfo
ProcessStartInfo(fileName: string, arguments: string) : ProcessStartInfo
union case Option.Some: Value: 'T -> Option<'T>
val d : 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

--------------------
Collections.Generic.List() : Collections.Generic.List<'T>
Collections.Generic.List(capacity: int) : Collections.Generic.List<'T>
Collections.Generic.List(collection: Collections.Generic.IEnumerable<'T>) : Collections.Generic.List<'T>
val errors : Collections.Generic.List<string>
val outputHandler : ((string -> 'a) -> obj -> DataReceivedEventArgs -> 'a)
val f : (string -> 'a)
val _sender : obj
type obj = Object
val args : DataReceivedEventArgs
type DataReceivedEventArgs =
  inherit EventArgs
  member 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
  ...

--------------------
Process() : Process
type DataReceivedEventHandler =
  delegate of obj * DataReceivedEventArgs -> unit
val started : bool
val ex : exn
val reraise : unit -> 'T
val not : value:bool -> bool
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
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>
val o : string
String.IsNullOrEmpty(value: string) : bool
val msbuild : targetProject:string -> buildArgs:string list -> seq<string> * seq<string>
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 PathSeparator : char
  static val InvalidPathChars : char[]
  static member ChangeExtension : path:string * extension:string -> string
  static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
  static member EndsInDirectorySeparator : path:ReadOnlySpan<char> -> bool + 1 overload
  static member GetDirectoryName : path:string -> string + 1 overload
  static member GetExtension : path:string -> string + 1 overload
  ...
Path.GetDirectoryName(path: ReadOnlySpan<char>) : ReadOnlySpan<char>
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 + 2 overloads
  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 MatchTimeout : TimeSpan
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  ...

--------------------
Text.RegularExpressions.Regex(pattern: string) : Text.RegularExpressions.Regex
Text.RegularExpressions.Regex(pattern: string, options: Text.RegularExpressions.RegexOptions) : Text.RegularExpressions.Regex
Text.RegularExpressions.Regex(pattern: string, options: Text.RegularExpressions.RegexOptions, matchTimeout: TimeSpan) : Text.RegularExpressions.Regex
val concat : sources:seq<#seq<'T>> -> seq<'T>
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
val tryFind : predicate:('T -> bool) -> source:seq<'T> -> 'T option
val m : Text.RegularExpressions.Match
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
field Text.RegularExpressions.RegexOptions.IgnoreCase: Text.RegularExpressions.RegexOptions = 1
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
    interface IReadOnlyList<'T>
    interface IReadOnlyCollection<'T>
    interface IEnumerable
    interface IEnumerable<'T>
    member GetReverseIndex : rank:int * offset:int -> int
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    ...
val ofSeq : source:seq<'T> -> 'T list
val errorText : string
val text : string
String.IsNullOrWhiteSpace(value: string) : bool
union case Option.None: Option<'T>
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool
val c : string

More information

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