PowerShell: Set the Location the Executing Script Path

I already knew about the proper way to get the executing path:

Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

…but today I’ve saw another way to set the scope of the current location to a desired path (open-source code is the most powerful resource):

NAME
Push-Location

SYNOPSIS
Adds the current location to the top of a location stack.

SYNTAX
Push-Location [[-Path] <String>] [-PassThru] [-StackName <String>] [-UseTransaction [<SwitchParameter>]]
[<CommonParameters>]

Push-Location [-LiteralPath <String>] [-PassThru] [-StackName <String>] [-UseTransaction [<SwitchParameter>]]
[<CommonParameters>]

DESCRIPTION
The Push-Location cmdlet adds (“pushes”) the current location onto a location stack. If you specify a path,
Push-Location pushes the current location onto a location stack and then changes the current location to the
location specified by the path. You can use the Pop-Location cmdlet to get locations from the location stack.

By default, the Push-Location cmdlet pushes the current location onto the current location stack, but you can use
the StackName parameter to specify an alternate location stack. If the stack does not exist, Push-Location creates
it.

For more information about location stacks, see the Notes.

RELATED LINKS
Online Version: http://go.microsoft.com/fwlink/p/?linkid=293892
Get-Location
Pop-Location
Set-Location
about_Providers

REMARKS
To see the examples, type: “get-help Push-Location -examples”.
For more information, type: “get-help Push-Location -detailed”.
For technical information, type: “get-help Push-Location -full”.
For online help, type: “get-help Push-Location -online”

It is actually a stack, so it could be very useful in situation where you need to temporary change the scope of the location for a sets of commands and then return back to the previous path. This is mandatory when your script is a part of a bigger script, and you also don’t have the ownership (think about PsGet) of that script, so it’s a best practice to push your needed location, and before the script ends pop it (Pop-Location) to resume the path used from the script who called your.

Combining together both commands you just have to add on the top of the script this command:

Push-Location (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)

The follow is the sample script where I’ve saw this command in action, it is a PsGet script to enable posh-git module (profile.example.ps1):

Push-Location (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)

# Load posh-git module from current directory
Import-Module .\posh-git

# If module is installed in a default location ($env:PSModulePath),
# use this instead (see about_Modules for more information):
# Import-Module posh-git

# Set up a simple prompt, adding the git prompt parts inside git repos
function global:prompt {
    $realLASTEXITCODE = $LASTEXITCODE

    # Reset color, which can be messed up by Enable-GitColors
    $Host.UI.RawUI.ForegroundColor = $GitPromptSettings.DefaultForegroundColor

    Write-Host($pwd.ProviderPath) -nonewline

    Write-VcsStatus

    $global:LASTEXITCODE = $realLASTEXITCODE
    return "> "
}

Enable-GitColors

Pop-Location

Start-SshAgent -Quiet

 

NuGet + Visual Studio: Automatic Package Restore of Different Solutions to the Same Folder

Attachment with the sample: NugetPackageRestore.zip

Today I had a problem using nuget package restore in a quite complex project that has multiple projects and multiple solutions file located in different folders, so that nuget was restoring the packages in a wrong folder for some of my solutions.

For instance if you have a file structure like this:

Root
  |- ProjectA
  |- |- ProjectA.Model
  |- |- |- ProjectA.Model.csproj
  |- |- ProjectA.Service
  |- |- |- ProjectA.Service.csproj
  |- |- ProjectA.sln
  |- Project B
  |- |- ProjectB.Model
  |- |- |- ProjectB.Model.csproj
  |- |- ProjectB.Service
  |- |- |- ProjectB.Service.csproj
  |- |- ProjectB.sln
  |- AllMyProjects.sln

AllMyProjects.sln simply contains all the projects (ProjectA.Model.csproj, ProjectA.Service.csproj, ProjectB.Model.csproj, ProjectB.Service.csproj).

When you run the build for all the 3 solutions, nuget by default will restores everything in a folder “packages” located at the same level of the solution file, producing something like this:

Root
  |- Packages
  |- (...all the packages...)
  |- ProjectA
  |- |- Packages
  |- |- |- (...all the packages...)
  |- |- ProjectA.Model
  |- |- |- ProjectA.Model.csproj
  |- |- ProjectA.Service
  |- |- |- ProjectA.Service.csproj
  |- |- ProjectA.sln
  |- Project B
  |- |- Packages
  |- |- |- (...all the packages...)
  |- |- ProjectB.Model
  |- |- |- ProjectB.Model.csproj
  |- |- ProjectB.Service
  |- |- |- ProjectB.Service.csproj
  |- |- ProjectB.sln
  |- AllMyProjects.sln

Now, if you first compile the ProjectA.sln and ProjectB.sln, also the AllMyProjects.sln will compile fine, but this just because the packages will be correctly restored by the two specific solution ProjectA.sln and ProjectB.sln, but if you try to clean up all the packages folder, and build the AllMyProjects.sln first, you will get a lot of compile error, this because the projects are poiting the nuget restored dll(s) inside specific folders and not a generic folder instead.

One possible fix to this, is to move all the solutions file, under the same folder, to le restore the packages to the same folder for every project, but I preferred to leave the structure as is, and try to force the nuget packages restore process. In fact there’s a key configuration “repositoryPath” to override the default packages folder location.

These are the steps to move the packages folder to a common location:

1 – Create a NuGet.config file under the root folder (nuget will find and use this file using a recursive search, starting from .nuget folder of the solution folder):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="repositoryPath" value="$\..\Packages" />
  </config>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
</configuration>

$ = refers to the NuGet.config file
we need to type “$\..\” and not just “$\” to set the Root folder just because I think is a kind of bug.

You will end-up with something like this:

Root
  |- ProjectA
  |- |- ProjectA.Model
  |- |- |- ProjectA.Model.csproj
  |- |- ProjectA.Service
  |- |- |- ProjectA.Service.csproj
  |- |- ProjectA.sln
  |- Project B
  |- |- ProjectB.Model
  |- |- |- ProjectB.Model.csproj
  |- |- ProjectB.Service
  |- |- |- ProjectB.Service.csproj
  |- |- ProjectB.sln
  |- AllMyProjects.sln
  |- NuGet.config

2a – Edit all the projects file and fix the dll reference by replacing the old relative path with the new one

2b – In alternative to 2a, you can run the nuget command “Update-Package –reinstall” from the nuget “Package Manager Console”, but this can dirty you projects, then I prefer do it manually directly from notepad :)

3 – Delete all the Packages folder and try to build every solution. To best test that everything is fine, before build a solution always delete the packages folder. You should see the “Packages” folder only once:

Root
  |- Packages
  |- (...all the packages...)
  |- ProjectA
  |- |- ProjectA.Model
  |- |- |- ProjectA.Model.csproj
  |- |- ProjectA.Service
  |- |- |- ProjectA.Service.csproj
  |- |- ProjectA.sln
  |- Project B
  |- |- ProjectB.Model
  |- |- |- ProjectB.Model.csproj
  |- |- ProjectB.Service
  |- |- |- ProjectB.Service.csproj
  |- |- ProjectB.sln
  |- AllMyProjects.sln
  |- NuGet.config

WPF: ContentControl vs ContentPresenter

A small post to explain the little but important difference between ContentControl and ContentPresenter.

The most significant difference is that ContentPresenter has the ContentSource property while ContentControl hasn’t.

The ContentPresenter.ContentSource property specify which dependency property of the parent template instnace should be used to fill the ContentPresenter.Content.

For instance if you have a UserControl “MyControl” that defines a dependency property called  “MyProperty”, you can use the value of MyControl.MyProperty in the MyControl.Template in this way:

<ControlTemplate TargetType="MyControl">
      <StackPanel>
          <ContentPresenter ContentSource="MyProperty" />
      </StackPanel>
</ControlTempalte>

Instead using the ContentControl you could write the same template in this way:

<ControlTemplate TargetType="MyControl">
      <StackPanel>
          <ContentControl Content="{TemplateBinding MyProperty}" />
      </StackPanel>
</ControlTempalte>

In fact the ContentControl has a template that uses a ContentPresenter to show it’s own Content property using the ContentSource. The ContentPresenter is a light-weight component that is supposed to be used in a template as a simple place-holder for the Content property. The default value for the ContentPresenter.ContentSource is “Content”, so you just need to add an empty ContentPresenter in a template to let be the place-holder of the Content property of the template parent instance.

WPF: Attached Property in XAML Markup (The object ‘…’ already has a child and cannot add ‘…’)

Let’s say you need an attached property to set an arbitrary header content to any DependencyObject, to let you use that value and populate the Header property of any HeaderedContentControl, creating the class directly in your WPF test application:

public static class HeaderManager
{
	public static readonly DependencyProperty HeaderProperty = DependencyProperty.RegisterAttached(
		&quot;Header&quot;,
		typeof(object),
		typeof(HeaderManager),
		new PropertyMetadata(null));

	public static void SetHeader(DependencyObject element, object value)
	{
		element.SetValue(HeaderProperty, value);
	}

	public static object GetHeader(DependencyObject element)
	{
		return (object)element.GetValue(HeaderProperty);
	}
}

Then you want to attach that property to an UserControl that when injected in a TabItem can self declare it’s own header, and in first attempt you will end up trying to do this:

&lt;UserControl x:Class=&quot;RadicalTabRegion.Presentation.FirstView&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
             xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
             xmlns:s=&quot;clr-namespace:RadicalTabRegion.Presentation.Regions.Specialized&quot;
             mc:Ignorable=&quot;d&quot;
             d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;300&quot;&gt;

    &lt;s:HeaderManager.Header&gt;
        &lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
            &lt;TextBlock Text=&quot;First View&quot;/&gt;
            &lt;CheckBox/&gt;
        &lt;/StackPanel&gt;
    &lt;/s:HeaderManager.Header&gt;

    &lt;Grid&gt;
        &lt;TextBlock Text=&quot;I'm the first view&quot;/&gt;
    &lt;/Grid&gt;

&lt;/UserControl&gt;

But if you try to compile this, you will get this error:

“The object ‘UserControl’ already has a child and cannot add ‘Grid’. ‘UserControl’ can accept only one child.”

This is because the compiler needs to know that HeaderManager.Header is an attached property, before compile xaml in baml, but because the HeaderManager class is declared in the same assembly of the xaml, it can’t. Actually I think this can be overcome by Microsoft, but never mind there’s a couple of solutions for that.

The first solution is to move the markup declaration after the first element in the UserControl content, and our case after the Grid:

&lt;UserControl x:Class=&quot;RadicalTabRegion.Presentation.FirstView&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
             xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
             xmlns:s=&quot;clr-namespace:RadicalTabRegion.Presentation.Regions.Specialized&quot;
             mc:Ignorable=&quot;d&quot;
             d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;300&quot;&gt;

    &lt;Grid&gt;
        &lt;TextBlock Text=&quot;I'm the first view&quot;/&gt;
    &lt;/Grid&gt;

    &lt;s:HeaderManager.Header&gt;
        &lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
            &lt;TextBlock Text=&quot;First View&quot;/&gt;
            &lt;CheckBox/&gt;
        &lt;/StackPanel&gt;
    &lt;/s:HeaderManager.Header&gt;

&lt;/UserControl&gt;

The second solution is to move the HeaderManager class into a different class library, so in a different assembly, and this is the best approach because let you use the attached property more naturally, without incurring in that compile error even if you declare the property just before the UserControl.Content, that is more natural for an Header property. For instance if you add the class into a class library called “RadicalTabRegion.Windows.Presentation” you will end-up with this XAML that just works fine:

&lt;UserControl x:Class=&quot;RadicalTabRegion.Presentation.FirstView&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
             xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
             xmlns:s=&quot;clr-namespace:RadicalTabRegion.Windows.Presentation.Regions.Specialized;assembly=RadicalTabRegion.Windows.Presentation&quot;
             mc:Ignorable=&quot;d&quot;
             d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;300&quot;&gt;

    &lt;s:HeaderManager.Header&gt;
        &lt;StackPanel Orientation=&quot;Horizontal&quot;&gt;
            &lt;TextBlock Text=&quot;First View&quot;/&gt;
            &lt;CheckBox/&gt;
        &lt;/StackPanel&gt;
    &lt;/s:HeaderManager.Header&gt;

    &lt;Grid&gt;
        &lt;TextBlock Text=&quot;I'm the first view&quot;/&gt;
    &lt;/Grid&gt;

&lt;/UserControl&gt;

This example is a part of an implementation I’m making for Radical to implement a TabControlRegion, that is able to inject a simple UserControl into a TabItem (generated at runtime) and let the developer deeply customize the TabItem.Header simply declaring the attached property directly into the UserControl. This is under development right now, and it is just one of the possible solutions, if I will like it, I will post the entire code, and pull a request for integrating the new region directly into Radical.

TFS: Delete Folder without a Workspace

Sorry about this title, but actually you cannot delete a source controlled folder without assigning first a workspace, BUT, but you can avoid wasting disk space avoiding to recursively download all the files in that folder, so it’s what I think you want to do, and then here’s the steps:

  1. Open the “Developer Command Prompt for VS2013″
  2. Go to the workspace folder where you have the folder you want to get without recursively get all the items
  3. run the command “tf get <folder path>” without the /recursive switch

TF will get only the first level content of the <folder path>, then you can go back on visual studio team explorer, delete the folder and checkin the changes :)

C#: Enable Cookie Container on System.Net.WebClient (for Authentication)

As I told on the previous post the WebClient can be easily extended to add more functionality such in this case the Cookie Container, and let use it to authenticate versus the web pages that are protected using an authenticated cookie:

public class CookieWebClient : WebClient
{
	public CookieContainer CookieContainer { get; private set; }

	/// <summary>
	/// This will instanciate an internal CookieContainer.
	/// </summary>
	public CookieWebClient()
	{
		this.CookieContainer = new CookieContainer();
	}

	/// <summary>
	/// Use this if you want to control the CookieContainer outside this class.
	/// </summary>
	public CookieWebClient(CookieContainer cookieContainer)
	{
		this.CookieContainer = cookieContainer;
	}

	protected override WebRequest GetWebRequest(Uri address)
	{
		var request = base.GetWebRequest(address) as HttpWebRequest;
		if (request == null) return base.GetWebRequest(address);
		request.CookieContainer = CookieContainer;
		return request;
	}
}

And then you can use it as follow:

using (var client = new CookieWebClient())
{
	var loginData = new NameValueCollection
	{
		{ "UserName", "TestUser" },
		{ "Password", "MyPassword" }
	};

	// Login into the website (at this point the Cookie Container will do the rest of the job for us, and save the cookie for the next calls)
	client.UploadValues("http://domain.com/Account/LogOn", "POST", loginData);

	// Call authenticated resources
	client.UploadString("http://domain.com/ProtectedArea/MyProtectedResource", "POST", "some data");
}

CookieWebClient takes also a CookieContainer as parameter, to let you control the cookie container outside, and passing over different CookieWebclient instantiation.