Friday, 30 May 2014

Caliburn Micro and UserControls

The things that took me a while to understand were:
  • The UserControl library needs a bootstrapper
  • How to bind the view-model to the view
  • How to reference the view-model  in XAML instead of the view

Wednesday, 28 May 2014

Expanding PowerShell variables

I had the situation where I wanted to include an environment variable in my configuration .xml.
Rather than inventing a substitution scheme I decided to use $ExecutionContext.InvokeCommand.ExpandString instead

e.g.
  $sourceString = "This is my computername: `${env:COMPUTERNAME}"
  $ExecutionContext.InvokeCommand.ExpandString($sourceString) 

Update the PowerShell Execution Policy to allow the running of remote scripts

Open a PowerShell window as an Administrator and run the command below on the target machine(enter ‘y’ at the prompt):

Set-ExecutionPolicy RemoteSigned

This will set the machine to require signing for remote scripts only.

Note that the user running the scripts must be a member of the Administrators Group on the remote machines.

This can be laborious if you're managing many servers so a quick ProcMon suggests that all this is doing is setting the registry entry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"ExecutionPolicy"="RemoteSigned"

This allowed me to update my servers using:

PowerShell pre 3.0: Where does this script live?

Before PowerShell 3.0's $PSCommandPath which holds the full path to the file and $PSScriptRoot which contains the path to the file's directory we had to hand-craft it.
e.g.

$private:PSCommandPath = $MyInvocation.MyCommand.Path
$private:PSScriptRoot = (Split-Path -Parent $PSCommandPath)

# echo $private:PSCommandPath 
# echo $private:PSScriptRoot
# Call MyOtherScript.ps1 which is in the same directory as this & (Join-Path -Path $private:PSScriptRoot -ChildPath "MyOtherScript.ps1")

See also: Which version of PowerShell am I running?

Which version of PowerShell am I running?

To find which version of PowerShell you are running, start a PowerShell window and type
Get-Host.

The resulting output includes a 'Version : #.#' line.

Set the memory limit on remotely invoked jobs to 4Gb

Powershell with WinRM

Windows 7 and Windows Server 2008 R2 should have these installed by default. For earlier versions of Windows, select the appropriate download from this article: http://support.microsoft.com/kb/968929.

WinRM requires at least PowerShell 2.0.

To find which version of PowerShell you are running, start a PowerShell window and type Get-Host – the resulting output includes a 'Version : #.#' line.

WinRM Configuration

Both the source and target machines must be configured for remote operations.
This requires the 'Windows Remote Management' service to be installed and started, for the WinRM listener to accept WS-Man requests and for the Firewall to include an exception for WinRM.
The simplest way to accomplish this is to get winrm to do it all for you.

Open a PowerShell window as an Administrator and run the command below on the target machine (enter ‘y’ at the prompts):
winrm quickconfig

Example script

Friday, 16 May 2014

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread

This System.NotSupportedException exception is raised when we attempt to modify (e.g. add to) a collection (e.g. an ObservableCollection) on a thread which isn't the same thread that created the collection (e.g. the UI thread).

In short: An ObservableCollection, for example, can only be modified in the thread that created it.

In WPF this thread affinity is handled by System.Windows.Threading.Dispatcher -- hence it's reference in the error message.

Typically a WPF project has a single Dispatcher instance so to modify the collection we'd have to invoke the modification while we're running in the UI (Dispatcher) thread.

We could use Dispatcher.CurrentDispatcher.Invoke (or BeginInvoke) to do the addition, however, with .Net 4.5 we now have System.Windows.Data.BindingOperations.EnableCollectionSynchronization.

EnableCollectionSynchronization 'Enables a collection to be accessed across multiple threads and specifies the lock object that should be used to synchronize access to the collection.'.

For example, I had a TraceListener which I wanted to be invoked from any number of threads.

The basis of it now looks like this: