Recording Skype
Written by Harry Fairhead   
Sunday, 12 July 2009
Article Index
Recording Skype
Getting started
Message in a queue
Talking to Skype
Make the call

Start a new C# Windows application using C# Express or Visual Studio – all of the ideas work in Visual Basic or any other .NET language with minor modifications. The first thing we need is the definition of the API call:

[DllImport("user32.dll")]
static extern uint
RegisterWindowMessage(
string lpString);

As we are using interop services to call the Windows API we also need to add:

using System.Runtime.InteropServices;

to the start of the program. We need two global variables to store the codes of the two custom messages:

public UInt32 APIDiscover;
public UInt32 APIAttach;

Now we can call the API twice to discover the codes. Start a new method called SkypeFirstConnect. The purpose of this, as its name suggests, is to make the very first connection to Skype – you may want to write a reconnect method to be used in the event that Skype temporarily goes off-line:

private void SkypeFirstConnect()
{
APIDiscover = RegisterWindowMessage(
"SkypeControlAPIDiscover");
APIAttach = RegisterWindowMessage(
"SkypeControlAPIAttach");

As long as Skype is installed on the system we should now have the two custom message codes stored in the appropriate variables. We can now send the APIDiscover message to every window in the system and wait for Skype to send the APIAttach message back to us.

 

In general, working with the Skype API is a matter of sending a message and then getting back a response. We need a general method of waiting for the response which sometimes has some associated text data. The simplest thing to do is to define a struct:

public struct databuffer
{
public string data;
public Boolean valid;
}

This has a field to hold the returned data and a Boolean field to indicate when the data is valid, i.e. a message has been sent back from Skype. We need a single global instance of this struct:

public databuffer skypedata;

Continuing the SkypeFirstConnect method we need to first invalidate the return data and use the API call SendMessageTimeout to send the APIDiscover message to all active windows:

skypedata.valid = false;
skypedata.data = string.Empty;
IntPtr result;
IntPtr aRetVal = SendMessageTimeout(
HWND_BROADCAST,
APIDiscover,
this.Handle,
IntPtr.Zero,
SendMessageTimeoutFlags.SMTO_NORMAL,
100,
out result);

This API call waits for the message to be processed or for a maximum of the “timeout” in milliseconds that you specify – 100 milliseconds in this case. The first parameter results in the APIDiscover messaging being “broadcast” to all windows, the third parameter passes the window handle of our application and the final few parameters control how the API call behaves – check the documentation for the fine detail but the following enumeration helps:

[Flags]
public enum SendMessageTimeoutFlags:uint
{
SMTO_NORMAL = 0x0000,
SMTO_BLOCK = 0x0001,
SMTO_ABORTIFHUNG = 0x0002,
SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
}

To make this work we also need a definition of the API call and a value for HWND_BROADCAST:

[DllImport("user32.dll")]
public static extern IntPtr
SendMessageTimeout(
IntPtr windowHandle,
uint Msg,
IntPtr wParam,
IntPtr lParam,
SendMessageTimeoutFlags flags,
uint timeout,
out IntPtr result);
public static readonly IntPtr
HWND_BROADCAST = new IntPtr(-1);

The method has now completed its task and all we have to do is wait for Skype to send a message back to us.

Exactly how this works is explained next but for the moment we have to decide whether to make the method “blocking” or “asynchronous”. We could wait within the method until Skype responds and this would block any further processing by the application or we could return and rely on some other part of the application to handle the response asynchronously. In most cases asynchronous operation is the more powerful and if you take using the Skype API further you should implement an asynchronous approach by generating an event when the response arrives. However blocking is simpler and using it makes the way things work more obvious. So let’s implement a WaitForSkype method which does just that – waits until Skype sends back a response that contains a specified key word and simply use it at the end of the method:

 WaitForSkype("");
}

If the target keyword is a null string then the method simply waits for any response from Skype. The code for the WaitForSkype function is fairly simple, just two nested loops, the outer one waiting for valid data from Skype and the inner one checking for the keyword:

private void WaitForSkype(string target)
{
do{
do
{
Application.DoEvents();
} while (!skypedata.valid);
}while(!skypedata.data.
Contains(target));
}

<ASIN:B000YL1946@UK>

<ASIN:0307351254>

<ASIN:B00158UZTW@COM>

<ASIN:0596101899>



Last Updated ( Monday, 27 July 2009 )