Google
 

Saturday, April 16, 2011

How to turn off your monitor




namespace TurnoffMonitor
{
///
/// Interaction logic for MainWindow.xaml
///

public partial class MainWindow : Window
{
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);

const int SC_MONITORPOWER = 0xF170;
const uint WM_SYSCOMMAND = 0x0112;

const int MONITOR_ON = -1;
const int MONITOR_OFF = 2;
const int MONITOR_STANBY = 1;

public MainWindow()
{
InitializeComponent();
}

private void ExecuteButton_Click(object sender, RoutedEventArgs e)
{
WindowInteropHelper helper = new WindowInteropHelper(this);
var handle = helper.Handle;


SendMessage(handle, WM_SYSCOMMAND, new IntPtr(SC_MONITORPOWER), new IntPtr(MONITOR_OFF));
}
}
}

Saturday, April 10, 2010

WCF 4.0 Service Discovery - Adding the binding to the discovery

With WCF 4.0 a wonderful new feature is added. Service Discovery allows us to see what services are running and where they are. However, when I started to look into this in detail, I noticed the information you get on services only contains the A (Address) and C (Contract) of the ABC, The Address and the Contract - but not the binding. So in this article I will show how to add the binding to the discovery information with little ease.

Note: All the code is developed on Visual Studio 2010 RC

EndpointDiscoveryMetadata



Within the discovery this class is probably one of the most important ones. This is the information we get when services go up and down. Below you can see that there is no binding information about the service.

Notice you can get the contact names, using:
Collection ContractTypeNames { get; }

and you can get the address using:
public EndpointAddress Address { get; set; }

But, no binding information!

When I posted on the forum asking why was it done this way, they told me that the binding are not part of the discovery standard (WS Discovery), they also told me that you can get the binding without problems by simply discovering the Mex endpoint and then issuing a call to get the metadata of the service. But, that is not ideal, you would need to discovery the service, and then get its metadata just to know the full ABC of an endpoint (2 network trips).
(http://social.msdn.microsoft.com/Forums/en/wcfprerelease/thread/ca6bc4be-bc46-4740-ba1e-dca8cf39aa5f)

One key field that EndpointDiscoveryMetadata has is Extensions. So right away I decided to see how I can fill up these extensions and add my own custom information in there. In this case it would be binding information.

The code


The example below is based on the WCF / WF code examples from Microsoft. The code has been modified to add binding information to the discovery metadata. I have used the Service Proxy example for this prototype.

You can get the Microsoft sample code here: http://www.microsoft.com/downloads/details.aspx?FamilyID=35ec8682-d5fd-4bc3-a51a-d8ad115a8792&displaylang=en


Adding Extensions to the EndpointDiscoveryMetadata



To add an extension to the Discovery Metadata, you need to create a new Endpoint Behavior and add it to the Endpoint.Behaviors collection. The behavior is a special behavior that belongs to the Discovery sub-system, it is called EndpointDiscoveryBehavior. Once you create this behavior you can add extensions to it using the Extension collection.
endpointDiscoveryBehavior.Extensions.Add

To make sure that the binding information is attached to the discovery metadata of each endpoint, the best approach was to create a new ServiceBehavior, and add a EndpointDiscoveryBehavior to each endpoint.

Below is the code of the Service Behavior:


public class BindingDiscoveryServiceBehavior : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection endpoints, BindingParameterCollection bindingParameters)
{

}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
var endpoints = serviceDescription.Endpoints;

foreach (ServiceEndpoint endpoint in endpoints)
{
var endpointDiscoveryBehavior = new EndpointDiscoveryBehavior();

StringBuilder sb = new StringBuilder();

sb.Append(endpoint.Address);
sb.Append(Environment.NewLine);
sb.Append(endpoint.Binding.Scheme);
sb.Append(Environment.NewLine);
sb.Append(endpoint.Binding.Name);

string bindingInfo = sb.ToString();
string largeData = String.Empty;

StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < 3000000; i++)
sb2.Append("Lots of data " + i.ToString() + Environment.NewLine);

largeData = sb2.ToString();

// add the binding information to the endpoint
endpointDiscoveryBehavior.Extensions.Add(
new XElement(
"root",
new XElement("BindingData", bindingInfo),
new XElement("LargeData", largeData)));

// add the extension
endpoint.Behaviors.Add(endpointDiscoveryBehavior);

}
}

public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{

}
}


Note that I have also added a very large data to the extension, just to show that you can pass large amount of data in the Extensions. (but you need to increase the limits on the discovery proxy TCP binding).


The next step is simple, you just need to add your Service Behavior to your service. You can do this by configuration, or simply applying it as an attribute on the service:


[BindingDiscoveryServiceBehavior]
public class CalculatorService : ICalculatorService



Getting the information when a service is "Discovered"


To see the binding information when a service is discovered, I have modified the Service Proxy from the WCF discovery example:

When a service is discovered, the OnBeginOnlineAnnouncement is called..

Below is the modified implementation:


[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DiscoveryProxyService : DiscoveryProxy
{
// Repository to store EndpointDiscoveryMetadata. A database or a flat file could also be used instead.
Dictionary onlineServices;

public DiscoveryProxyService()
{
this.onlineServices = new Dictionary();
}

// OnBeginOnlineAnnouncement method is called when a Hello message is received by the Proxy
protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)
{
this.AddOnlineService(endpointDiscoveryMetadata);
return new OnOnlineAnnouncementAsyncResult(callback, state);
}

protected override void OnEndOnlineAnnouncement(IAsyncResult result)
{
OnOnlineAnnouncementAsyncResult.End(result);
}

// OnBeginOfflineAnnouncement method is called when a Bye message is received by the Proxy
protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)
{
this.RemoveOnlineService(endpointDiscoveryMetadata);
return new OnOfflineAnnouncementAsyncResult(callback, state);
}

protected override void OnEndOfflineAnnouncement(IAsyncResult result)
{
OnOfflineAnnouncementAsyncResult.End(result);
}

// OnBeginFind method is called when a Probe request message is received by the Proxy
protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state)
{
this.MatchFromOnlineService(findRequestContext);
return new OnFindAsyncResult(callback, state);
}

protected override void OnEndFind(IAsyncResult result)
{
OnFindAsyncResult.End(result);
}

// OnBeginFind method is called when a Resolve request message is received by the Proxy
protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state)
{
return new OnResolveAsyncResult(this.MatchFromOnlineService(resolveCriteria), callback, state);
}

protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result)
{
return OnResolveAsyncResult.End(result);
}

// The following are helper methods required by the Proxy implementation
void AddOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
lock (this.onlineServices)
{
this.onlineServices[endpointDiscoveryMetadata.Address] = endpointDiscoveryMetadata;
}

PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Adding");
// show the binding information
PrintBindingInformation(endpointDiscoveryMetadata);
}

private void PrintBindingInformation(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
// Get the binding data
XElement element = endpointDiscoveryMetadata.Extensions.Elements("BindingData").FirstOrDefault();
string bindingInfo = element.Value;

Console.WriteLine("Binding Data");
Console.WriteLine(bindingInfo);
}

void RemoveOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)
{
if (endpointDiscoveryMetadata != null)
{
lock (this.onlineServices)
{
this.onlineServices.Remove(endpointDiscoveryMetadata.Address);
}

PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Removing");
}
}

void MatchFromOnlineService(FindRequestContext findRequestContext)
{
lock (this.onlineServices)
{
foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)
{
if (findRequestContext.Criteria.IsMatch(endpointDiscoveryMetadata))
{
findRequestContext.AddMatchingEndpoint(endpointDiscoveryMetadata);
}
}
}
}

EndpointDiscoveryMetadata MatchFromOnlineService(ResolveCriteria criteria)
{
EndpointDiscoveryMetadata matchingEndpoint = null;
lock (this.onlineServices)
{
foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)
{
if (criteria.Address == endpointDiscoveryMetadata.Address)
{
matchingEndpoint = endpointDiscoveryMetadata;
}
}
}
return matchingEndpoint;
}

void PrintDiscoveryMetadata(EndpointDiscoveryMetadata endpointDiscoveryMetadata, string verb)
{
Console.WriteLine("\n**** " + verb + " service of the following type from cache. ");
foreach (XmlQualifiedName contractName in endpointDiscoveryMetadata.ContractTypeNames)
{
Console.WriteLine("** " + contractName.ToString());
break;
}
Console.WriteLine("**** Operation Completed");
}

sealed class OnOnlineAnnouncementAsyncResult : AsyncResult
{
public OnOnlineAnnouncementAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}

public static void End(IAsyncResult result)
{
AsyncResult.End(result);
}
}

sealed class OnOfflineAnnouncementAsyncResult : AsyncResult
{
public OnOfflineAnnouncementAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}

public static void End(IAsyncResult result)
{
AsyncResult.End(result);
}
}

sealed class OnFindAsyncResult : AsyncResult
{
public OnFindAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
this.Complete(true);
}

public static void End(IAsyncResult result)
{
AsyncResult.End(result);
}
}

sealed class OnResolveAsyncResult : AsyncResult
{
EndpointDiscoveryMetadata matchingEndpoint;

public OnResolveAsyncResult(EndpointDiscoveryMetadata matchingEndpoint, AsyncCallback callback, object state)
: base(callback, state)
{
this.matchingEndpoint = matchingEndpoint;
this.Complete(true);
}

public static EndpointDiscoveryMetadata End(IAsyncResult result)
{
OnResolveAsyncResult thisPtr = AsyncResult.End(result);
return thisPtr.matchingEndpoint;
}
}
}


Notice that I am getting the binding information in the code below:
XElement element = endpointDiscoveryMetadata.Extensions.Elements("BindingData").FirstOrDefault();
string bindingInfo = element.Value;


Now I have the binding information, so when I ask for a specific contract, I can get the binding as well as the address back to the client that is requesting the endpoint information. Now we can discover the full A B C and not just the A and C.

Saturday, September 19, 2009

WAS hosting for services with multiple msmq binding endpoints - not ideal!

I have been looking into this issue of hosting a service with multiple message queue endpoints with WAS for sometime. One thing that kept bothering me is that the SVC file name of the service needed to match the name of the queue. Furthermore, it was not just the name of the queue, but the name of the virtual folder + the queue name so the activation service will detect messages in my queue and then activate my service.


Once I got all the pieces to work, I renamed my SVC file, checked the permission of my queue to allow the activation service to peek into it, and got the service hosted in WAS, I realized that I can't get another queue on the same service to work. Considering the SVC file needs to match the queue, only one endpoint is satisfied, having another queue endpoint is possible, but the activation service will not look at it. This means that the service will process messages of another queue, but the service will not be activated based on these other queues. So you will need to first activate the service using the SVC named queue, and then the other queues will work.

This means that if you try to host a service with multiple queue endpoints, you must choose which queue will be responsible for the activation of the service. Only one must be chosen (and that queue needs to have the SVC file name renamed after it). Other queues, will not force activation of the service.

I have confirmed this to be true with Micrsofot support. They couldn't even give a good explanation why this was done this way. Why do you need to rename the SVC file? why can't you just use a configuration? or read the metadata of the service... I can think of many other ways to handle activation of queues, without the limitation of one queue per service, and forcing the user to rename his SVC file.

So how do you handle a service with multiple queue endpoints? Well, one simple way is not to use WAS hosting and use Windows Service Hosting, this problem does not exist with non-was hosting, but you loose on the activation model. You can make your own activation model, but that's like re-doing WAS.

Another option if you like using WAS, is to create multiple SVC files, one named after each queue within your service. The SVC files will all point to the same service class / assembly, but it will cause multiple service instances to be created depending on which queue forced the activation. You place all these SVC files within the same virtual folder. This might work only if the service is completely stateless.

Other work-around is to make sure the idle timeout is really large, so your service is only activated once, and then stays alive "forever". But, that just takes the activation out of WAS, which at that point, you may as well host it within a windows service.

Microsoft support also told me, that you can "ping" your service, to make sure it is activated, but that's just crazy... so I will not write more about that option.

Or... you can simply avoid having multiple queues in the same service (if you are planning to host your service under WAS).

I plan to update this post with an official KB article explaining this issue. Microsoft Support told me they will send it to me once they all agree this is a limitation by design.

Although this is not a popular feature of WAS, I feel there might be others out there trying the very same thing I am trying. I hope this helps them a little bit.




Friday, August 14, 2009

GetHashCode using MD5

Wanted to have a way to get a hash code for an object, and the code will be different when the data within the object changes. Only supported for objects that support serialization... but it is better then nothing...


public static class HashCodeGenerator
{
public static string GetMD5HashCode(this object obj)
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Flush();
var data = stream.ToArray();
StringBuilder sBuilder = new StringBuilder();

// get the hash code of the object.
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hashBytesArray = md5.ComputeHash(data);

// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < hashBytesArray.Length; i++)
{
sBuilder.Append(hashBytesArray[i].ToString("x2"));
}

return sBuilder.ToString();
}

public static bool CompareMD5HashCode(this object obj, string hashCode)
{
string hash = obj.GetMD5HashCode();
bool isMatch = false;
if (hash == hashCode)
isMatch = true;

return isMatch;
}
}

Thursday, August 13, 2009

Object to XML and XML to Object

I always need this code... so now its on my page!


internal static class XmlSerializerHelper
{
public static object GetObjectFromXml(string xml, Type type)
{
XmlSerializer ser = new XmlSerializer(type);
object value = ser.Deserialize(new StringReader(xml));
return value;
}

public static string GetXmlFromObj(object obj, Type type)
{
string xml;
XmlSerializer ser = new XmlSerializer(type);
using (StringWriter writer = new StringWriter())
{
ser.Serialize(writer, obj);
writer.Flush();
xml = writer.ToString();
}

return xml;
}

public static string ToXml(this object obj)
{
Type type = obj.GetType();
string xml = GetXmlFromObj(obj, type);
return xml;
}

}

DataForm Control supporting nested classes


One of the cool things in the toolkit is a new DataForm control. You can give it any object and it will produce a form that will allow you to edit / read your object. However, I noticed that the DataForm, out of the box does not support "auto generation" of fields for nested complex types. This is something that sounds simple to support out of the box, becasue a nested class is really another DataForm control nested within its parent DataForm. Still, when tyring to put a complex type, the Dataform control simply puts a textbox and put the ToString() value of your complex type as its value. Not very useful.

With the help of the UI guy at my work, we found a way to change this limitation and allow for nested UI. I will include the code in this post, but it is mostly testing code and prototype code. You can take it and modify it for your needs.

To do this we creaed a SuperDataForm control



using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Collections.Generic;

namespace ParameterManagement
{
public class SuperDataForm : DataForm
{
List Controls = new List();

public bool CompositeItemIsValid;
public SuperDataForm()
{
this.Loaded += new RoutedEventHandler(SuperDataForm_Loaded);

}

void SuperDataForm_Loaded(object sender, RoutedEventArgs e)
{
if (this.CurrentItem == null)
{
this.CurrentItem = this.DataContext;
}
}

protected override void OnAutoGeneratingField(DataFormAutoGeneratingFieldEventArgs e)
{
// normally change this condition to check it is one of your complex types
// or that it is not a basic type.
if (e.PropertyType == typeof(NestedComplexType))
{
var control = new SuperDataForm();

control.CommandButtonsVisibility = DataFormCommandButtonsVisibility.All;
control.IsReadOnly = false;
Controls.Add(control);
Binding binding = new Binding(e.PropertyName);
binding.Mode = BindingMode.TwoWay;
binding.ValidatesOnExceptions = true;
binding.NotifyOnValidationError = true;
control.SetBinding(DataForm.CurrentItemProperty, binding);
e.Field.IsReadOnly = false;
e.Field.Content = control;
}

}

protected override void OnValidatingItem(System.ComponentModel.CancelEventArgs e)
{
// this is needed to have validation on the children controls
foreach (var control in Controls)
{
if (!control.ValidateItem())
{
CompositeItemIsValid = false;
break;
}
}
}

protected override void OnCurrentItemChanged(EventArgs e)
{

}



}
}


Download Code Here