Jesper Niedermann's .NET Blog
about .NET and related technologies RSS 2.0
# Tuesday, 31 August 2010

The new Guidance Automation Framework GAX 2010 and GAT 2010 which is installed through the Extension Manager in Visual Studio 2010, provides a nicer usability experience compared to the Visual Studio 2008 predecessor. It is installed using the new vsix installer. A vsix install is much nicer than the old msi install since it integrates into Visual Studio. You can uninstall using the Extension Manager and if a new version comes out it should appear on the Updates tab of the extension manager.

Another nice thing is that a generated factory template solution now only consists of one project which itself results in a vsix file. So the installer of your own generated factories will also be vsix files. Nice…

But nicest of all is the fact that it is automatically integrated with the Visual Studio 2010 Experimental Instance (formerly known as Experimental Hive). Before you had to manually edit your recipes to get them to register in the Experimental Hive. But know you just press Ctrl+F5 and the Experimental Instance is automatically launched with your factory installed. It is now almost easy to debug your recipes. :)

But apparently there are few weird bugs in GAX/GAT 2010. One I run into all the time is this error:

Unable to read the project file 'Something.csproj'.

C:\Something\Something\Something.csproj(354,3): The imported project "C:\Microsoft.Practices.RecipeFramework.Build.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

Which happens when I try to open a Guidance Automation solution.

For some reason the declaration of the variable RecipeFramework in the project file is not provided. This I deal with by editing the Project file by hand and adding a declaration to the end of the first PropertyGroup like this:

 

  <RecipeFrameworkPath>$(DevEnvDir)Extensions\Microsoft patterns and practices\GAX 2010\2.0.20406.0</RecipeFrameworkPath>

After applying this fix I can open the solution.

I have read somewhere that it is important to adhere to the following install order:

    1. Visual Studio 2010 Ultimate or Professional (obviously)
    2. The Visual Studio 2010 SDK
    3. GAX 2010
    4. GAT 2010

And this might be what I have screwed up on the particular machine where I get the error.

Anyway the above mentioned fix works. And overall I am very satisfied with the new improvements in GAX/GAT.

Tuesday, 31 August 2010 17:31:11 (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET | GAX | Tips & Tricks | Visual Studio
# Wednesday, 12 May 2010

Windows developers who are used to click events in WinForms, WPF or Silverlight might miss click and double click events, but because of the game loop where everything is drawn and updated every few milliseconds an event based approach is probably not a good idea in most cases. Not so much because of the performance of an event based approach, but more because the complexity is overwhelming. If several users clicks and double clicks several keys on the keyboard simultaneously, how would you decide which of these are clicked and in which order, and further more it is not obvious to subscribers of the events that they are in the game loop, so they might do code which performs inadequately.

I have made a few generic classes that expands the MouseState, GamePadState and KeyboardState in order to make click “events” available. But of course I utilize the standard polling mechanism in XNA which is to call GetState() on each device.

The approach is that I call my own version of GetState() in the main game loop. My GetState() method first enqueues the state in a Queue, and then dequeues all states older than 500 ms, before the state is returned. In this way a historical map of user interactions is maintained at all times.

Now I can simply check if a key or button was clicked by checking if the key was pressed and then released “historically”. Similarly I can check for double click by checking if the key or button was pressed, then released, then pressed again and then released again.

Now you probably realize why I go back 500 ms. It is because this is the standard time in which a double click should be executed.

I have used this approach in the game Protect the Carrot at http://ptc.codeplex.com and it works like a charm (The url for the game does not work today, since the game will only be published in a few weeks).

Here is the implementation of the MouseExtended class which uses this approach:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;

namespace PTC.Input
{
public class MouseExtended : InputDeviceExtended<MouseState>
{
private static MouseExtended m_Current;
public static MouseExtended Current
{
get
{
if (m_Current == null)
{
m_Current = new MouseExtended();
}
return m_Current;
}
}

public MouseState GetState(GameTime currentTime)
{
DequeueOldStates(currentTime);
MouseState state = Mouse.GetState();
EnqueueNewState(currentTime, state);
return state;
}

private bool ClickCount(MouseButton checkButton, int requiredCount)
{
ButtonState found = ButtonState.Released;
int count = 0;
foreach (InputStateExtended<MouseState> stateExt in RecordedStates)
{
if (found == ButtonState.Pressed &&
ButtonStateToCheck(stateExt.State, checkButton) == ButtonState.Released)
{
count++;
if (count >= requiredCount)
return true;
}
found = ButtonStateToCheck(stateExt.State, checkButton);
}
return false;
}

private ButtonState ButtonStateToCheck(MouseState state, MouseButton checkButton)
{
switch (checkButton)
{
case MouseButton.Left:
return state.LeftButton;
case MouseButton.Middle:
return state.MiddleButton;
case MouseButton.Right:
return state.RightButton;
case MouseButton.XButton1:
return state.XButton1;
case MouseButton.XButton2:
return state.XButton2;
default:
return state.LeftButton;
}
}

public bool WasSingleClick(MouseButton checkButton)
{
return(ClickCount(checkButton, 1));
}

public bool WasDoubleClick(MouseButton checkButton)
{
return (ClickCount(checkButton, 2));
}

}
}

And here is the generic InputDeviceExtended class which MouseExtended inherits:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace PTC.Input
{
public class InputDeviceExtended<S> where S : struct
{
private Queue<InputStateExtended<S>> m_RecordedStates = new Queue<InputStateExtended<S>>();

public Queue<InputStateExtended<S>> RecordedStates
{
get { return m_RecordedStates; }
}

private Stack<InputStateExtended<S>> m_StatesForReuse = new Stack<InputStateExtended<S>>();

protected void EnqueueNewState(GameTime time, S state)
{
if (!state.Equals(m_CurrentState))
{
m_CurrentState = state;
m_RecordedStates.Enqueue(CreateState(time, state));
}
}

private S m_CurrentState;
public S CurrentState
{
get { return m_CurrentState; }
}

protected void DequeueOldStates(GameTime currentTime)
{
InputStateExtended<S> state = null;
if (m_RecordedStates.Count > 0)
{
state = m_RecordedStates.Peek();
}
if (state != null && state.StateTime < currentTime.TotalRealTime.Subtract(new TimeSpan(0, 0, 0, 0, InputDeviceConstants.ClickCountTimeMS)))
{
m_StatesForReuse.Push(m_RecordedStates.Dequeue());
DequeueOldStates(currentTime);
}
}

private InputStateExtended<S> CreateState(GameTime time, S state)
{
if (m_StatesForReuse.Count > 0)
{
//Reuses the object to fight of the GC
InputStateExtended<S> stateExt = m_StatesForReuse.Pop();
stateExt.StateTime = time.TotalRealTime;
stateExt.State = state;
return stateExt;
}
else
{
return new InputStateExtended<S>(time, state);
}
}
}
}

Notice that the Recorded States are reused. When dequeued from the queue the are added to a reuse stack. This is a standard trick to fight of the Garbage Collector, by always keeping a reference to objects on the heap they never become garbage + they are reused so the memory use will not explode.

I have also implemented the necessary extended classes for the Keyboard and the gamepad. I have included them in the attachment to this post. I have not tested the GamepadExtended class since I do not own a Gamepad, but it is implemented exactly as the keyboard and mouse classes and ought to work.

To wire up the new classes you just add the relevant Getstate() calls to the Update game loop like so:

protected override void Update(GameTime gameTime)
{
KeyboardExtended.Current.GetState(gameTime);
MouseExtended.Current.GetState(gameTime);
base.Update(gameTime);
}

And then you can check for click and double click “events”. For instance you check for double click of the left mouse button like this:

if(MouseExtended.Current.WasDoubleClick(MouseButton.Left)))
{
//Do double click reaction
}

Hope you like the stuff.And look out for the amazing “Protect The Carrot” game within the next month or so, at http://ptc.codeplex.com

In InputDeviceExtended.zip I have included the code for all the InputDevice classes.

Wednesday, 12 May 2010 21:38:51 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tips & Tricks | XNA
# Friday, 13 November 2009

In the Day View project I needed to open a Windows 7 Sticky Note programmatically and write to it. Unfortunately I found out that there is not an API for the Sticky Notes application. At least not a managed one.

So I had to fake it and make my own API. I have made a small class that basicly uses Process.Start to open the program, and SendKeys to write to the Note.

Here it is:

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace DayView
{
public class StickyNote
{
private const string m_ProcessName = "StikyNot";
private readonly string m_ProcessFileName = Path.Combine(Environment.SystemDirectory, "StikyNot.exe");
private event EventHandler m_Activated = delegate { };
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

public void Activate()
{
bool makeNewNote = true;
Process p = FindProcess();
if (p == null)
{
p = StartProcess();
if (!NoteContainsText(p.MainWindowHandle))
{
makeNewNote = false;
}
}
var state = new StickyNoteState();
state.MakeNewNote = makeNewNote;
state.StickyNoteProcess = p;
ThreadPool.QueueUserWorkItem(Activate, state);
}

private void Activate(object state)
{
var stickyNoteState = state as StickyNoteState;
if (stickyNoteState.MakeNewNote)
{
NewNote(stickyNoteState.StickyNoteProcess);
}
OnActivated();
}

private Process StartProcess()
{
var startInfo = new ProcessStartInfo(m_ProcessFileName);
Process p = Process.Start(startInfo);
Thread.Sleep(200); //This is an annoying hack. I haven't been able to find another way to be sure the process is started.
return p;
}

private void NewNote(Process p)
{
SetForegroundWindow(p.MainWindowHandle);
Signal("^n");
}

/// <summary>
/// Weird hack to find out if note contains text.
/// </summary>
/// <returns></returns>
private bool NoteContainsText(IntPtr handle)
{
string textOfClipboard = Clipboard.GetText();
Signal("^a");
Signal("^c");
Signal("{RIGHT}");
string noteText = Clipboard.GetText().Trim();
if (textOfClipboard == null)
{
Clipboard.SetText(textOfClipboard);
}
return !string.IsNullOrEmpty(noteText);
}

private Process FindProcess()
{
Process[] processes = Process.GetProcessesByName(m_ProcessName);
if(processes != null && processes.Length > 0)
{
return processes[0];
}
return null;
}

internal void OnActivated()
{
m_Activated(this, new EventArgs());
}

public event EventHandler Activated
{
add { m_Activated += value; }
remove { m_Activated -= value; }
}

public void Signal(string message)
{
SendKeys.SendWait(message);
SendKeys.Flush();
}
}

public class StickyNoteState
{
public bool MakeNewNote { get; set; }
public Process StickyNoteProcess { get; set; }

}
}

It works OK. The only really buggy thing in the code is in line 47, where I have to use a Thread.Sleep in order to make sure the note is loaded before I write to it. Unfortunately this is necessary because the Process class does not provide an event to signal when it has finished loading. I arbitrarily chose 200 milliseconds for the Sleep. Larger values might be necessary on slower computers.

In order to use the class you have to configure SendKeys in your app.config like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
</configuration>
Friday, 13 November 2009 23:28:10 (GMT Standard Time, UTC+00:00)  #    Comments [4] -
.NET | Tips & Tricks | Windows 7
# Sunday, 14 June 2009

I was using my codeplex project ManagedMenuExtensions recently when I realized that it threw an Exception, when clicking on a menu attached to a C# project under a solution folder. The reason was that the object which normally contained an EnvDTE.Project when a project was clicked contained null, when this project was contained in a solution folder.

I normally use this code to get at the selected project (m_VSStudio is the DTE object of the current solution):

private UIHierarchyItem SelectedItem
{
get
{
UIHierarchy uiHierarchy = m_VSStudio.ToolWindows.SolutionExplorer;
if(uiHierarchy == null)
return null;

object[] items = uiHierarchy.SelectedItems as object[];
if(items == null || items.Length == 0)
return null;

return items[0] as UIHierarchyItem;
}
}

The SelectedItem.Object of type object now contains a EnvDTE.Solution object if the solution is selected in the solution explorer, and guess what :O) it contains an EnvDTE.Project if a project is selected. It is this SelectedItem.Object that contains null, if the project is contained in a solution folder.

I googled this problem and found others who had the same problem, but none with a solution, so I had to come up with my own. I don't know if this behaviour is by design from Microsoft, or if it is a bug.

My Solution

Normally I would test if a project is selected with this code:

var project = SelectedItem.Object as Project;
if (project != null)
{
//Do something with the project
}

Now I use this code instead:

Project project = GetProject(SelectedItem.Object);
if (project != null)
{
//Do something with the project
}

Where I implemented GetProject(...) as:

private Project GetProject(object selectedItemObject)
{
var project = selectedItemObject as Project;
if (project != null)
return project;

var item = selectedItemObject as ProjectItem;
if (item == null)
return null;

return item.SubProject;
}

Not exactly beautiful, but that is to be expected when playing with Visual Studios AddIn model, and the kind of thing I try to hide in ManagedMenuExtensions. I haven't had a chance to look at Visual Studio 2010 yet, one could hope that they have done a better job of hiding the ugly underlying COM stuff.

 

Anyway, I hope this helps the next person who tries to search for a workaround for this rather weird behaviour.

Sunday, 14 June 2009 18:33:04 (GMT Daylight Time, UTC+01:00)  #    Comments [3] -
.NET | Tips & Tricks | Visual Studio
# Wednesday, 06 May 2009

My favourite RSS reader is GreatNews. First of all it is a standalone application, and secondly it is portable, which means I can install it on a USB key or better yet in my Dropbox which is what I do.

Well to be fair it is not portable in the purist way because it caches some stuff on the computers harddrive, but that is only for performance, so functionally GreatNews IS portable.

And GreatNews is very fast, which is just one more reason to love it.

In fact it has only one drawback, the database tends to get corrupt every 2-3 months, and there is no obvious way to repair it. I guess it will be corrected at some point in time (?) but for now it nearly made me give up on this otherwise great product.

After some googling I found that GreatNews uses an sqlite database called newsfeed.db. I couldn't really find a repair tool for it, even though I found a page which lots of tools for sqlite.

So I had to repair it in a more indirect way.

I downloaded one called sqliteman and with this I was able to make a new database called newsfeed.db and export all content from the old database and import it to the new one.

One nice sideeffect was that the database was only 1/10 in size after the import. Apparently either GreatNews or Sqllite tends to bloat the database.

After the import I replaced the old database with the new one (you should make a backup of course !), and viola it worked perfectly. So once more I am a happy user of GreatNews :O).

I cannot guarantee that this method will work for you too, perhaps I was just lucky. I advice you to keep your backup of the old newsfeed.db just in case.

P.S: To export the database you just choose "Dump database..." as shown below in a screenshot from sqliteman, which generates an SQL script that can be opened and run in the new database:

newsfeed1

Wednesday, 06 May 2009 21:34:53 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
Tips & Tricks | Tools
# Friday, 01 May 2009

If you want to Execute something on each element of the result of a Linq expression. You can either loop over the result using foreach(...) or turn the result into a List using .ToList(), and then use .Foreach(...) on the resulting list. Like this:

(from excep in ErrorList
where excep is ArgumentException select excep)
.ToList().ForEach(e => Console.WriteLine(e.Message));

This is ugly, and I prefer to make my own Extension method for IEnumerable<T> called Execute(...):

public static void Execute<T>(this IEnumerable<T> list, Action<T> action)
{
foreach(T element in list)
{
action(element);
}
}

This means you can do this instead:

(from excep in ErrorList
where excep is ArgumentException select excep)
.Execute(e => Console.WriteLine(e.Message));

Back in the days when I used Linq in a program for the first time, I wondered why there was no way to execute an action on each element of a list, so I implemented the Execute method.

It was only later that I discovered that the default way was .ToList().Foreach(...)

I must say I still prefer my original approach.

BTW: In a small none scientific test I have tested the two approaches.

With Linq To Objects iterating over 100000 integers and printing them to the Console takes about 21 seconds with the Foreach method and about 20 seconds with the Execute method, so it is even faster at least for this particular example. Though nothing to get excited about. :O)

The test was done in a Vista VPC with VS2008,

Small performance test: LinqPerfTest.zip

Friday, 01 May 2009 21:12:40 (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Linq | Tips & Tricks
# Friday, 13 March 2009

Any windows user is familiar with Windows Explorer but were you aware that one can access an ftp site or WebDAV enabled site using the Windows Explorer ? I myself haven't really been looking in to this, since I have been using Filezilla to upload files to my website, but why not use Windows Explorer ? It is always at hand with the Windows+E keystroke.

As an example I will show you have to access the http://live.sysinternals.com site via the Windows Explorer since it is a WebDAV enabled site with anonymous access. The site contains all the famous tools from Sysinternals a company which was purchased by Microsoft.

In order to connect you just have to click on the good old "Map Network Drive ..."

Temp1

Since I know the name of the subdirectory 'tools', the easiest way seems to be to map to a drive letter directly by typing the name \\live.sysinternals.com\tools in the folder textbox:

Temp2

If you are trying to connect to an ftp server the right way seems to be to click on "sign up for online storage..." After pressing "Next" twice you get this screen:

Temp3

Here you can write the name of the ftp server or website if using WebDAV, so here I could have written 'http://live.sysinternals.com'. The next screen makes you enter username/password or Anonymous access. Pretty self explanatory.

The end result is that the site appears under 'My Network Places.'

After adding the sysinternals site to your explorer you get all the usual advantages, easy copying and pasting etc.

BTW there are still reasons for using a "proper" ftp client like Filezilla, e.g. you can specify an alternative port number, which doesn't seem to be an option in the Windows Explorer.

Friday, 13 March 2009 20:58:42 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Tips & Tricks
# Wednesday, 11 March 2009

Currently I am looking into taking over a huge enterprise legacy system written mostly in C#, but also some C++. The numbers are staggering several million lines of code, 1200 GUI screen, mostly WinForms, about 750 C# projects, 150 solution files, just to mention a few. In all about 4 times larger than the largest enterprise system I have previously been working on.

Just building and deploying the system is a pretty big task since due to events beyond my control I basicly only have the sourcecode and nothing else. Not quite true because there are some documentation, but buried in the thousands of files.

When I managed to modify a build file and build the entire monster with it, it took 2½ hours to complete.

I won't even try to include all projects in a single Visual Studio file. I wonder if it would load ? This gives me a problem though. How about debugging ? I cannot press F5 for any of the visual studio projects because the build process using the build file set up a ton of config files with IP adresses, connection strings and the like. So it doesn't make sense to run the thing from Visual Studio.

But if I start up the exe assembly how do I attach a debugger ? Well, I decided to use a simple trick. I added a line of code in the top of the main() method:

static void Main(string[] args) 
{
Debugger.Break();
...

Debugger.Break() is basicly a programmatic breakpoint, but it is more than that. If no debugger is attached it asks the user for a debugger. Smart! And for the process to debug I can just choose the Visual Studio process with the project containing the exe assembly. Henceforth the control is mine.

I could even consider writing this method and using it instead:

[Conditional("DEBUG")]
private static void DebuggerBreak()
{
if(!Debugger.IsAttached)
Debugger.Break();
}

This gives me the advantage that the IL code is only build in DEBUG mode and that the Debugger is only attached if one is not attached already.

Wednesday, 11 March 2009 06:23:39 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tips & Tricks
Archive
<2017 August>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the author/Disclaimer
I am a software architect with focus on Microsoft Technologies. I have been working with these in different large companies since 1995. I am currently employed at UVdata A/S.
Here is my View Jesper Niedermann's profile on LinkedIn

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Privacy policy
The privacy policy of this site.

© Copyright 2017
Jesper Niedermann
Sign In
Statistics
Total Posts: 28
This Year: 0
This Month: 0
This Week: 0
Comments: 32
All Content © 2017, Jesper Niedermann
DasBlog theme 'Niedermann' created by Jesper Niedermann, based on 'Business' created by Christoph De Baene (delarou)