Visual Studo Power Tools
I just installed Visual Studio Power Tools.
Visual Studio Power Tools | MSDN
I will see if there are features that I actually use.
Archive for the ‘Visual Studio’ Category.
I just installed Visual Studio Power Tools.
I will see if there are features that I actually use.
I found out that I needed to read the 64 bit registry from a 32 bit app today.
Why you might ask?
Well, I need to get the RegisteredOrganization value from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion and unfortunately Microsoft has a bug where the WOW6432 version of this key always says Microsoft, so a 32 bit application would always return Microsoft as the RegisteredOrganization, regardless of what the user entered when they installed the OS. This is hardly desired.
Note: This is also why all Visual Studio projects created in Windows 7 64 bit have Microsoft in the project’s Assembly Information. Change the WOW6432 version of the RegisteredOrganization and you fix this Visual Studio issue.
Well, turns out C# doesn’t have functionality until .NET 4, so prior to .NET 4, to choose the 64 bit hive when running a 32 bit app, so we have to do use a DLLImport and use RegOpenKeyEx, RegCloseKey, and RegQueryValueEx.
I don’t have this well commented, and it is not very newbie proof, but here are three different ways to do this. Hopefully you can understand one or more of these.
Here is how to do this in .NET 4.
using Microsoft.Win32;
namespace Read64bitRegistryFrom32bitApp
{
class Program
{
static void Main(string[] args)
{
string value64 = string.Empty;
string value32 = string.Empty;
RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
value64 = localKey.GetValue("RegisteredOrganization").ToString();
}
RegistryKey localKey32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey32 != null)
{
value32 = localKey32.GetValue("RegisteredOrganization").ToString();
}
}
}
}
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Read64bitRegistryFrom32bitApp
{
class Program
{
static void Main(string[] args)
{
string value64 = GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");
Console.WriteLine(value64);
string value32 = GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");
Console.WriteLine(value32);
}
public enum RegSAM
{
QueryValue = 0x0001,
SetValue = 0x0002,
CreateSubKey = 0x0004,
EnumerateSubKeys = 0x0008,
Notify = 0x0010,
CreateLink = 0x0020,
WOW64_32Key = 0x0200,
WOW64_64Key = 0x0100,
WOW64_Res = 0x0300,
Read = 0x00020019,
Write = 0x00020006,
Execute = 0x00020019,
AllAccess = 0x000f003f
}
public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);
#region Member Variables
#region Read 64bit Reg from 32bit app
[DllImport("Advapi32.dll")]
static extern uint RegOpenKeyEx(
UIntPtr hKey,
string lpSubKey,
uint ulOptions,
int samDesired,
out int phkResult);
[DllImport("Advapi32.dll")]
static extern uint RegCloseKey(int hKey);
[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
public static extern int RegQueryValueEx(
int hKey, string lpValueName,
int lpReserved,
ref uint lpType,
System.Text.StringBuilder lpData,
ref uint lpcbData);
#endregion
#endregion
#region Functions
static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName)
{
return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName);
}
static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName)
{
return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName);
}
static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
{
//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
int hkey = 0;
try
{
uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
if (0 != lResult) return null;
uint lpType = 0;
uint lpcbData = 1024;
StringBuilder AgeBuffer = new StringBuilder(1024);
RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);
string Age = AgeBuffer.ToString();
return Age;
}
finally
{
if (0 != hkey) RegCloseKey(hkey);
}
}
#endregion
}
}
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Read64bitRegistryFrom32bitApp
{
public enum RegSAM
{
QueryValue = 0x0001,
SetValue = 0x0002,
CreateSubKey = 0x0004,
EnumerateSubKeys = 0x0008,
Notify = 0x0010,
CreateLink = 0x0020,
WOW64_32Key = 0x0200,
WOW64_64Key = 0x0100,
WOW64_Res = 0x0300,
Read = 0x00020019,
Write = 0x00020006,
Execute = 0x00020019,
AllAccess = 0x000f003f
}
public static class RegHive
{
public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);
}
public static class RegistryWOW6432
{
#region Member Variables
#region Read 64bit Reg from 32bit app
[DllImport("Advapi32.dll")]
static extern uint RegOpenKeyEx(
UIntPtr hKey,
string lpSubKey,
uint ulOptions,
int samDesired,
out int phkResult);
[DllImport("Advapi32.dll")]
static extern uint RegCloseKey(int hKey);
[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
public static extern int RegQueryValueEx(
int hKey, string lpValueName,
int lpReserved,
ref uint lpType,
System.Text.StringBuilder lpData,
ref uint lpcbData);
#endregion
#endregion
#region Functions
static public string GetRegKey64(UIntPtr inHive, String inKeyName, String inPropertyName)
{
return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName);
}
static public string GetRegKey32(UIntPtr inHive, String inKeyName, String inPropertyName)
{
return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName);
}
static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
{
//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
int hkey = 0;
try
{
uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
if (0 != lResult) return null;
uint lpType = 0;
uint lpcbData = 1024;
StringBuilder AgeBuffer = new StringBuilder(1024);
RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData);
string Age = AgeBuffer.ToString();
return Age;
}
finally
{
if (0 != hkey) RegCloseKey(hkey);
}
}
#endregion
#region Enums
#endregion
}
}
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Read64bitRegistryFrom32bitApp
{
class Program
{
static void Main(string[] args)
{
string value64 = RegistryWOW6432.GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");
string value32 = RegistryWOW6432.GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization");
}
}
}
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;
namespace Read64bitRegistryFrom32bitApp
{
/// <summary>
/// An extension class to allow a registry key to allow it to get the
/// registry in the 32 bit (Wow6432Node) or 64 bit regular registry key
/// </summary>
public static class RegistryWOW6432
{
#region Member Variables
#region Read 64bit Reg from 32bit app
public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);
[DllImport("Advapi32.dll")]
static extern uint RegOpenKeyEx(
UIntPtr hKey,
string lpSubKey,
uint ulOptions,
int samDesired,
out int phkResult);
[DllImport("Advapi32.dll")]
static extern uint RegCloseKey(int hKey);
[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
public static extern int RegQueryValueEx(
int hKey,
string lpValueName,
int lpReserved,
ref RegistryValueKind lpType,
StringBuilder lpData,
ref uint lpcbData);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegQueryValueEx")]
private static extern int RegQueryValueEx(
int hKey,
string lpValueName,
int lpReserved,
ref RegistryValueKind lpType,
[Out] byte[] lpData,
ref uint lpcbData);
#endregion
#endregion
#region Functions
public static string GetRegKey64(this RegistryKey inKey, String inPropertyName)
{
string strKey = inKey.ToString();
string regHive = strKey.Split('\\')[0];
string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName);
}
public static string GetRegKey32(this RegistryKey inKey, String inPropertyName)
{
string strKey = inKey.ToString();
string regHive = strKey.Split('\\')[0];
string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
return GetRegKey64(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName);
}
public static byte[] GetRegKey64AsByteArray(this RegistryKey inKey, String inPropertyName)
{
string strKey = inKey.ToString();
string regHive = strKey.Split('\\')[0];
string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
return GetRegKey64AsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName);
}
public static byte[] GetRegKey32AsByteArray(this RegistryKey inKey, String inPropertyName)
{
string strKey = inKey.ToString();
string regHive = strKey.Split('\\')[0];
string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
return GetRegKey64AsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName);
}
private static UIntPtr GetRegHiveFromString(string inString)
{
if (inString == "HKEY_LOCAL_MACHINE")
return HKEY_LOCAL_MACHINE;
if (inString == "HKEY_CURRENT_USER")
return HKEY_CURRENT_USER;
return UIntPtr.Zero;
}
static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
{
//UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
int hkey = 0;
try
{
uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
if (0 != lResult) return null;
RegistryValueKind lpType = 0;
uint lpcbData = 1024;
StringBuilder strBuffer = new StringBuilder(1024);
RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, strBuffer, ref lpcbData);
string value = strBuffer.ToString();
return value;
}
finally
{
if (0 != hkey) RegCloseKey(hkey);
}
}
static public byte[] GetRegKey64AsByteArray(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
{
int hkey = 0;
try
{
uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
if (0 != lResult) return null;
RegistryValueKind lpType = 0;
uint lpcbData = 2048;
// Just make a big buffer the first time
byte[] byteBuffer = new byte[1000];
// The first time, get the real size
RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);
// Now create a correctly sized buffer
byteBuffer = new byte[lpcbData];
// now get the real value
RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);
return byteBuffer;
}
finally
{
if (0 != hkey) RegCloseKey(hkey);
}
}
#endregion
#region Enums
public enum RegSAM
{
QueryValue = 0x0001,
SetValue = 0x0002,
CreateSubKey = 0x0004,
EnumerateSubKeys = 0x0008,
Notify = 0x0010,
CreateLink = 0x0020,
WOW64_32Key = 0x0200,
WOW64_64Key = 0x0100,
WOW64_Res = 0x0300,
Read = 0x00020019,
Write = 0x00020006,
Execute = 0x00020019,
AllAccess = 0x000f003f
}
#endregion
}
}
using Microsoft.Win32;
namespace Read64bitRegistryFrom32bitApp
{
class Program
{
static void Main(string[] args)
{
string value64 = string.Empty;
string value32 = string.Empty;
byte[] byteValue64 = new byte[1024];
byte[] byteValue32 = new byte[1024];
RegistryKey localKey = Registry.LocalMachine;
localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
value32 = localKey.GetRegKey32("RegisteredOrganization");
value64 = localKey.GetRegKey64("RegisteredOrganization");
// byteValue32 = localKey.GetRegKey32AsByteArray("DigitalProductId"); // Key doesn't exist by default in 32 bit
byteValue64 = localKey.GetRegKey64AsByteArray("DigitalProductId");
}
}
}
}
Copyright ® Rhyous.com – Linking to this post is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.
Here is a simple snippet to add to Visual Studio if you want:
Place it here for Visual Studio 2010: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Visual C#
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>classr</Title>
<Shortcut>classr</Shortcut>
<Description>Code snippet for class with prepopulated regions.</Description>
<Author>Microsoft Corporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>name</ID>
<ToolTip>Class name</ToolTip>
<Default>MyClass</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[class $name$
{
#region Member Fields
#endregion
#region Constructor
/// <summary>
/// The default constructor
/// </summary>
public $name$()
{
}
#endregion
#region Properties
#endregion
#region Functions
#endregion
#region enums
#endregion
$selected$$end$
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
WPF provides a ProgressBar control. But there isn’t really a manual for it, especially if you want to follow MVVM.
So I am going to make a little application that counts from zero to ten and tracks the progress. You are going to see when it is OK to use the foreground and when it is not OK but better to use BackgroundWorker.
While much of this code may be production ready, you should be aware that this code intentionally implements a foreground process that is an example of what not to do.
There are two basic classes used for MVVM.
These are found on different blogs and different posts all over the internet, so I would say they are public domain, or free and unlicensed.
class ProgressBarViewModel : ViewModelBase
{
}
This will be populated as we create our View.
Ok, so lets create the GUI.
Here is the XAML.
<Window x:Class="WPFProgressBarUsingBackgroundWorker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFProgressBarUsingBackgroundWorker"
Title="MainWindow" >
<Window.Resources>
<local:ProgressBarViewModel x:Key="PBVM" />
</Window.Resources>
<Grid>
<StackPanel>
<Label Content="{Binding Path=Value}" DataContext="{StaticResource ResourceKey=PBVM}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="labelNumberCounter" VerticalAlignment="Center" FontSize="175" />
<ProgressBar Margin="0,3,0,3" Height="20" Name="progressBar" Value="{Binding Path=Value}" DataContext="{StaticResource ResourceKey=PBVM}" Minimum="{Binding Min}" Maximum="{Binding Max}"/>
<Button Command="{Binding Path=IncrementBy1}" Content="Manual Count" DataContext="{StaticResource PBVM}" Height="23" IsEnabled="{Binding Path=IsNotInProgress}" Name="button1" Width="Auto" />
<Button Margin="0,3,0,3" IsEnabled="{Binding Path=IsNotInProgress}" Command="{Binding Path=IncrementAsForegroundProcess}" DataContext="{StaticResource ResourceKey=PBVM}" Content="Count to 10 as a foreground process" HorizontalAlignment="Stretch" Height="23" Name="buttonForeground" VerticalAlignment="Top" Width="Auto" />
<Button Margin="0,3,0,3" IsEnabled="{Binding Path=IsNotInProgress}" Command="{Binding Path=IncrementAsBackgroundProcess}" DataContext="{StaticResource ResourceKey=PBVM}" Content="Count to 10 as a background process" HorizontalAlignment="Stretch" Height="23" Name="buttonBackground" VerticalAlignment="Top" Width="Auto" />
<Button Command="{Binding Path=ResetCounter}" Content="Reset" DataContext="{StaticResource PBVM}" Height="23" IsEnabled="{Binding Path=IsNotInProgress}" Name="buttonReset" Width="Auto" />
</StackPanel>
</Grid>
</Window>
Here is the code for the ProgressBarViewModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Text;
using System.Windows.Input;
using MVVM;
namespace WPFProgressBarUsingBackgroundWorker
{
class ProgressBarViewModel : ViewModelBase
{
#region Member Fields
Double _Value;
bool _IsInProgress;
int _Min = 0, _Max = 10;
#endregion
#region Member RelayCommands that implement ICommand
RelayCommand _Increment;
RelayCommand _IncrementBy1;
RelayCommand _IncrementAsBackgroundProcess;
RelayCommand _ResetCounter;
#endregion
#region Constructors
/// <summary>
/// The default constructor
/// </summary>
public ProgressBarViewModel()
{
}
#endregion
#region Properties
/// <summary>
/// Used to mark if the counter is in progress so the counter can't be started
/// while it is already running.
/// </summary>
public bool IsInProgress
{
get { return _IsInProgress; }
set
{
_IsInProgress = value;
NotifyPropertyChanged("IsInProgress");
NotifyPropertyChanged("IsNotInProgress");
}
}
public bool IsNotInProgress
{
get { return !IsInProgress; }
}
public int Max
{
get { return _Max; }
set { _Max = value; NotifyPropertyChanged("Max"); }
}
public int Min
{
get { return _Min; }
set { _Min = value; NotifyPropertyChanged("Min"); }
}
/// <summary>
/// This is the Value. The Counter should display this.
/// </summary>
public Double Value
{
get { return _Value; }
set
{
if (value <= _Max)
{
if (value >= _Min) { _Value = value; }
else { _Value = _Min; }
}
else { _Value = _Max; }
NotifyPropertyChanged("Value");
}
}
#region ICommand Properties
/// <summary>
/// An ICommand representation of the Increment() function.
/// </summary>
public ICommand IncrementBy1
{
get
{
if (_IncrementBy1 == null)
{
_IncrementBy1 = new RelayCommand(param => this.Increment());
}
return _IncrementBy1;
}
}
/// <summary>
/// An ICommand representation of the IncrementProgressForegroundWorker() function.
/// </summary>
public ICommand IncrementAsForegroundProcess
{
get
{
if (_Increment == null)
{
_Increment = new RelayCommand(param => this.IncrementProgressForeground());
}
return _Increment;
}
}
/// <summary>
/// An ICommand representation of the IncrementProgressForeground() function.
/// </summary>
public ICommand IncrementAsBackgroundProcess
{
get
{
if (_IncrementAsBackgroundProcess == null)
{
_IncrementAsBackgroundProcess = new RelayCommand(param => this.IncrementProgressBackgroundWorker());
}
return _IncrementAsBackgroundProcess;
}
}
/// <summary>
/// An ICommand representation of the Reset() function.
/// </summary>
public ICommand ResetCounter
{
get
{
if (_ResetCounter == null)
{
_ResetCounter = new RelayCommand(param => this.Reset());
}
return _ResetCounter;
}
}
#endregion ICommand Properties
#endregion
#region Functions
/// <summary>
/// This function manually increments the counter by 1 in the foreground.
/// Because it only increments by one, the WPF control bound to Value will
/// display the new value when this function completes.
/// </summary>
public void Increment()
{
// If we are in progress already, don't do anything
if (IsInProgress)
return;
// If the value is already at 10, start the counting over.
if (Value == 10)
Reset();
Value++;
}
/// <summary>
/// This function starts the counter as a foreground process.
/// This doesn't work. It counts to 10 but the UI is not updated
/// until the function completes. This is especially problematic
/// since the buttons are left enabled.
/// </summary>
public void IncrementProgressForeground()
{
// If we are in progress already, don't do anything
if (IsInProgress)
return;
Reset();
IsInProgress = true;
Value = 0;
for (int i = _Min; i < _Max; i++)
{
Value++;
Thread.Sleep(1000);
}
IsInProgress = false;
}
/// <summary>
/// This starts the counter as a background process.
/// </summary>
public void IncrementProgressBackgroundWorker()
{
// If we are in progress already, don't do anything
if (IsInProgress)
return;
Reset();
IsInProgress = true;
BackgroundWorker worker = new BackgroundWorker();
// Configure the function that will run when started
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
/*The progress reporting is not needed with this implementation and is therefore
commented out. However, in your more complex application, you may have a use for
for this.
//Enable progress and configure the progress function
worker.WorkerReportsProgress = true;
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
*/
// Configure the function to run when completed
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
// Launch the worker
worker.RunWorkerAsync();
}
/// <summary>
/// This is the function that is called when the worker is launched with the RunWorkerAsync() call.
/// </summary>
/// <param name="sender">The worker as Object, but it can be cast to a worker.</param>
/// <param name="e">The DoWorkEventArgs object.</param>
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = _Min; i < _Max; i++)
{
Value++;
Thread.Sleep(1000);
}
}
/// <summary>
/// This worker_ProgressChanged function is not in use for this project. Thanks to INotifyPropertyChanged, this is
/// completely unnecessary.
/// </summary>
/// <param name="sender">The worker as Object, but it can be cast to a worker.</param>
/// <param name="e">The ProgressChangedEventArgs object.</param>
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Does nothing yet
throw new NotImplementedException();
}
/// <summary>
/// This worker_RunWorkerCompleted is called when the worker is finished.
/// </summary>
/// <param name="sender">The worker as Object, but it can be cast to a worker.</param>
/// <param name="e">The RunWorkerCompletedEventArgs object.</param>
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
IsInProgress = false;
}
/// <summary>
/// This function resets the Value of the counter to 0.
/// </summary>
private void Reset()
{
Value = Min;
}
#endregion
}
}
I’m sorry that this is not the most Newbie proof post. But I tried to comment like crazy the code so you can get through it.
Now if you find a discrepancy in my walk-through, please comment. Also, if it is easier for you to just download the project, here it is:
WPFProgressBarUsingBackgroundWorker.zip
I don’t know if you, like me, have a development box running Visual Studio 2010 and VMWare workstation. I develop in C# and WPF, and test the product in a VM. Then sometimes, when I work from home, I remote desktop into my development box.
When I am using RDP to remote control a VMWare Workstation host, and I run a WPF Application inside a VM, the WPF application doesn’t display. The window opens, and you see the frame of your windows, but the inside is just blank or a white/gray box. None of the WPF Controls are visible.
I have found two ways to fix this. One is permanent and one is temporary.
Option 1 – (Permanent) Set this registry key. Read more about this here on MSDN: Graphics Rendering Registry Settings
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics] "DisableHWAcceleration"=dword:00000001
Option 2 – (Temporary) Or just reboot the VM while connected to the VMWare Workstation host via RDP. It seems that the VM boots and the OS detects the lack of support and disabled hardware acceleration. However, once you reboot when you are not RDP’ed into the VMWare Workstation host, you have hardware acceleration back.
I took me a long time to figure this out, because there was little to nothing in a Google search. I came across this solution while looking for something else a month or so ago, and needed to use it again when working from home last night. I thought I would post it so I never have to look for it again.
Well, if you have read my blog at all, you will realize that I have a developer job writing in C# on Windows, but it is my personal hobby to use FreeBSD.
I am very excited about Mono. I love the C# language. I also love FreeBSD.
I am going to go ahead and say something bold. Few people now realize this yet, but the ability to code in C# on open source platforms is going to be the single most important feature in the coming years. It will eventually be a standard library that will exist or be one of the first items installed on every system.
For more information:
http://www.mono-project.com/Mono:FreeBSD
Packaging for Mono and related applications on FreeBSD (http://www.freebsd.org) is handled by the BSD# Project. The purpose of this project is to maintain the existing Mono/C# ports in the FreeBSD ports tree, port new applications, and work on resolving FreeBSD specific issues with Mono. BSD# is entirely user supported and is not an official FreeBSD or Mono project.
For Licensing information:
http://www.mono-project.com/Licensing”
Mono is a port and as always a port is easy to install on FreeBSD.
Note: The version of mono in ports is not necessarily the latest and greated. I recommend that you install the latest version of mono. See this article.
Installing the latest version of Mono on FreeBSD or How to install and use portshaker?
| # # |
cd /usr/ports/lang/mono make BATCH=yes install |
The mono compiler is gmcs. It is simple to compile C# code.
using System;
namespace HelloWord
{
class HelloWord
{
static void Main(string[] args)
{
System.Console.WriteLine("Hello World");
}
}
}
Mono programs must be run using the “mono” command.
There is an IDE for Mono called MonoDevelop. MonoDevelop is a port and as always a port is easy to install on FreeBSD.
| # # |
cd /usr/ports/devel/monodevelop make BATCH=yes install |
The Mono Develop port integrated with KDE to add itself to the KDE menu under Applications | Development | MonoDevelop. So you can run it from there.
This IDE allows you to create C# solutions. It is possible to run compile them on FreeBSD and run them on Windows, or compile them on Windows and run them on FreeBSD.
C# and Mono are supposed to be cross platform. So I can write it in Windows using Visual Studio or I can write in FreeBSD using Mono Develop and either way it should run on both Windows and FreeBSD and any other platform that supports mono.
So here are the results of my quick tests:
Yes. I copied the file to a Windows 7 64 bit box and ran it. It worked.
No. I created a GTK# 2.0 project on FreeBSD in Mono Develop, and didn’t add anything to it, I just compiled it. I copied the file to windows and ran it. However, it crashed.
Supposedly you have to install the GTK# for .NET on the windows box, but it still didn’t work.
Not at first. I created a basic Windows Form application, and didn’t add anything to it, I just compiled it. I copied it to FreeBSD and ran it. It crashed. However, by default .NET 4.0 is used.
Yes, if compiled with .NET 3.5 or earlier. I changed the project to use .NET 3.5 and tried again. It ran flawlessly.
No. There is PresentationFramework assembly so the application crashes immediately. I tried multiple .NET versions.
Note: I didn’t really test much more than the basics. I just created new projects, left them as is and tried them. It would be interesting to see a more fully developed application tested and working on both platform and to know what issues were encountered in doing this.
Unfortunately there is no WPF and no plans for it. Of course, WPF stand for Windows Presentation Foundation, and so the who “Windows” part of that might need to be changed to something like XPF, Xorg Presentation foundation.
However since there is Moonlight, which is to Silverlight as Mono is to C# and .NET, and Silverlight is a subset of WPF, I have to assume that WPF will arrive in mono eventually, even if it is by way of Moonlight first.
Databinding in WPF allows binding the Command property to methods encapulated in an ICommand. By creating an ICommand object to hold an event function, the Command value can bind to the event function as an ICommand.
The goal of Model-View-ViewModel is to have zero code in the code behind of a WPF Control Instead, everything the WPF Control does happens using databinding.
While this article will show you how to do this, you be left a little fuzzy as to understanding of the implementation. It may take some time and research to fully understand everything this is doing. Understand that methods can be objects, and this is a process to turn a method object into an ICommand so it can be using in WPF for databinding.
You should have Visual Studio 2008/2010.
In Visual Studio, create a new WPF Application project and give it a name.
using System;
using System.Windows.Input;
namespace WpfDataBindingToICommand
{
public class RelayCommand : ICommand
{
#region Constructors
public RelayCommand()
{
}
#endregion
}
}
#region ICommand Members
public bool CanExecute(object parameter)
{
throw new NotImplementedException();
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
throw new NotImplementedException();
}
#endregion
#region Member Variables
readonly Action<object> _ActionToExecute;
readonly Predicate<object> __ActionCanExecute;
#endregion
public bool CanExecute(object parameter)
{
return __ActionCanExecute== null ? true : __ActionCanExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_ActionToExecute(parameter);
}
The final class looks as follows:
using System;
using System.Windows.Input;
namespace WpfDataBindingToICommand
{
/// <summary>
/// This RelayCommand object is used to encapsulate function logic into an oject that inherits ICommand.
/// </summary>
public class RelayCommand : ICommand
{
#region Member Variables
readonly Action<object> _ActionToExecute;
readonly Predicate<object> _ActionCanExecute;
#endregion
#region Constructors
/// <summary>
/// This creates a new RelayCommand.
/// </summary>
/// <param name="inActionToExecute">This is the logic of the actin to execute. This objects is usually a method that returns void.</param>
public RelayCommand(Action<object> inActionToExecute)
: this(inActionToExecute, null)
{
}
/// <summary>
/// This creates a new RelayCommand.
/// </summary>
/// <param name="inActionToExecute">This is the logic of the actin to execute. This objects is usually a method that returns void.</param>
/// <param name="inActionCanExecute">This is the logic for whether the action can execute.</param>
public RelayCommand(Action<object> inActionToExecute, Predicate<Object> inActionCanExecute)
{
if (inActionToExecute == null)
throw new ArgumentNullException("execute");
_ActionToExecute = inActionToExecute;
_ActionCanExecute = inActionCanExecute;
}
#endregion
#region ICommand Members
public bool CanExecute(object parameter)
{
return _ActionCanExecute == null ? true : _ActionCanExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_ActionToExecute(parameter);
}
#endregion
}
}
Step 2 – Creating a ViewModelBase abstract base class
This object is used to create common logic for all objects that will be using in Binding. This object will implement INotifyPropertyChanged so it only has to be implemented once.
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Functions
protected void NotifyPropertyChanged(String inPropertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(inPropertyName));
}
}
#endregion
The final object looks as follows:
using System;
using System.ComponentModel;
namespace WpfDataBindingToICommand
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
#region Constructors
public ViewModelBase()
{
}
#endregion
#region Functions
protected void NotifyPropertyChanged(String inPropertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(inPropertyName));
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
Note: You may also want to implement IDisposable.
We are going to have the ViewModel and business in the same object for this example, but sometimes you will have a separate ViewModel object that represents your data/business.
using System;
using System.Windows;
using System.Windows.Input;
namespace WpfDataBindingToICommand
{
public class SampleViewModel : ViewModelBase
{
#region Constructors
public SampleViewModel()
{
}
#endregion
}
}
public class SampleViewModel : ViewModelBase
{
string _Message = "Hello. This is the default message.";
public string Message
{
get { return _Message; }
set
{
_Message = value;
NotifyPropertyChanged("Message");
}
}
}
public void ShowMessage(String inMessage)
{
MessageBox.Show(inMessage);
}
RelayCommand _ShowMessageCommand;
public ICommand ShowMessageCommand
{
get
{
if (_ShowMessageCommand == null)
{
_ShowMessageCommand = new RelayCommand(param => this.ShowMessage(Message));
}
return _ShowMessageCommand;
}
}
Note: Notice that in order to pass the ShowMessage method, instead of the return value of the function, into the RelayCommand objectwhich is void anyway, the param => syntax is used.
The final SampleViewModel looks as follows.
using System;
using System.Windows;
using System.Windows.Input;
namespace WpfDataBindingToICommand
{
public class SampleViewModel : ViewModelBase
{
#region Member Variables
string _Message = "Hello. This is the default message.";
RelayCommand _ShowMessageCommand;
#endregion
#region Constructors
public SampleViewModel()
{
}
#endregion
#region Properties
public string Message
{
get { return _Message; }
set
{
_Message = value;
NotifyPropertyChanged("Message");
}
}
public ICommand ShowMessageCommand
{
get
{
if (_ShowMessageCommand == null)
{
_ShowMessageCommand = new RelayCommand(param => this.ShowMessage(Message));
}
return _ShowMessageCommand;
}
}
#endregion
#region Functions
public void ShowMessage(String inMessage)
{
MessageBox.Show(inMessage);
}
#endregion
#region Enums
#endregion
}
}
Ok, so lets modify the XAML of the default MainWindow.xaml code that was auto-created with the project. We will keep it simple and have a text box and a button to pop up the message.
Note: For this simple program all the work we did to implement databinding for binding events to methods seems like an absurd burden. However, for large applications, this design will lead to a better way to manage your code. It will decouple your GUI from your code, making future refactoring of the GUI much easier. This also improves the ability to make minor changes to the GUI. It also makes the code more sustainable and more easily tested. Unit tests are more effective as the GUI layer is not required and most functions are in the business layer.
<Window x:Class="WpfDataBindingToICommand.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfDataBindingToICommand"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:SampleViewModel x:Key="Sample" />
</Window.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid DataContext="{StaticResource ResourceKey=Sample}">
<TextBox Text="{Binding Message}" Name="textBoxMessage" Margin="5"/>
<Button Command="{Binding ShowMessageCommand}" Content="ShowMessage" Grid.Row="1" Height="23" Name="buttonShowMessage" HorizontalAlignment="Right" Width="Auto" Margin="5"/>
You are done. The final XAML is as follows:
<Window x:Class="WpfDataBindingToICommand.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfDataBindingToICommand"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:SampleViewModel x:Key="Sample" />
</Window.Resources>
<Grid DataContext="{StaticResource ResourceKey=Sample}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Message}" Name="textBoxMessage" Margin="5"/>
<Button Command="{Binding ShowMessageCommand}" Content="ShowMessage" Grid.Row="1" Height="23" Name="buttonShowMessage" HorizontalAlignment="Right" Width="Auto" Margin="5"/>
</Grid>
</Window>
Notice that we never touched the code behind of MainWindow. The GUI and the code are as decoupled as possible. Not event the event functions are needed in the code behind. This decoupling or GUI and code is our goal.
WPF Apps With The Model-View-ViewModel Design Pattern
Understanding Routed Events and Commands In WPF
Copyright ® Rhyous.com – Linking to this page is allowed without permission and as many as ten lines of this page can be used along with this link. Any other use of this page is allowed only by permission of Rhyous.com.
You have your WPF Window and you have an object that you don’t want to make a static resource. You want to declare it as a member variable in the code.
using System;
using System.ComponentModel;
namespace WPFPerson
{
public class Person : INotifyPropertyChanged
{
#region Member Variables
String _FirstName;
String _LastName;
#endregion
#region Constructors
/*
* The default constructor
*/
public Person()
{
}
#endregion
#region Properties
public String FirstName
{
get { return _FirstName; }
set
{
_FirstName = value;
NotifyPropertyChanged("FirstName");
}
}
public String LastName
{
get { return _LastName; }
set
{
_LastName = value;
NotifyPropertyChanged("LastName");
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
MainWindow.xaml (WPF Window)
<Window x:Class="WPFPerson.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >
<Grid Name="PersonGrid" >
<TextBox Height="23" HorizontalAlignment="Left" Margin="173,87,0,0" Name="textBoxFirstName" VerticalAlignment="Top" Width="234" Text="{Binding FirstName, Mode=TwoWay}" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="173,116,0,0" Name="textBoxLastName" VerticalAlignment="Top" Width="234" Text="{Binding LastName, Mode=TwoWay}"/>
<Label Content="FirstName" Height="28" HorizontalAlignment="Left" Margin="103,85,0,0" Name="labelFirstName" VerticalAlignment="Top" />
<Label Content="LastName" Height="28" HorizontalAlignment="Left" Margin="103,114,0,0" Name="labelLastName" VerticalAlignment="Top" />
<Button Content="Defaults" Height="23" HorizontalAlignment="Left" Margin="337,199,0,0" Name="buttonDefaults" VerticalAlignment="Top" Width="75" Click="buttonDefaults_Click" />
</Grid>
</Window>
MainWindow.cs (Code Behind)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace WPFPerson
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly Person _Person;
public MainWindow()
{
_Person = new Person();
InitializeComponent();
textBoxFirstName.DataContext = _Person;
textBoxLastName.DataContext = _Person;
}
private void buttonDefaults_Click(object sender, RoutedEventArgs e)
{
_Person.FirstName = "Jared";
_Person.LastName = "Barneck";
}
}
}
Example 2 – Forthcoming…
Example 3 – Forthcoming…
Sources:
http://www.wrox.com/WileyCDA/Section/Windows-Presentation-Foundation-WPF-Data-Binding-with-C-2005.id-305562.html
In C++ and in PHP and other languages, a great logging feature is the ability to log the file and line number where the log occurs.
These unfortunately do not exist. I have been searching even in the latest .NET 4.0 and haven’t found them. If they are there, they are hidden. Having these two variables is an extremely useful feature in other languages and it appears to be a feature very overlooked by the C# developers. However, maybe they didn’t overlook it. Maybe there is a good reason that it is not there.
There were a couple of solutions floating around online but many of them only worked with debugging enabled (or in release if the pdb file is in the same directory).
Here is one example that only works in debugging (or in release if the pdb file is in the same directory).
StackHelper.cs
using System;
using System.Diagnostics;
namespace FileAndLineNumberInCSharpLog
{
public static class StackHelper
{
public static String ReportError(string Message)
{
// Get the frame one step up the call tree
StackFrame CallStack = new StackFrame(1, true);
// These will now show the file and line number of the ReportError
string SourceFile = CallStack.GetFileName();
int SourceLine = CallStack.GetFileLineNumber();
return "Error: " + Message + "\nFile: " + SourceFile + "\nLine: " + SourceLine.ToString();
}
public static int __LINE__
{
get
{
StackFrame CallStack = new StackFrame(1, true);
int line = new int();
line += CallStack.GetFileLineNumber();
return line;
}
}
public static string __FILE__
{
get
{
StackFrame CallStack = new StackFrame(1, true);
string temp = CallStack.GetFileName();
String file = String.Copy(String.IsNullOrEmpty(temp)?"":temp);
return String.IsNullOrEmpty(file) ? "": file;
}
}
}
}
Here is a little Program.cs that shows how to use it.
using System;
namespace FileAndLineNumberInCSharpLog
{
class Program
{
static void Main(string[] args)
{
int x = 100;
int y = 200;
int z = x * y;
Console.WriteLine(StackHelper.ReportError("New Error"));
}
}
}
Unfortunately if the above does only work in release if the pdb file is available.
Well, according to this MSDN forum post, it simply cannot be done.
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/6a7b021c-ec81-47c5-8f6a-2e280d548f3f
If I ever find a way to do it, I will post it.
So for troubleshooting a production file at a customer’s site, you pretty much have to send out your pdb file to them when they need it. There are a lot of benefits to C# and this lacking feature is one of the eye sores.
Ok, so if you are going to have a string visible in your WPF application and your application can be in multiple languages, you are facing the localization problem.
Usually people as themselves two questions:
The answers are usually not now and I don’t know. So no localization work is done at first. Later, you wish you were more prepared for localization.
Well, I am here to tell you that you can at least prepare to be localized by doing a few simple steps:
If you are going to have a string in your WPF application, it is a good idea to store those strings in a centralized place for localization purposes. Usually in Visual Studio, that is in Resources.resx.
Often a string is entered directly into an the WPF XAML. This is not recommended. Maybe you are thinking that you don’t need to localize your application, so this is not important to you. Ok, really what you are thinking is:
“I don’t know how to do it and if I ever get big enough to need localization, at that point, I will figure it out.”
Well, what if I told you that using Resources.resx is extremely easy?
What if I told you that it hardly takes more time at all?
If it easy and hardly time consuming at all, you would do it, right? I would. Hence this post.
I have a project called LicenseAgreementManager. Right now this only needs to display a license agreement in English, but maybe someday, this will need to display a license agreement in any language.
In Visual Studio, create a new WPF Applcation project.
I named my project LicenseAgreementManager.
Right away, you already have at least one string statically entered into your XAML, the text for the window title.


You now have a publicized Resource.resx file and a few strings inside it.
<Window x:Class="LicenseAgreementManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
<Window x:Class="LicenseAgreementManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:LicenseAgreementManager.Properties"
Title="MainWindow" Height="350" Width="525">
<Window x:Class="LicenseAgreementManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:LicenseAgreementManager.Properties"
Title="{x:Static p:Resources.EULA_Title}"
Height="350" Width="525">
That was pretty easy, wasn’t it.
As you add elements that have strings, use the Resources.resx.
I have just added some items and removed the sizing as best as possible. Here is my XAML.
<Window x:Class="LicenseAgreementManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:LicenseAgreementManager.Properties"
Title="{x:Static p:Resources.EULA_Title}"
SizeToContent="WidthAndHeight"
xml:lang="en-US">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RichTextBox Name="_EulaTextBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<StackPanel Grid.Row="1" Margin="0,10,0,0" Name="stackPanel2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<RadioButton Content="{x:Static p:Resources.EULA_Accept}" Margin="20,20,20,0" Name="radioButton1" />
<RadioButton Content="{x:Static p:Resources.EULA_NotAccept}" Margin="20,20,20,0" Name="radioButton2" />
<Button Content="{x:Static p:Resources.Next_Button}" Name="button1" Margin="20,20,35,20" HorizontalAlignment="Right" />
</StackPanel>
</Grid>
</Window>
You don’t have to be localized to be prepared for easy localization. By doing the above simple steps, when it comes time to add localization, you will be ready.
If you want to go on an finish localization. You might want to read some of my sources.
Sources:
http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=52910
http://msdn.microsoft.com/en-us/library/ms788718%28v=VS.90%29.aspx
http://msdn.microsoft.com/en-us/library/ms746621.aspx