0 people like it.
Like the snippet!
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