DCSIMG
May 2010 - Posts - Shai Raiten's Blog

Shai Raiten's Blog

It's all about code...

May 2010 - Posts

TFS 2010 - Red X on Work Items (TF51535)

TFS 2010 - Red X on Work Items (TF51535)image

I came across a very strange problem in Visual Studio 2010, for some strange reason one of the Users was unable to view Work Item in just Two project.
Yes I’ve check permissions, clean cache and tested on a different computer but the same result each time.

imageMicrosoft Test Manager had the same problem and each time I tried to open the “Track” tab I got the following error:

I’ve looked at the Window Event log(local machine) for errors but nothing, I checked the server and saw the following error:

TF53010: The following error has occurred in a Team Foundation component or extension:
Detailed Message: TF200035: One or more errors occurred when Team Foundation Server attempted to synchronize the following identity: S-1-5-21-575125362-957187282-2506226335-3421. Number of errors that occurred: 1.

Sync error for identity: S-1-5-21-575125362-957187282-2506226335-3421
Logon failure: unknown user name or bad password.

We tried to change the password but still nothing.

The next step is to enable Visual Studio 2010 log to help us finding the problem.

After enabling Visual Studio log I saw the following errors:

Visual Studio 2010 Log
<detail ExceptionMessage="TF51535: Missing or unsupported field name."><details id="0" xmlns="http://schemas.microsoft.com/TeamFoundation/2005/06/WorkItemTracking/faultdetail/03" /></detail>

Window Event Log:TF51535: Missing or unsupported field name

Inner exception ==>System.Web.Services.Protocols.SoapException: TF51535: Missing or unsupported field name. ---> TF51535: Missing or unsupported field name.
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean
asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at Microsoft.TeamFoundation.WorkItemTracking.Proxy.ClientServiceProxy2.GetStoredQueryItems(Int64 rowVersion, Int32 projectId)
at Microsoft.TeamFoundation.WorkItemTracking.Proxy.WorkItemServer.GetStoredQueryItems(String requestId, Int64 rowVersion, Int32 projectId,
RowSetCollection& queriesDataSet)
at Microsoft.TeamFoundation.WorkItemTracking.Client.QueryHierarchy.UpdateQueries(Boolean refresh)

Missing or unsupported field?

I went to check QueryItems table at TFS DB, and run a query for all queries for that specific User under the projects with the problem.

SELECT * FROM [Tfs_DefaultCollection].[dbo].[QueryItems]
where Text like '%ba7426a8-df26-4ac3-b9ea-fbd33cde4a39%'
AND (ProjectID = 123 OR ProjectID = 34)

I’ve looked around and saw some queries with an old field inside them - “mm.Status

image

Solution

To solve this problem just change the fDeleted value from 0 to 1.

update [Tfs_DefaultCollection].[dbo].[QueryItems]
set fDeleted = 1
WHERE Text like '%ba7426a8-df26-4ac3-b9ea-fbd33cde4a39%'}
AND (ProjectID = 123 OR ProjectID = 34)

Enjoy.  

How To Enable Visual Studio 2010 Log

How To Enable Visual Studio 2010 Log

To enable visual studio logger go to :

  1. C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE (64bit OS)
    C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE (32bit OS)
  2. Edit “devenv.exe.config” (Make sure you close all open instances of Visual Studio)
  3. Add below text before </Configuration> tag,  and edit the location of the log file (E:\Backup\tf.log)

    <system.diagnostics>
          <switches>
            <add name="TeamFoundationSoapProxy" value="4" />
            <add name="VersionControl" value="4" />
          </switches>
          <trace autoflush="true" indentsize="3">
            <listeners>
              <add name="myListener"
           type="Microsoft.TeamFoundation.TeamFoundationTextWriterTraceListener,Microsoft.TeamFoundation.Common, Version=10.0.0.0,
           Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" initializeData="E:\Backup\tf.log" />
              <add name="perfListener" type="Microsoft.TeamFoundation.Client.PerfTraceListener,Microsoft.TeamFoundation.Client,
              Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            </listeners>
          </trace>
    </system.diagnostics>    .

  4. Save devenv.exe.config and open visual studio.

    For Example:

image

Window Hooks – Summary

Window Hooks – Summaryc28d6731fe203d3f80e2774a151c3e8a1_thumb_221CE17E

A week ago I received a question through my blog "How can I create buttons on top all open applications?", I didn't waste time and start writing about my solution to the question.

So here is a series of posts regarding this question above:

Because this was a couple of long posts I decide to publish the full article at CodeProject:

Full Article at CodeProject - Add Your Control On Top Another Application

Enjoy

How To Change Default Language In Visual Studio

How To Change Default Language In Visual Studioimage

I've just installed Clean version of Visual Studio 2010 Ultimate and by mistake I choose my default language as Visual Basic.

So each time I'm starting a new project the default language is Visual Basic and I need to waste couple of expensive seconds to choose C# under other languages.

So here is how you change the default language in Visual Studio to the language you want.

How To:

1. Open Visual Studio, Tools and Click "Import and Export Settings…"

image

A wizard appears and choose the last option - "Reset all Settings"

image

Choose the right language for you and hit next.

image

Enjoy.

TFS 2010 Beta 2 and the Release Candidate Expiration is June 30, 2010

Beta 2 and the Release Candidate Expiration is June 30, 2010

Brian Harry just post about the expiration date for both Beta 2 and the Release Candidate is June 30, 2010.

So if you're still using Beta 2 or RC version of TFS 2010 hurry up and start planning Upgrade to TFS 2010 RTM.

Expiration

Add Your Control On Top Another Application – Part 4 (Win32)

Add Your Control On Top Another Application – Part 4 (Win32)c28d6731fe203d3f80e2774a151c3e8a[1]

And here we are, the last part in this series – How to set Window Event using SetWinEventHook.

In the previous posts we have found the Target window handle and his TitleBar position, we created a new Control(HoverControl) and placed him On Top the Target TitleBar, the only thing that left if to listen Target window events (Example: LocationChange) so we can move our HoverControl accordingly.

We going to use some more NativeMethods to complete this task, get ready…. Go!

Step 1: Add SetWinEventHook & UnhookWinEvent To NativeMethods Class

We need to use SetWinEventHook because this function allows clients to specify which processes and threads they are interested in.Clients can call SetWinEventHook multiple times if they want to register additional hook functions or listen for additional events.

[DllImport("user32.dll")]

internal static extern IntPtr SetWinEventHook(

    AccessibleEvents eventMin, //Specifies the event constant for the lowest event value in the range of events that are handled by the hook function. This parameter can be set to EVENT_MIN to indicate the lowest possible event value.

    AccessibleEvents eventMax, //Specifies the event constant for the highest event value in the range of events that are handled by the hook function. This parameter can be set to EVENT_MAX to indicate the highest possible event value.

    IntPtr eventHookAssemblyHandle, //Handle to the DLL that contains the hook function at lpfnWinEventProc, if the WINEVENT_INCONTEXT flag is specified in the dwFlags parameter. If the hook function is not located in a DLL, or if the WINEVENT_OUTOFCONTEXT flag is specified, this parameter is NULL.

    WinEventProc eventHookHandle, //Pointer to the event hook function. For more information about this function

    uint processId, //Specifies the ID of the process from which the hook function receives events. Specify zero (0) to receive events from all processes on the current desktop.

    uint threadId,//Specifies the ID of the thread from which the hook function receives events. If this parameter is zero, the hook function is associated with all existing threads on the current desktop.

    SetWinEventHookParameter parameterFlags //Flag values that specify the location of the hook function and of the events to be skipped. The following flags are valid:

    );

Removes an event hook function created by a previous call to.

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool UnhookWinEvent(IntPtr eventHookHandle);

 

WinEventProc - Important

An application-defined callback (or hook) function that the system calls in response to events generated by an accessible object. The hook function processes the event notifications as required. Clients install the hook function and request specific types of event notifications by calling SetWinEventHook.

internal delegate void WinEventProc(IntPtr winEventHookHandle, AccessibleEvents accEvent, IntPtr windowHandle, int objectId, int childId, uint eventThreadId, uint eventTimeInMilliseconds);

 

[DllImport("user32.dll")]

internal static extern IntPtr SetFocus(IntPtr hWnd);

 

[Flags]

internal enum SetWinEventHookParameter

{

    WINEVENT_INCONTEXT = 4,

    WINEVENT_OUTOFCONTEXT = 0,

    WINEVENT_SKIPOWNPROCESS = 2,

    WINEVENT_SKIPOWNTHREAD = 1

}

Value Meaning
WINEVENT_INCONTEXT The DLL that contains the callback function is mapped into the address space of the process that generates the event. With this flag, the system sends event notifications to the callback function as they occur. The hook function must be in a DLL when this flag is specified. This flag has no effect when both the calling process and the generating process are not 32-bit or 64-bit processes, or when the generating process is a console application. For more information, see In-Context Hook Functions.
WINEVENT_OUTOFCONTEXT The callback function is not mapped into the address space of the process that generates the event. Because the hook function is called across process boundaries, the system must queue events. Although this method is asynchronous, events are guaranteed to be in sequential order. For more information, see Out-of-Context Hook Functions.

WINEVENT_SKIPOWNPROCESS
Prevents this instance of the hook from receiving the events that are generated by threads in this process. This flag does not prevent threads from generating events.
WINEVENT_SKIPOWNTHREAD Prevents this instance of the hook from receiving the events that are generated by the thread that is registering this hook


Step 2: Create SetControl & GetWindowPosition Methods

What you need to go in this step is just to extract the code from btn_get_pos_Click & btn_add_Click methods to external method, this will serve us later.

void SetControl(bool log)

{

    //Creates new instance of HoverControl

    if (OnTopControl != null)

        OnTopControl.Close();

    OnTopControl = new HoverControl();

    OnTopControl.Show();

    //Search for HoverControl handle

    IntPtr OnTopHandle = Helpers.Find(OnTopControl.Name, OnTopControl.Title);

 

    //Set the new location of the control (on top the titlebar)

    OnTopControl.Left = left;

    OnTopControl.Top = top;

 

    if(log)

        Log("Hover Control Added!");

 

    //Change target window to be parent of HoverControl.

    Helpers.SetWindowLong(OnTopHandle, Helpers.GWLParameter.GWL_HWNDPARENT, TargetWnd.ToInt32());

}

 


void GetWindowPosition(bool log)

{

    var pos = Helpers.GetWindowPosition(TargetWnd);

 

    left = pos.Left;

    right = pos.Right;

    bottom = pos.Bottom;

    top = pos.Top;

 

    if(log)

        Log(string.Format("Left:{0} , Top:{1} , Top:{2} , Top:{3}", left, top, right, bottom));

 

    //retrieves the last system error.

    Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());

}

Step 3: Add Events And Callbacks

First we need to define what types of events we want to listen too and than create a dictionary with AccessibleEvents and Specific CallBack (or generic to all events).

You can find more about WinEvents in –> http://msdn.microsoft.com/en-us/library/system.windows.forms.accessibleevents.aspx.

I’ve add event for LocationChanged and Destroy, LocationChanged will help me to find the position on the target window each time the user changes the position and Destory when the target window closed and we need to close our HoverControl.

private Dictionary<AccessibleEvents, NativeMethods.WinEventProc> InitializeWinEventToHandlerMap()

{

    Dictionary<AccessibleEvents, NativeMethods.WinEventProc> dictionary = new Dictionary<AccessibleEvents, NativeMethods.WinEventProc>();

    //You can add more events like ValueChanged - for more info please read -

    //http://msdn.microsoft.com/en-us/library/system.windows.forms.accessibleevents.aspx

    //dictionary.Add(AccessibleEvents.ValueChange, new NativeMethods.WinEventProc(this.ValueChangedCallback));

    dictionary.Add(AccessibleEvents.LocationChange, new NativeMethods.WinEventProc(this.LocationChangedCallback));

    dictionary.Add(AccessibleEvents.Destroy, new NativeMethods.WinEventProc(this.DestroyCallback));

 

    return dictionary;

}

 

private void DestroyCallback(IntPtr winEventHookHandle, AccessibleEvents accEvent, IntPtr windowHandle, int objectId, int childId, uint eventThreadId, uint eventTimeInMilliseconds)

{

    //Make sure AccessibleEvents equals to LocationChange and the current window is the Target Window.

    if (accEvent == AccessibleEvents.Destroy && windowHandle.ToInt32() == TargetWnd.ToInt32())

    {

        //Queues a method for execution. The method executes when a thread pool thread becomes available.

        ThreadPool.QueueUserWorkItem(new WaitCallback(this.DestroyHelper));

    }

}

 

private void DestroyHelper(object state)

{

    Execute ex = delegate()

    {

        //Removes an event hook function created by a previous call to

        NativeMethods.UnhookWinEvent(g_hook);

        //Close HoverControl window.

        OnTopControl.Close();

    };

    this.Dispatcher.Invoke(ex, null);

}

 

private void LocationChangedCallback(IntPtr winEventHookHandle, AccessibleEvents accEvent, IntPtr windowHandle, int objectId, int childId, uint eventThreadId, uint eventTimeInMilliseconds)

{

    //Make sure AccessibleEvents equals to LocationChange and the current window is the Target Window.

    if (accEvent == AccessibleEvents.LocationChange && windowHandle.ToInt32() == TargetWnd.ToInt32())

    {

        //Queues a method for execution. The method executes when a thread pool thread becomes available.

        ThreadPool.QueueUserWorkItem(new WaitCallback(this.LocationChangedHelper));

    }

}

 

private void LocationChangedHelper(object state)

{

    Execute ex = delegate()

    {

        if(OnTopControl!=null)

            OnTopControl.Close();

        GetWindowPosition(false);

        SetControl(false);

    };

    this.Dispatcher.Invoke(ex, null);

}

 

Step 4: Set WinEventHook

This is the last step and the most important one,you can set as many events as you like but make sure to use GCHandle garbage collector will not move the callback and you will get many errors.

IntPtr g_hook;

private void btn_set_event_Click(object sender, RoutedEventArgs e)

{

    Dictionary<AccessibleEvents, NativeMethods.WinEventProc> events = InitializeWinEventToHandlerMap();

 

    //initialize the first event to LocationChanged

    NativeMethods.WinEventProc eventHandler =

        new NativeMethods.WinEventProc(events[AccessibleEvents.LocationChange].Invoke);

 

    //When you use SetWinEventHook to set a callback in managed code, you should use the GCHandle

    //(Provides a way to access a managed object from unmanaged memory.) structure to avoid exceptions.

    //This tells the garbage collector not to move the callback.

    GCHandle gch = GCHandle.Alloc(eventHandler);

 

    //Set Window Event Hool on Location changed.

    g_hook = NativeMethods.SetWinEventHook(AccessibleEvents.LocationChange,

        AccessibleEvents.LocationChange, IntPtr.Zero, eventHandler

        , 0, 0, NativeMethods.SetWinEventHookParameter.WINEVENT_OUTOFCONTEXT);

 

    //Hook window close event - close our HoverContorl on Target window close.

    eventHandler = new NativeMethods.WinEventProc(events[AccessibleEvents.Destroy].Invoke);

 

    gch = GCHandle.Alloc(eventHandler);

 

    g_hook = NativeMethods.SetWinEventHook(AccessibleEvents.Destroy,

        AccessibleEvents.Destroy, IntPtr.Zero, eventHandler

        , 0, 0, NativeMethods.SetWinEventHookParameter.WINEVENT_OUTOFCONTEXT);

 

    //AccessibleEvents -> http://msdn.microsoft.com/en-us/library/system.windows.forms.accessibleevents.aspx

    //SetWinEventHookParameter -> http://msdn.microsoft.com/en-us/library/dd373640(VS.85).aspx

}


Enjoy.

Add Your Control On Top Another Application – Part 3 (Win32)

Add Your Control On Top Another Application – Part 3 (Win32)image

This is part 3 and we are almost done!

The first post in this series Add Your Control On Top Another Application – Part 1 (Win32) we saw how to find window handle just by pointing the process, this was done by using Win32 native methods.
In Add Your Control On Top Another Application – Part 2 (Win32)

We used another native method that helped us to find target window position based on TitleBar info.

This part will show how to use this information to add our own control on top another application (See picture).

Download Demo Project

Step 1: Create HoverControl

The HoverContorl is basically a control, I’ve created a new Window control called HoverControl with the following attributes:WindowStyle="None" AllowsTransparency="True" Background="{Binding Null}"

this is important because we want to window to be transparent and without window borders.
Below the full xaml of the HoverControl.

<Window x:Class="Win32HooksDemo.HoverControl"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="HoverControl" Height="10" Width="150"

        WindowStyle="None" AllowsTransparency="True" Background="Transparent">

  <Grid>

    <Rectangle ToolTip="Click To Close" MouseDown="rectangle1_MouseDown"  Name="rectangle1"

               Stroke="#FFC7FF00" Fill="Red" RadiusY="10" RadiusX="10" StrokeThickness="2"/>

    <TextBlock FontSize="9" FontWeight="Bold" HorizontalAlignment="Center"

               Text="This is my Hover Control" />

  </Grid>

</Window>

Mouse down event should close the HoverControls.

Step 2: Add SetWindowLong To NativeMethod Class.

The SetWindowLongPtr function changes an attribute of the specified window. The function also sets a value at the specified offset in the extra window memory.

To write code that is compatible with both 32-bit and 64-bit versions of Windows, also add SetWindowLongPtr

///The SetWindowLongPtr function changes an attribute of the specified window

[DllImport("user32.dll", EntryPoint = "SetWindowLong")]

internal static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong);

 

[DllImport("user32.dll", EntryPoint = "SetWindowLong")]

internal static extern int SetWindowLong32(IntPtr windowHandle, Win32HooksDemo.Helpers.GWLParameter nIndex, int dwNewLong);

 

[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]

internal static extern IntPtr SetWindowLongPtr64(IntPtr windowHandle, Win32HooksDemo.Helpers.GWLParameter nIndex, IntPtr dwNewLong);

 

[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]

internal static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong);

 

Step 3: Add SetWindowLong In Helpers Class

The only attribute we need to change in this case is - GWL_HWNDPARENT, our agenda is to set target window as parent\owner of our HoverControl.

//Specifies the zero-based offset to the value to be set.

//Valid values are in the range zero through the number of bytes of extra window memory, minus the size of an integer.

public enum GWLParameter

{

    GWL_EXSTYLE = -20, //Sets a new extended window style

    GWL_HINSTANCE = -6, //Sets a new application instance handle.

    GWL_HWNDPARENT = -8, //Set window handle as parent

    GWL_ID = -12, //Sets a new identifier of the window.

    GWL_STYLE = -16, // Set new window style

    GWL_USERDATA = -21, //Sets the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero.

    GWL_WNDPROC = -4 //Sets a new address for the window procedure.

}

 

Instead of checking if this 64bit or 32bit from our UI class add SetWindowLong inside the helpers class.

 

public static int SetWindowLong(IntPtr windowHandle, GWLParameter nIndex, int dwNewLong)

{

    if (IntPtr.Size == 8) //Check if this window is 64bit

    {

        return (int)NativeMethods.SetWindowLongPtr64(windowHandle, nIndex, new IntPtr(dwNewLong));

    }

    return NativeMethods.SetWindowLong32(windowHandle, nIndex, dwNewLong);

}

 

Step 4: Add HoverControl On Top Target Application

First we need to create new instance of our new HoverContorl, set the position based on Target window TitleBar position (Part 2) and set the HoverControl as Child of Target window.

Add button click event and let’s add the following code:

if (OnTopControl != null)

    OnTopControl.Close();

//Creates new instance of HoverControl

HoverControl OnTopControl = new HoverControl();

OnTopControl.Show();

//Search for HoverControl handle

IntPtr OnTopHandle = Helpers.Find(OnTopControl.Name, OnTopControl.Title);

 

//Set the new location of the control (on top the titlebar)

OnTopControl.Left = left;

OnTopControl.Top = top;

 

//Change target window to be parent of HoverControl.

Helpers.SetWindowLong(OnTopHandle, Helpers.GWLParameter.GWL_HWNDPARENT, TargetWnd.ToInt32());

 

Log("Hover Control Added!");

 

Download Demo Project

image

Enjoy

Add Your Control On Top Another Application – Part 2 (Win32)

Add Your Control On Top Another Application – Part 2 (Win32)image

In my previous post Add Your Control On Top Another Application – Part 1 (Win32) I’ve showed how to obtain window handle from process.

Now I can assume that we have the window handle (If not read Part 1), now we need to get TitleBarInfo fro the TargetWindow, Using that data we can get the position of the window and more.

 Download Project

Step 1: Add GetTitleBarInfo and GetLastError

Using GettitleBarInfo will allow us to get information from the Target application.

[return: MarshalAs(UnmanagedType.Bool)]

[DllImport("user32.dll")]

internal static extern bool GetTitleBarInfo(IntPtr hwnd, ref TITLEBARINFO pti);

 

//GetLastError- retrieves the last system error.

[DllImport("coredll.dll", SetLastError = true)]

internal static extern Int32 GetLastError();

 

Step 2: Add TitleBarInfo & RECT Properties

Before we can use GetTitleBarInfo let’s add the following properties to the NativeMethods class.

[StructLayout(LayoutKind.Sequential)]

internal struct TITLEBARINFO

{

    public const int CCHILDREN_TITLEBAR = 5;

    public uint cbSize; //Specifies the size, in bytes, of the structure.

    //The caller must set this to sizeof(TITLEBARINFO).

 

    public RECT rcTitleBar; //Pointer to a RECT structure that receives the

    //coordinates of the title bar. These coordinates include all title-bar elements

    //except the window menu.

 

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]

 

    //Add reference for System.Windows.Forms

    public AccessibleStates[] rgstate;

    //0    The title bar itself.

    //1    Reserved.

    //2    Minimize button.

    //3    Maximize button.

    //4    Help button.

    //5    Close button.

}

 

[StructLayout(LayoutKind.Sequential)]

internal struct RECT

{

    internal int left;

    internal int top;

    internal int right;

    internal int bottom;

}

Step 3: Add GetWindowPosition

Into the Helpers class add GetWindowPosition (below), GetWindowPosition first will initialize TITLEBARINFO (Make sure you set the sbSize) than use GetTitleBarInfo to get the TitleBar position on the screen.

public static WinPosition GetWindowPosition(IntPtr wnd)

{

    NativeMethods.TITLEBARINFO pti = new NativeMethods.TITLEBARINFO();

 

    pti.cbSize = (uint)Marshal.SizeOf(pti);//Specifies the size, in bytes, of the structure.

    //The caller must set this to sizeof(TITLEBARINFO).

 

    bool result = NativeMethods.GetTitleBarInfo(wnd, ref pti);

 

    WinPosition winpos;

    if (result)

        winpos = new WinPosition(pti);

    else

        winpos = new WinPosition();

 

    return winpos;

}

 

Download Project

Enjoy

Add Your Control On Top Another Application – Part 1 (Win32)

Add Your Control On Top Another Application – Part 1 (Win32)image

Couple of days ago I got an email asked me to help with creating a buttons on top all open applications, this has reminded me the CodedUI Recorder.
As you can see from the picture when using CodedUI Testing you will see the “Currently Recording” notification on every active application you are recording.

How?

The design is to make the title bar window of the target application as the parent\owner window of the Control your want to add.
But this is not enough, we need to listen to many events like size change, style etc.. but I’ll get there later.
Here is what we need to do:

  1. Find window handle with FindWindow
  2. Get window position and title bar info using GetTitleBarInfo
  3. Set window as owner\parent using SetWindowLong
  4. SetWinEventHook for couple of events of the target application.

Download Demo Project

 imageSo let’s get started…

Step 1: Create Project

Create a WinForm or WPF project and add the following classes:

  • We will use this class to combine native methods so we can write our code mote efficiently.
    public static class Helpers
  • Native methods collection.
    static class NativeMethods

Step 2: Get Running Processes

Create new class called “PItem” and copy this code:

public class PItem

{

    public string ProcessName { get; set; }

    public string Title { get; set; }

 

    public PItem(string processname, string title)

    {

        this.ProcessName = processname;

        this.Title = title;

    }

 

    public override string ToString()

    {

        if (!string.IsNullOrEmpty(Title))

            return string.Format("{0} ({1})", this.ProcessName, this.Title);

        else

            return string.Format("{0}", this.ProcessName);

    }

}

 

Now, getting all active processes:

Process[] pro_list = e.Result as Process[];

foreach (Process pro in pro_list)

{

    try

    {

        //When using 64bit OS pro.MainModule.ModuleName will throw exception

        // for each 32bit, so Instead of ModuleName I've used ProcessName

        ProcessList.Items.Add(new PItem(pro.ProcessName, pro.MainWindowTitle));

    }

    catch (Exception)

    {

        //Security\ Permissions Issue

    }

}

Step 3: Add Find Native Methods

FindWindow function retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.
Add below methods to NativeMethods.

using System.Runtime.InteropServices;


// Get a handle to an application window.

[DllImport("user32.dll", SetLastError = true)]

internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

 

// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]

internal static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

 

Add below code to Helpers
I’ve created a Find method to handle both FindWindow and FindWindowByCaption (much more easy to search that way :-D)

public static IntPtr Find(string ModuleName, string MainWindowTitle)

{

    //Search the window using Module and Title

    IntPtr WndToFind = NativeMethods.FindWindow(ModuleName, MainWindowTitle);

    if (WndToFind.Equals(IntPtr.Zero))

    {

        if (!string.IsNullOrEmpty(MainWindowTitle))

        {

            //Search window using TItle only.

            WndToFind = NativeMethods.FindWindowByCaption(WndToFind, MainWindowTitle);

            if (WndToFind.Equals(IntPtr.Zero))

                return new IntPtr(0);

        }

    }

    return WndToFind;

}

Step 4: Find Window Handle From Process

Using PItem we can use the ModuleName\Process Name and if the window is exists we can also use window title.
Calling our Helpers class and using Find method with ProcessName and WindowTitle.

PItem pro = ProcessList.SelectedItem as PItem;

 

string ModuleName = pro.ProcessName;

string MainWindowTitle = pro.Title; ;

 

TargetWnd = Helpers.Find(ModuleName, MainWindowTitle);

 

if (!TargetWnd.Equals(IntPtr.Zero))

    Log(ModuleName + " Window: " + TargetWnd.ToString()); // We Found The Window

else

    Log(ModuleName + " Not found"); // No Window Found

 

Download Demo Project

Enter Island – Bluetooth Radar = #1 Place

Enter Island – Bluetooth Radar = #1 Place

image

Three weeks ago I heard about the Enter Island competition and I have decide to compete and build the “Bluetooth Radar”.

If you are not familiar with Enter Island competition here what you had to do, first to be from Middle East or Africa and to do one of the following:

Publish a photo or a short video of your IT workspace on the contest’s Facebook page, publish any project you built with Visual Studio 2010 on the CodePlex <<<--- I built a WPF 4 project called –
Bluetooth RadarOver than 6000 downloads in 22 days,  and I got a
Reviewd from Life Hacker About Bluetooth Radar.

Last night I got the following email from Microsoft:

Dear ShaiR,
Thanks for your contribution and active participation in the “Enter The Island: IT’s The Best Job in the World” contest!
Microsoft Middle East and Africa team and myself would like to sincerely thank you for investing your time in it.
With the support of those people who downloaded you project more than 2000 times you took the #1 place in the competition.
So it’s my pleasure to announce you as 1 of those who will join the IT Community at Mauritius this May!

Thanks for the support.