Using MSBuild Conditional Constructs to run one or other target

I was doing modification of MSBuild target https://github.com/MNF/OctoPack.Precompile/blob/master/Source/OctoPack.Precompile.targets to have different behavior depending on parameter OutDir was specified or not for Msbuild.
Follow to MSDN “MSBuild Conditional Constructs”  I selected  Choose Element and  tried to put it   inside <Target> element
 <Target Name=”foo” />
<Choose>
<When>

<Otherwise>
</Choose>
</Target>
It didn’t work as for Choose Element allowed Parents are only Project, Otherwise, When.
I tried other way to include Target inside Choose/When element, but it is also not allowed, because Target also should be direct child of Project.
I found an implementation in http://stackoverflow.com/questions/30904741/msbuild-now-to-conditionally-use-one-of-two-targets-with-same-name when you set target depends on other targets and each child target has different conditions:
 <Target Name=”foo” DependsOnTargets=”_fooDebug;_fooRelease”/>
    <Target Name=”_fooDebug” Condition=”‘$(Configuration)’ == ‘Debug’ “
Later I found in  http://stackoverflow.com/questions/2284389/how-do-you-stop-msbuild-execution-without-raising-an-error/ that CallTaget elements with condition can be used as well:
 <CallTarget Targets="Exit"
Condition="Special Condition"/>
I beleive that MSDN “MSBuild Conditional Constructs” documentation should provide reference to all such options.

OutDir vs OutputPath for Visual studio 2015 and Asp.Net Core

TL;DR

In MSBuild for Asp.Net Core use /p:OutputPath parameter, not /p:OutDir nor both.

Full story

We’ve used psake powershell build for ASP.Net 4.61 project and passed both parameters
msbuild  /p:OutDir=“$binariesDir\” /p:OutputPath=“$outPath\”
Actually /p:OutputPath was ignored(almost, see below) and build was saved to specified in /p:OutDir folder.
When I included Asp.Net Core project into solution, it’s failed because dll, referenced by the Core project, was saved to OutDir folder, but Asp.Net Core project tried to find it in OutputPath folder.
I’ve tried to remove /p:OutputPath  parameter (as suggested in OutputPath vs OutDir thread: “to keep the OutputPath that is generated by Visual Studio, then set the OutDir as a command argument”), Asp.Net Core project failed because dll was saved to OutDir folder, but Asp.Net Core project tried to find it in relative bin\Release\ folder.
When I removed OutDir parameter and specified /p:OutputPath=“$binariesDir\” build was successful,  but package for MSDeploy, specified in a custom MS Build step, was created in a relative path obj\Release\Package rather than specified $binariesDir folder, so I needed to adjust package path.
Current VS 2015 MSDN page  Common MSBuild Project Properties doesn’t document OutDir , but only OutputPath.
 
Note that previously MSDN recommended the opposite: “OutputPath has been deprecated and OutDir should be used instead whenever possible. ”
   

Gmail arbitrary rejects emails with big number of recipients

I was sending information letter to the club subscribers(total 225 emails) using Gmail account. I keep them in 3 mailing lists: 2 with 95 emails and 3rd with remaining(GMail limit recipients to 100 per email). The first list was rejected with the following (not very specific) message.
Delivery to the following recipient failed permanently: email address
Technical details of permanent failure:
Message rejected. See https://support.google.com/mail/answer/69585 for more information.
But the second list with the same size was successful.
Additional annoyance was that “delivery failed” notifications were received slowly within 5 minutes, and initially I didn’t understand which group  (or emails from both groups)  were rejected.
 The simple workaround to split big list in 3 smaller mailing lists one was successful.

TestContext.WriteLine doesn’t accept curly brackets

In test class I was using TestContext.WriteLine trying to output JSON string, I’ve got
System.FormatException : Input string was not in a correct format.
at System.Text.StringBuilder. AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
at System.String.Format(IFormatProvider provider, String format, Object[] args)
at Microsoft.VisualStudio.TestPlatform.MSTestFramework.TestContextImplementation.WriteLine(String format, Object[] args)

Example of code that works for Debug.WriteLine, but not for TestContext.WriteLine is the following:

var msg = “{curly braces}”;
Debug.WriteLine(msg);
TestContext.WriteLine(msg);

I found, that TestContext.WriteLine expects first parameter as a format string, that consider { and } as placeholder delimiters.

UPDATE: Simple workaround,  suggested in a comment by Steve Gilham

TestContext.WriteLine(“{0}”,msg);

I had to write EscapeCurlyBraces extension

public static string EscapeCurlyBraces( this string message)
{
string ret = message.Replace( “{“, “{{” ).Replace(“}”, “}}”);
return ret;
}

and call
TestContext.WriteLine(msg.EscapeCurlyBraces() );
I’ve wrote a suggestion to MS Connect that it will be good to have separate overload TestContext.WriteLine(string msg); that doesn’t consider the parameter as format and doesn’t expect any additional parameters.

The file  https://github.com/MNF/CommonDotNetHelpers/blob/master/src/Strings/StringFormatExtensions.cs and corresponding unit tests https://github.com/MNF/CommonDotNetHelpers/blob/master/Tests/Strings/StringFormatExtensionsTests.cs are located on GitHub.

Pocket Favorites are not available when you off-line

I am using Pocket(previously known as Read It Later) and sometimes sent to support my suggestions.
Unfortunately they do not have convenient support forums(or uservoice sites), so I post my suggestions here to have them visible:

IPad Pocket Favorites are not available when you off-line. It shows message similar to Archives. For Archives it makes sense, but why favorites have this limitation?
Could you please allow to access Favorites list off-line.

The support person agreed that including the Favorites would be great approach to improving upon this feature.

He also ask to submit the request officially here: http://pocket.co/soPybA This helps the team prioritize most requested features we receive.

I don’t understand why email to support is not considered as official request. Anyway everyone who wants to suggest something to Pocket, should fill the boring form

#favorites, #pocket, #support

Globally replace obsolete NLog.WarnException using regular expression

I’ve updated NLog ver 2.0 to 4.3.5. After this I’ve noticed a compiler warning that 
WarnException(msg,exc) is obsolete and should be replaced by Warn(exc,msg)

It could be globally replaced using regular expressions 

WarnException\((.*),(.*)\);
to 

Warn($2, $1);

See saved regex in https://regex101.com/r/kL8cR4/1

#nlog, #regex

FromToRange generic class

Quite often you need to return from method 2 values that describe the range, e.g. From/To or Min/Max. You could use standard MS classes Pair or Tuple https://msdn.microsoft.com/en-us/library/system.tuple.aspx. However the names of properties are not describe the meaning of the values.
So I am using own class FromToRange. It is done similar to Pair(from http://blog.o-x-t.com/2007/07/16/generic-pair-net-class/)

///<summary>
/// similar to Pair(from http://blog.o-x-t.com/2007/07/16/generic-pair-net-class/"
///See also  DateTimeRange ( https://github.com/MNF/CommonDotNetHelpers/blob/master/src/Dates/DateTimeRange.cs)
///</summary>

public class FromToRange
{
public T From { get; set; }
public T To { get; set; }

public FromToRange()
{
}

public FromToRange(T from, T to)
{
this.From = from;
this.To = to;
}
public override string ToString()
{
string sRet = String.Format("From {0} to {1}", From, To);
return sRet;
}
public override bool Equals(object obj)
{
if (this == obj) return true;
FromToRange pair = obj as FromToRange;
if (pair == null) return false;
return Equals(From, pair.From) && Equals(To, pair.To);
}

public override int GetHashCode()
{
return (From != null ? From.GetHashCode() : 0) + 29 * (To != null ? To.GetHashCode() : 0);
}

}