Contents tagged with .NET 4.0
-
Pomodoro Timer for the Windows 7 TaskBar
EDIT: The code is now open source on codeplex, on http://pomodorotaskbar.codeplex.com There's a new version available for download there too.
If you’re into the Pomodoro technique and looking for a pretty simple out-of-the-way timer which sits in the Windows 7 taskbar and is controlled from the Win7 JumpList, this one might be worth trying out.
NOTE: Icon overlays will NOT work if you're using small TaskBar icons!
That’s the timer looking like a tomato, with the remaining session minutes written out dynamically as icon overlay.
The timer has a couple of JumpList Tasks which you can use to control it. The program works well when “pinned” to the taskbar if you prefer it.
You can also control the timer from the main window with one large action-button (stop, start, stop ringing and restart session).
When the timer is stopped, you can just click on the remaining minutes-textbox and change the default session length to whatever you like. The value is stored.
When the session is ended, the window flashes, the tomato shakes and a ringing sound is played a few times to get your attention.
Note, this is a very simple program which I’m planning to release as open source when I’ve received some feedback. I prefer to keep it simple, but may add session logging. The name as well as the looks may change. .NET 4.0 is required.
Download the Pomodoro Timer: http://pomodorotaskbar.codeplex.com/releases/view/71998
-
Refactored Dapper Extensions
Making extensions for Dapper-dot-net was so fun and I needed a few more simple ones so I refactored a bit and made a few Update() and Delete() extensions as well. I’m also looking for Id-properties with the [Key] attribute on them. The class grew a bit, but it now supports the functions below. Note that this will only work for very simple objects and tables, but it might be helpful for some of you
I’m trying to follow the overall Dapper syntax as much as I can. If you done specify the table name with the input parameter, I’m using the name of the class/entity as table name, except where anonymous types are used.
The object I’m using for testing
public class Test { [Key] public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
Insert typed object
var entity = new Test() { Name = "Johan", Age = 44 }; connection.Insert(entity);
Insert anonymous object
connection.Insert("insert into test", new { Name = "Johan", Age = 20 });
Update typed object (where-clause built up from Id-properties)
var entity = new Test() { Id = 16, Name = "Johan", Age = 50 }; connection.Update(entity);
Delete typed object (where-clause built up from Id-properties)
var entity = new Test() { Id = 4, Name = "Johan", Age = 44 }; var deletedCount = connection.Delete(entity);
Delete anonymous object (where-clause built up from anonymous object)
var deletedCount = connection.Delete("delete from test", new { Name = "Johan" });
The Code:
public static class DapperExtensions { public static void Insert(this IDbConnection connection, object entityToInsert) { Insert(connection, null, entityToInsert); } public static void Insert(this IDbConnection connection, string sql, object entityToInsert) { var name = entityToInsert.GetType().Name; var sb = new StringBuilder(sql); if (sql == null) sb.AppendFormat("insert into {0}", name); sb.Append(" ("); BuildInsertParameters(entityToInsert, sb); sb.Append(") values ("); BuildInsertValues(entityToInsert, sb); sb.Append(")"); connection.Execute(sb.ToString(), entityToInsert); } public static int Update(this IDbConnection connection, object entityToUpdate) { return Update(connection, null, entityToUpdate); } public static int Update(this IDbConnection connection, string sql, object entityToUpdate) { var idProps = GetIdProperties(entityToUpdate); if (idProps.Count() == 0) throw new ArgumentException("Entity must have at least one [Key] property"); var name = entityToUpdate.GetType().Name; var sb = new StringBuilder(sql); if (sql == null) sb.AppendFormat("update {0}", name); sb.AppendFormat(" set "); BuildUpdateSet(entityToUpdate, sb); sb.Append(" where "); BuildWhere(sb, idProps.ToArray()); return connection.Execute(sb.ToString(), entityToUpdate); } public static int Delete<T>(this IDbConnection connection, T entityToDelete) { return Delete(connection, null, entityToDelete); } public static int Delete<T>(this IDbConnection connection, string sql, T entityToDelete) { var idProps = typeof (T).IsAnonymousType() ? GetAllProperties(entityToDelete) : GetIdProperties(entityToDelete); if (idProps.Count() == 0) throw new ArgumentException("Entity must have at least one [Key] property"); var name = entityToDelete.GetType().Name; var sb = new StringBuilder(sql); if (sql == null) sb.AppendFormat("delete from {0}", name); sb.Append(" where "); BuildWhere(sb, idProps); return connection.Execute(sb.ToString(), entityToDelete); } private static void BuildUpdateSet(object entityToUpdate, StringBuilder sb) { var nonIdProps = GetNonIdProperties(entityToUpdate).ToArray(); for (var i = 0; i < nonIdProps.Length; i++) { var property = nonIdProps[i]; sb.AppendFormat("{0} = @{1}", property.Name, property.Name); if (i < nonIdProps.Length - 1) sb.AppendFormat(", "); } } private static void BuildWhere(StringBuilder sb, IEnumerable<PropertyInfo> idProps) { for (var i = 0; i < idProps.Count(); i++) { sb.AppendFormat("{0} = @{1}", idProps.ElementAt(i).Name, idProps.ElementAt(i).Name); if (i < idProps.Count() - 1) sb.AppendFormat(" and "); } } private static void BuildInsertValues(object entityToInsert, StringBuilder sb) { var props = GetAllProperties(entityToInsert); for (var i = 0; i < props.Count(); i++) { var property = props.ElementAt(i); if (property.GetCustomAttributes(true).Where(a => a is KeyAttribute).Any()) continue; sb.AppendFormat("@{0}", property.Name); if (i < props.Count() - 1) sb.Append(", "); } } private static void BuildInsertParameters(object entityToInsert, StringBuilder sb) { var props = GetAllProperties(entityToInsert); for (var i = 0; i < props.Count(); i++) { var property = props.ElementAt(i); if (property.GetCustomAttributes(true).Where(a => a is KeyAttribute).Any()) continue; sb.Append(property.Name); if (i < props.Count() - 1) sb.Append(", "); } } private static IEnumerable<PropertyInfo> GetAllProperties(object entity) { return entity.GetType().GetProperties(); } private static IEnumerable<PropertyInfo> GetNonIdProperties(object entity) { return GetAllProperties(entity).Where(p => p.GetCustomAttributes(true).Any(a => a is KeyAttribute) == false); } private static IEnumerable<PropertyInfo> GetIdProperties(object entity) { return GetAllProperties(entity).Where( p => p.GetCustomAttributes(true).Any(a => a is KeyAttribute)); } } public static class TypeExtension { public static Boolean IsAnonymousType(this Type type) { if (type == null) return false; var hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; var nameContainsAnonymousType = type.FullName.Contains("AnonymousType"); var isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; return isAnonymousType; } }
Feel free to fork the code as much as you can, I’m too tired to stay up longer. Dapper is getting really useful
-
Simple Insert Extension for Dapper
Last week I started using Dapper (dapper-dot-net on Google Code) for a project I’m working on. Dapper is a micro ORM, which extends IDbConnection. It’s very fast and works very well for queries where you want to return both typed and dynamic lists of objects. Have a quick look at the webpage and you’ll see what I mean.
Today I needed to do some inserting, which you can do with the Execute() extension, but you’d have to type out all the “insert into xxx (col1,col2) values (@val1, @val2)” stuff. Some guys suggested to create a dapper.contrib and adding extensions of insert, update, delete and so on but it’s not there yet (at time of writing).
Anyway, the extensions in dapper are already so well written I thought it should be quite easy to just add a dead simple (or stupid if you prefer) Insert() extensions on top of the existing Execute(), and I ended up with this raw unrefactored code. All it does really is building up the SQL for the insert using some property reflection, dapper itself does the heavy lifting:
public static class DapperExtensions { public static void Insert(this IDbConnection connection, object entityToInsert, string sql = "insert into " ) { var name = entityToInsert.GetType().Name; if (sql == "insert into ") { sql = "insert into " + name + " "; } sql += " ("; for (var i = 0; i < entityToInsert.GetType().GetProperties().Length; i++) { var propertyInfo = entityToInsert.GetType().GetProperties()[i]; sql += propertyInfo.Name; if (i < entityToInsert.GetType().GetProperties().Length - 1) sql += ","; } sql += ") values ("; for (var i = 0; i < entityToInsert.GetType().GetProperties().Length; i++) { var propertyInfo = entityToInsert.GetType().GetProperties()[i]; sql += "@" + propertyInfo.Name; if (i < entityToInsert.GetType().GetProperties().Length - 1) sql += ","; } sql += ")"; connection.Execute(sql, entityToInsert); } }
I’m using it like this with a type:
using (var connection = new SqlConnection(connectionString)) { connection.Open(); var entity = new Test() { Name = "Johan", Age = 43 }; connection.Insert(entity); }
public class Test { public string Name { get; set; } public int Age { get; set; } }
…or like this with an anonymous type:
using (var connection = new SqlConnection(connectionString)) { connection.Open(); connection.Insert(new { Name = "Johan", Age = 43 }, "insert into test"); }
Works for me ™
-
Detecting Idle Time with Global Mouse and Keyboard Hooks in WPF
Years and years ago I wrote this blog post about detecting if the user was idle or active at the keyboard (and mouse) using a global hook. Well that code was for .NET 2.0 and Windows Forms and for some reason I wanted to try the same in WPF and noticed that a few things around the keyboard and mouse hooks didn’t work as expected in the WPF environment. So I had to change a few things and here’s the code for it, working in .NET 4.
I took the liberty and refactored a few things while at it and here’s the code now. I’m sure I will need it in the far future as well.
using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace Irm.Tim.Snapper.Util { public class ClientIdleHandler : IDisposable { public bool IsActive { get; set; } int _hHookKbd; int _hHookMouse; public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); public event HookProc MouseHookProcedure; public event HookProc KbdHookProcedure; //Use this function to install thread-specific hook. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); //Call this function to uninstall the hook. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook); //Use this function to pass the hook information to next hook procedure in chain. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); //Use this hook to get the module handle, needed for WPF environment [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle(string lpModuleName); public enum HookType : int { GlobalKeyboard = 13, GlobalMouse = 14 } public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) { //user is active, at least with the mouse IsActive = true; Debug.Print("Mouse active"); //just return the next hook return CallNextHookEx(_hHookMouse, nCode, wParam, lParam); } public int KbdHookProc(int nCode, IntPtr wParam, IntPtr lParam) { //user is active, at least with the keyboard IsActive = true; Debug.Print("Keyboard active"); //just return the next hook return CallNextHookEx(_hHookKbd, nCode, wParam, lParam); } public void Start() { using (var currentProcess = Process.GetCurrentProcess()) using (var mainModule = currentProcess.MainModule) { if (_hHookMouse == 0) { // Create an instance of HookProc. MouseHookProcedure = new HookProc(MouseHookProc); // Create an instance of HookProc. KbdHookProcedure = new HookProc(KbdHookProc); //register a global hook _hHookMouse = SetWindowsHookEx((int)HookType.GlobalMouse, MouseHookProcedure, GetModuleHandle(mainModule.ModuleName), 0); if (_hHookMouse == 0) { Close(); throw new ApplicationException("SetWindowsHookEx() failed for the mouse"); } } if (_hHookKbd == 0) { //register a global hook _hHookKbd = SetWindowsHookEx((int)HookType.GlobalKeyboard, KbdHookProcedure, GetModuleHandle(mainModule.ModuleName), 0); if (_hHookKbd == 0) { Close(); throw new ApplicationException("SetWindowsHookEx() failed for the keyboard"); } } } } public void Close() { if (_hHookMouse != 0) { bool ret = UnhookWindowsHookEx(_hHookMouse); if (ret == false) { throw new ApplicationException("UnhookWindowsHookEx() failed for the mouse"); } _hHookMouse = 0; } if (_hHookKbd != 0) { bool ret = UnhookWindowsHookEx(_hHookKbd); if (ret == false) { throw new ApplicationException("UnhookWindowsHookEx() failed for the keyboard"); } _hHookKbd = 0; } } #region IDisposable Members public void Dispose() { if (_hHookMouse != 0 || _hHookKbd != 0) Close(); } #endregion } }
The way you use it is quite simple, for example in a WPF application with a simple Window and a TextBlock:
<Window x:Class="WpfApplication2.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> <TextBlock Name="IdleTextBox"/> </Grid> </Window>
And in the code behind we wire up the ClientIdleHandler and a DispatcherTimer that ticks every second:
public partial class MainWindow : Window { private DispatcherTimer _dispatcherTimer; private ClientIdleHandler _clientIdleHandler; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { //start client idle hook _clientIdleHandler = new ClientIdleHandler(); _clientIdleHandler.Start(); //start timer _dispatcherTimer = new DispatcherTimer(); _dispatcherTimer.Tick += TimerTick; _dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1); _dispatcherTimer.Start(); } private void TimerTick(object sender, EventArgs e) { if (_clientIdleHandler.IsActive) { IdleTextBox.Text = "Active"; //reset IsActive flag _clientIdleHandler.IsActive = false; } else IdleTextBox.Text = "Idle"; } }
Remember to reset the ClientIdleHandle IsActive flag after a check.
-
ASP.NET 4 Website Fails to Start on Your TFS 2010 Server?
Getting a “Could not find permission set named ‘ASP.Net’” error on your TFS 2010 server? It may have to do with the fact you’re trying to run ASP.NET as a child site of a SharePoint Web Site. The problem is described in the “ASP.NET 4 braking changes” site:
This error occurs because the ASP.NET 4 code access security (CAS) infrastructure looks for a permission set named ASP.Net. However, the partial trust configuration file that is referenced by WSS_Minimal does not contain any permission sets with that name.
Currently there is not a version of SharePoint available that is compatible with ASP.NET. As a result, you should not attempt to run an ASP.NET 4 Web site as a child site underneath SharePoint Web sites.
There is a workaround you could try by setting this in your web.config, if you know what you’re doing:
<trust level="Full" originUrl="" />
-
Weeko – MEF and WPF to plug in Tool Windows into Visual Studio 2010
Today I opened up a new Codeplex project called “Weeko”, which is a Sioux name for “pretty”.
Weeko is an experiment which uses MEF to easily plug in tool windows into VS2010. The tool windows are developed as ordinary WPF UserControls. Install the Visual Studio extension and drop your user control assembly into the extensions directory of Visual Studio and it will show up inside the IDE.
This is how it can look with a couple of sample “addins” – The Rss feed, Twitter feed and a digital clock are all WPF User Controls which are exported and imported using MEF – Managed Extensibility Framework.
Feel free to check it out and if you got some ideas for improvements please let me know. I’m thinking about how to better manage available plugins, load/unload etc.