100% CPU

2008/07/02 16:55
http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx?msg=1540676#xx1540676xx

This did the trick!!!!!! No 100% CPU load anymore

I understand the setting, but what on earth then is the default setting, some busy poll loop???
Can't MS sack that programmer for life

Well, looking a bit more on the internet (http://www.iis.net/922/SinglePageArticle.ashx[^] I found this:

"Due to a bug in the Windows Communication Foundation that isn't fixed in Beta 2 a net.tcp request to the net.tcp Listener Adapter service (SMSvcHost.exe) will peg the CPU at 90%. The workaround is to add the following to the file %windir%\WinFX\v3.0\Windows Communication Foundation\SMSvcHost.exe.config:

"socket alwaysUseCompletionPortsForAccept="true""

Apparently this bug isn't just in WCF, but already made his way to XP / .NET 2.0

-- modified at 12:37 Tuesday 20th June, 2006
Posted by xhoto

public class OrderTimeDESC : IComparer

{

    int IComparer.Compare(Object order1, Object order2)

    {

        return (((Order)order1).ReceiptDateTime.CompareTo(((Order)order2).ReceiptDateTime));

    }

}

 

public class OrderTimeASC : IComparer

{

    int IComparer.Compare(Object order1, Object order2)

    {

            return (((Order)order2).ReceiptDateTime.CompareTo(((Order)order1).ReceiptDateTime));

    }

}


public
void SortTest()

{

    IComparer orderTimeDESC = new OrderTimeDESC();

    IComparer orderTimeASC = new OrderTimeASC();

 

    Order order1 = new Order();

    order1.ReceiptDateTime = DateTime.Now;

    Order order2 = new Order();

    order2.ReceiptDateTime = DateTime.Now.AddDays(1);

    Order order3 = new Order();

    order3.ReceiptDateTime = DateTime.Now.AddDays(2);

    Order[] orders = new Order[3];

    orders[0] = order3;

    orders[1] = order1;

    orders[2] = order2;

 

    Array.Sort(orders, orderTimeASC);

 

    for (int i = 0; i < orders.GetLength(0); i++)

        System.Console.WriteLine(orders[i].ReceiptDateTime.ToString());

 
    Array.Sort(orders, orderTimeDESC);

 

    for (int i = 0; i < orders.GetLength(0); i++)

        System.Console.WriteLine(orders[i].ReceiptDateTime.ToString());

}

Posted by xhoto

http://www.codeproject.com/aspnet/ASPNetFileManagement.asp

 

Active Directory 와 xml 파싱해서 내용 처리를 한다.

Posted by xhoto

방범(Caps) 설정같은거 할때보면 장비를 동작시키고 사람이 빠져 나갈 시간을 두어

작동버튼 클릭하고 나서 한 3~5분정도 뒤부터 값을 넘겨 줄려고 합니다.

담 예제에서

버튼에 Threadsleep(60000);

라는것을 추가 했을때

전체가 멈춰버리는 현상이 일어나는데

private void button1_Click(object sender, System.EventArgs e)

        {

            Thread.sleep(60000);

            valuePoint = "100.0 1";

            retWrite = ilon.DataPointWrite(pointName[0], fieldName, valuePoint, priority, propagate);   

        }

그래서 위 문장을 다음과 같이 바꾸었습니다.

 

        private void button1_Click(object sender, System.EventArgs e)

        {

            Thread T1 = new Thread(new ThreadStart(delayTime));

            T1.IsBackground = true;

            T1.Start();

        }

 

        private void delayTime()

        {

            Thread.Sleep(60000);

            valuePoint = "100.0 1";

            retWrite = ilon.DataPointWrite(pointName[0], fieldName, valuePoint, priority, propagate);

        }

결과는 만족 하게 나왔는데 문제는 저기서 시작한 T1.start()를 retWrite되고나면 Abort();시켜줄수는 없나요?

 

그리고 한가지더 1초씩 매번 실행하는 타이머 안에 쓰레드를

Thread T2 = new Thread(new ThreadStart(함수명)); 과같이

쓰레드를 생성했을때

저거 T2.Start();를 타이머에서 한뒤

Abort(); 안해주고 바로 다음 1초뒤 다시

Thread T2 = new Thread(new ThreadStart(함수명)); 를

실행하게 되면 문제가 없나요?

일주일정도 지나도 메모리가 늘어나는것도 아니공... CPU 점유율이 올라가는것도 아니공

생성된 쓰레드는 자동으로 Abort();되는건지도 궁금합니다. ^^;

 

 private void button7_Click(object sender, System.EventArgs e)

        {     int i=0;

            while(i<2000)

            {

                Application.DoEvents();

                System.Threading.Thread.Sleep(100);

                i++;

                this.Text=(i/10).ToString()+"초";

            }

            MessageBox.Show("");

}

Posted by xhoto

Sample Image - dialingparams.jpg

Introduction

Dialing parameters/patterns are strings of information that govern how a phone number is dialed when establishing a RAS connection in Pocket PC. For example:

  • 9,G would dial a 9 and then the base phone number.
  • 1FG would dial 1, the area code, and then the phone number.
Unfortunately, there is no documented API for modifying the dialing parameters in Pocket PC. All of the dialing parameters/patterns are stored in the registry. Being confronted with this problem several times before and finding very little information on the topic, I decided to write a short article on how to do change these settings with EVC 3.0. Writing the DLL in unmanaged code allows for the DLL to be used in EVB (Which I would not recommend anyone to use), EVC, and with the .NET Languages using P/Invoke.

The code in this project will explain how to each of the fields in the screenshots above.

Using the code

Now, modifying the device registry is not that difficult, but the type/format in which the settings are stored makes it less than obvious as to what needs to be done to modify these settings. To save you the heartache of figuring this out, I have done the dirty work for you. Notice the screenshot from the device registry below:



HKEY_CURRENT_USER\ControlPanel\Dial\Locations

This is all fine and dandy, you might say, but where are the settings for Country Code, Tone/Pulse dialing, and the Disable Call Waiting Dial String?
After asking myself this question, I did a little google research and found that the registry actually stores the values in the following format:

  • Location
  • Local Calls Dial String
  • Long Distance Calls Dial String
  • International Calls Dial String
  • Area Codes Dial String
  • Country Code
  • Disable Call Waiting Dial String
  • Tone or Pulse, where Tone = 0 and Pulse = 1
It turns out that the registry editor has a difficult time displaying registry keys of the type REG_MULTI_SZ. According to the Pocket PC 2002 SDK Documentation REG_MULTI_SZ is an array of null-terminated strings, terminated by two null characters. So, somehow the registry editor is getting a little confused when displaying this array of strings, and with that you are whisked away on a wild goose chase to find where the rest of the settings are stored only to determine a few days later that they where right in front of you all along.

Now that we know where all the settings are REALLY stored, we can begin coding.
// C++ CodeBOOL WINAPI SetDialingParameters(WCHAR *KeyName,                  WCHAR *Location,                  WCHAR *LocalCalls,                  WCHAR *LongDistanceCalls,                  WCHAR *InternationalCalls,                  WCHAR *AreaCode,                  WCHAR *DisableCallWaitingSequence,                  WCHAR *CountryCode,                  WCHAR *ToneOrPulse                ){    HKEY hKey;    DWORD dataType = REG_MULTI_SZ;    LONG retVal = 0;    LONG ConfigurationStringSize = 512;    WCHAR *ConfigurationString = new WCHAR[ConfigurationStringSize];    memset(ConfigurationString,'\0',512);    // Build the configuration string.    wcscat(ConfigurationString, Location);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, LocalCalls);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, LongDistanceCalls);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, InternationalCalls);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, AreaCode);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, DisableCallWaitingSequence);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, CountryCode);    wcscat(ConfigurationString, TEXT("$"));    wcscat(ConfigurationString, ToneOrPulse);    wcscat(ConfigurationString, TEXT("$"));    // Format the string correctly.    int ConfigStringLen = wcslen(ConfigurationString);    for(int x = 0; x < ConfigStringLen; ++x)    {       if(ConfigurationString[x] == '$')          ConfigurationString[x] = '\0';    }        // Open the registry key.    retVal = RegOpenKeyEx(HKEY_CURRENT_USER ,                           TEXT("ControlPanel\\Dial\\Locations"),                           0, KEY_READ, &hKey);    if(retVal != ERROR_SUCCESS)     {       delete [] ConfigurationString;       return false;    }        // Set the value of the key.    retVal = RegSetValueEx(hKey, KeyName, NULL, dataType,                           (PBYTE)ConfigurationString,                           ConfigurationStringSize);    RegCloseKey(hKey);    delete [] ConfigurationString;    if(retVal != ERROR_SUCCESS)       return false;    else       return true;}

That's all the code it takes to store the key! Of course now we would want to put this inside a DLL so we can call it from our application. Refer to source file at the top of this article for details on this.

After creating the DLL, you will want to put it to good use. We will now walk through P/Invoking the DLL from managed code since that is what most of you guys will probably be using this with.

Fire up Visual Studio .NET 2003 and create a new Smart Device Application for Pocket PC.
Create a new class for your P/Invoke method and insert the code below into your class definition:

// C# Code[System.Runtime.InteropServices.DllImport("DialingParameters.dll")]public static extern int SetDialingParameters(string KeyName,                     string Location,                     string LocalCalls,                     string LongDistanceCalls,                         string InternationalCalls,                     string AreaCode,                     string DisableCallWaitingSequence,                     string CountryCode,                     string ToneOrPulse                    );
That's it! To call this DLL from EVB, you would need to make a declare statement at the top of your form much like the following:
Declare Function RasDial Lib "DialingParameters.dll"                         Alias "SetDialingParameters" (ByVal KeyName As String,                             ByVal Location As String,                             ByVal LocalCalls As String,                             ByVal LongDistanceCalls As String,                                 ByVal InternationalCalls As String,                             ByVal AreaCode As String,                             ByVal DisableCallWaitingSequence As String,                             ByVal CountryCode As String,                             ByVal ToneOrPulse As String                            ) As Long

Points of Interest

Remember to keep your EVC DLL in the same folder as your consuming application or your method call will fail.

Posted by xhoto

using System;

using Microsoft.Win32;

 

class Reg {

    public static void Main() {

 

        // Create a RegistryKey, which will access the HKEY_USERS

        // key in the registry of this machine.

        RegistryKey rk = Registry.Users;

 

        // Print out the keys.

        PrintKeys(rk);

    }

 

    static void PrintKeys(RegistryKey rkey) {

 

        // Retrieve all the subkeys for the specified key.

        String [] names = rkey.GetSubKeyNames();

 

        int icount = 0;

 

        Console.WriteLine("Subkeys of " + rkey.Name);

        Console.WriteLine("-----------------------------------------------");

 

        // Print the contents of the array to the console.

        foreach (String s in names) {

            Console.WriteLine(s);

 

            // The following code puts a limit on the number

            // of keys displayed.  Comment it out to print the

            // complete list.

            icount++;

            if (icount >= 10)

                break;

        }

    }

}

Posted by xhoto
Download the code for this article: NETColumn0410.exe (121KB)

In the July 2003 installment of the .NET column I covered the basics of Win32® interoperation with the Microsoft® .NET Framework (P/Invoke). Based on reader feedback, this topic is worthy of further coverage, so I have decided to revisit P/Invoke in this column. It will build upon the information in the July 2003 issue, so if you are not familiar with basic .NET interop, I suggest reviewing that column before digging into this one.

This month I am going to delve into the interop details of marshaling data structures to native functions. In a future piece, I hope to address calls into native code that calls back into your managed code, and I'll work through an interop case study using Windows® Forms. So let's get started on marshaling structures.


Marshaling Structures

The common language runtime (CLR) is capable of marshaling references to managed memory to native APIs. In order to accomplish this, the runtime has to consider a number of differences between managed memory and native memory. Let's take a look at some of these differences:

  • The field layout of managed reference objects is reorganized by the runtime (by default)
  • Managed reference objects are garbage collected; native memory is not
  • Managed reference objects are moved around in physical memory by the system; native objects are not
  • Certain common native structure layouts, such as inline arrays, are difficult to accomplish using some .NET-compliant languages such as C# and Visual Basic® .NET

These are the major considerations that you and the CLR must account for when moving data between managed and native code. To begin addressing these differences, I'll start with an example. Figure 1 shows an excerpt from the winbase.h header file in the Windows Platform SDK, that contains the declaration of the GetSystemPowerStatus API and the SYSTEM_POWER_STATUS native structure type definition.

Figure 2 shows C# code that makes a call to the native GetSystemPowerStatus API, and outputs information from the resulting data structure. Note that in the C# code it is necessary to redefine the native SYSTEM_POWER_STATUS type definition as SystemPowerStatus, a managed reference type. The type can have any name, but must have a field layout that matches that of the target data structure. It is also possible to marshal managed value types to native code, which I will cover in a moment. But for now, it is important to note that you need to define a managed type that exactly matches the in-memory layout of the native structure that is expected by the API.

The SystemPowerStatus class in Figure 2 is attributed with the StructLayoutAttribute class. Any time you use a managed reference type to marshal data to native code, you must apply the StructLayoutAttribute to the type definition and specify a layout kind of Sequential. The LayoutKind.Sequential setting tells the runtime to leave the fields in their defined order, which addresses the first difference in the preceding bulleted list. We will look at the StructLayoutAttribute in more detail in a moment, but first let's dig into the memory ramifications of the code in Figure 2.


Object Lifetime and Pinning

Looking at the call to GetSystemPowerStatusRef in Figure 2, a question arises. What happens if a garbage collection kicks in during the call to the native function? If this happens, won't the object referred to by the status local variable potentially be moved around in memory by the collector? In fact, if status were not referred to by subsequent code, couldn't the collector clean up the object entirely while the native method is executing? The answer to these questions would be yes, were it not for the pinning feature of the CLR.

When the runtime marshaler sees that your code is passing to native code a reference to a managed reference object, it automatically pins the object. What this means is that the object is put in a special state where the garbage collector will neither move the object in memory nor remove the object from memory. Pinned objects hurt the performance of the garbage collector, but they assure that the memory remains intact for the life of the native call; this is critical to the proper functioning of the native code.

When the native function returns, the marshaled object is automatically unpinned. Automatic pinning is very convenient, but it raises another question. What happens if the native function caches the pointer for use later on? When the function returns, won't the collector be free to move the object? The answer is yes, and the solution for your code in such a situation is to manually pin the object using the System.Runtime.InteropServices.GCHandle type.

The following lines of code use the GCHandle type in order to pin and unpin a managed string:

String s = "PinMe";GCHandle pinHandle = GCHandle.Alloc(s, GCHandleType.Pinned);try{   •••}finally{   pinHandle.Free();}

Manually pinning an object is not difficult. The tricky part is knowing when you should. The GetSystemPowerStatus API, for example, does not cache the pointer that is passed in as its only argument. And so, automatic pinning is sufficient for calls to this native API. However, an overlapped call to the native ReadFileEx function would require manual pinning of the second and fourth parameters to the call because the API will continue to utilize the referenced memory after the function returns. You need to know the behavior of the function you are calling well enough to decide whether automatic pinning is sufficient, or whether you will need to manually pin your managed object.

Pinning addresses the differences between managed and native memory in terms of moving memory around and collecting unreferenced objects. Now let's take a look at how the native call in Figure 2 differs if we use a value type rather than a reference type.


Marshaling Value Types vs. Reference Types

The code in Figure 3 functions similarly to the code in Figure 2 in that it makes a call to the native GetSystemPowerStatus function. However, in Figure 3 the SystemPowerStatus type is defined as a managed structure rather than a managed class. Said another way, we are marshaling a value type rather than a reference type.

When your code defines a variable of a reference type, the variable is either a reference to an object or it is a null reference. In contrast, a variable of a value type is the actual data, and no reference is involved. This difference between the two data types in the managed type system affects marshaling to native code.

When you pass a reference variable to a native function, the runtime marshals the reference into a native pointer to the data structure. However, when you marshal a value to a native function, the runtime pushes a copy of the value object onto the thread's stack. Sometimes this is what you want, but more often a native API will expect a pointer to a structure (as is the case with GetSystemPowerStatus), and so you have to take steps to indicate to the system that a pointer to the variable should be passed, rather than a copy of the variable.

To do this, you can define the parameter to your static extern P/Invoke method as an out or ref parameter. Remember that this tells the runtime to pass a reference to the variable, rather than to the data in the variable on the stack.

Fundamentally, the difference between marshaling classes and structures is one of indirection. When you marshal a managed reference type, you are always passing either a pointer or a pointer to a pointer. When you marshal a managed value type, you are either passing the data wholesale on the stack or you are passing a pointer to the data. Thus, you can marshal value types with either zero or one level of indirection, while reference types can be marshaled using one or two levels of indirection to the native code.

Surprisingly, you often find that marshaling managed value types is preferable to marshaling managed reference types. One reason is that managed structures are somewhat more similar to C structures than are managed classes. The runtime never reorganizes the field layouts of managed structures written in C# or Visual Basic .NET, and the garbage collector never moves unboxed values around in memory. Most structure marshaling can be performed using either value types or reference types. However, until you have a compelling reason to use a class to marshal data to native code, you should generally use structures.


StructLayoutAttribute

You may have noticed that StructLayoutAttribute is absent from the structure definition in Figure 3. This is because the C# compiler emits one automatically for structures. However, you may still need to use StructLayoutAttribute explicitly with your value type definitions for its other features. StructLayoutAttribute allows you to specify four marshaling settings for your managed reference and value types. They are as follows: layout kind, character set, field packing, and size.

The LayoutKind enumerated value of StructLayoutAttribute can be any of three values: Auto, Sequential, and Explicit. We have already addressed Sequential, which is typically the setting you will use and which is the layout emitted by the C# and Visual Basic .NET compilers when compiling value types not explicitly attributed with a StructLayoutAttribute. Reference types not marked with StructLayoutAttribute default to using Auto layout, which is not a valid setting for code that interoperates with native functions. Finally, there is the Explicit value.

When you set LayoutKind to Explicit, you are telling the marshaler that you want to lay out the fields in your type on a field-by-field basis. Using the Explicit setting also requires you to apply FieldOffsetAttribute to each field in your data type, specifying the relative offset (in bytes) of each field. You do not usually need the full flexibility of LayoutKind.Explicit; however, it is useful for marshaling more advanced data structures, such as unions in C, where fields overlap one another.

The CharSet property of StructLayoutAttribute lets you specify whether Char and String fields in your type are marshaled as one-byte ANSI values or two-byte Unicode values. The CharSet enumerated type includes Ansi, Unicode, and Auto settings. The default is Ansi and this is almost never what you want. Instead, when marshaling a structure containing text, you should generally use the Auto setting, which uses ANSI on Windows 95-based systems and Unicode on Windows NT®-based systems. We'll take a look at an example of marshaling a data structure containing text in just a moment.

The Pack and Size properties of StructLayoutAttribute allow you to specify the packing boundary for your fields and the size of your structure, respectively. The default packing size is eight bytes, which is consistent with most of the type definitions in the Win32 SDK. The size of your data type in memory is usually based on the fields in the type definition. But you can use the Size property to manually set the memory footprint of your type. The Marshal.SizeOf method returns the size, in bytes, of the marshaled version of a managed object or type.


Non-Blittable Marshaling

So far we have only looked at marshaling cases where the runtime is able to pass to native code a pointer that points directly to managed memory. Two things make this possible: pinning and a memory layout consistent with what native code expects. Sometimes, however, it is impractical or impossible for your managed memory to be laid out in the same arrangement as a native equivalent data structure.

In these cases, the runtime makes a copy of your managed object using native memory and native layout. A pointer to the copy is then passed to the native call. If the parameter to the extern method is also marked as [Out] using OutAttribute, then the marshaler will also copy the memory back into your managed ob-ject when the call returns. In these cases, you may have to use MarshalAsAttribute to help the marshaler understand what the native memory layout is supposed to look like. Structures and classes that require marshaling in this fashion are called non-blittable types, and they incur substantially more overhead from the runtime due to the memory allocations and copies. Note, though, that there are some non-blittable types where MarshalAs isn't needed. And there are cases where you could use MarshalAs (such as marking an integer with I4), although in reality the setting would be ignored. And so, while the presence of the MarshalAsAttribute is not necessarily an indicator of whether a type is blittable or non-blittable, it is often useful or necessary for marshaling of non-blittable types.

Let's look at an example. The code in Figure 4 is excerpted from header files in the Win32 Platform SDK. It shows the ANSI versions of the GetVersionEx API function and OSVERSIONINFO structure. The OSVERSIONINFO structure contains an inline array of 128 CHAR values. This field is interesting for two reasons. It is not directly expressible in C# as arrays are always reference types. Also, it is a character array and therefore could be a total of 128 bytes or 256 bytes depending on whether ANSI or Unicode is used. Figure 5 contains the C# code that calls this API.

Notice that the OSVersionInfo class definition in Figure 5 has replaced the inline CHAR array in the native structure with a String object reference in the managed object. Notice also that the field is attributed with MarshalAsAttribute, which specifies that the field should be marshaled as a ByValTStr with a size of 128 characters. I could have chosen to marshal this field as a managed Char[] as well, however that would have the same memory layout as String, and so I chose to use the String for the sake of convenience. See Figure 6 for a picture of the memory layout differences between the native structure and the managed representation of the native structure.

Figure 6 Layout Differences in Native and Managed Memory
Figure 6 Layout Differences in Native and Managed Memory

Figure 6 should make it clear why the runtime can't just pass a pointer to the managed object directly to the native API. The native API is expecting a memory layout similar to the block on the left, where the char array is part of the memory block. The native API would simply treat the pointer/reference field in the managed memory block as two or four char values and would continue to clobber memory after the managed object's block. This is why the runtime must make a second copy of the managed structure with a layout equivalent to the native structure.

In brief, when cases arise in which there is no way to directly express the memory layout of the target structure, you can use MarshalAsAttribute to specify alternate memory arrangements for the marshaled version of the data. In all cases like this, the CLR will have to copy the managed fields to a native memory buffer before calling the native API.

In native code, there is no equivalent to managed metadata. This is why you have to carefully define your managed types to match the resulting native memory expected by the target function. However, the native code's lack of knowledge about the passed-in buffer also allows you to make manual adjustments to meet your needs, for example to handle considerations such as performance.

For instance, an alternative implementation of the managed OSVersionInfo class may choose to ignore the string returned in the last field and just leave that field out of the class definition. Of course, in an implementation such as this, the Size property of the StructLayoutAttribute must be used to extend the size of the instance to leave space for the data; otherwise a call to the native function would cause memory corruption.

Similarly, it is possible to define the last field as 128 individual char fields. Doing this, of course, is tedious. But this up-front effort pays off in back-end performance. The sample code for this column, available on the MSDN®Magazine Web site, includes an implementation of OSVersionInfo that takes this approach. Look for OSVersionInfoBlittable in the sources. The OSVersionInfoBlittable structure is both a value type and is blittable. Calls to GetVersionExBlit will be substantially faster than calls to the counterpart function in Figure 5. Meanwhile, you can use a public property to provide friendly String access to the otherwise unfriendly block of Char fields. The get accessor method in the CSDVersion property uses unsafe C# syntax to create a String object using the address of the first Char in the block of Chars. This has the effect of deferring the conversion portion of the marshaling until code accesses the String. It also limits the conversion to the String portion of the data structure.

Also included in the download is a performance test that runs the blittable and non-blittable interop methods a million times while timing them. On my system the blittable call to GetVersionInfo was over 10 times faster than the non-blittable counterpart.


A Word About Complexity

The P/Invoke facilities of the CLR are very complete and should allow for marshaling of many different kinds of data to native code. As the complexity of your data structures increase, however, you will find more use for unsafe code blocks in C#, the MarshalAsAttribute, and other detailed tools in the interop arsenal. Getting interop right can prove tedious as things get complex.

Part of what makes interop complicated using C# is the fact that C# does not know how to natively read C/C++ header files. If it did, it could help out significantly in your P/Invoke work. However, the C++ compiler is capable of building managed code, and can read standard header files directly. You may find that, for interoperation with certain native functions, a helper DLL written using managed C++ saves some trouble, compared to P/Invoking directly from C#.

That's it for this month's column. Browse over to http://www.pinvoke.net, a site created by Adam Nathan to allow developers to find, edit, and add P/Invoke signatures for public consumption. This has helped many people P/Invoke to Win32 and other APIs without having to battle the complexity alone.

 

http://msdn.microsoft.com/msdnmag/issues/04/10/NET/default.aspx

Posted by xhoto

Platform Invocation Services (PInvoke) allows managed code to call unmanaged functions that are implemented in a DLL.

This tutorial shows you what you need to do to be able to call unmanaged DLL functions from C#. The attributes discussed in the tutorial allow you to call these functions and have data types be marshaled correctly.

Sample Files

See Platform Invoke Sample to download and build the sample files discussed in this tutorial.

Platform Invoke

Further Reading

Tutorial

There are two ways that C# code can directly call unmanaged code:

For both techniques, you must provide the C# compiler with a declaration of the unmanaged function, and you may also need to provide the C# compiler with a description of how to marshal the parameters and return value to and from the unmanaged code.

The tutorial consists of the following topics:

The tutorial includes the following examples:

Calling a DLL Export Directly from C#

To declare a method as having an implementation from a DLL export, do the following:

  • Declare the method with the static and extern C# keywords.
  • Attach the DllImport attribute to the method. The DllImport attribute allows you to specify the name of the DLL that contains the method. The common practice is to name the C# method the same as the exported method, but you can also use a different name for the C# method.
  • Optionally, specify custom marshaling information for the method's parameters and return value, which will override the .NET Framework default marshaling.

Example 1

This example shows you how to use the DllImport attribute to output a message by calling puts from msvcrt.dll.

// PInvokeTest.csusing System;using System.Runtime.InteropServices;class PlatformInvokeTest{    [DllImport("msvcrt.dll")]    public static extern int puts(string c);    [DllImport("msvcrt.dll")]    internal static extern int _flushall();    public static void Main()     {        puts("Test");        _flushall();    }}

Output

Test

Code Discussion

The preceding example shows the minimum requirements for declaring a C# method that is implemented in an unmanaged DLL. The method PlatformInvokeTest.puts is declared with the static and extern modifiers and has the DllImport attribute which tells the compiler that the implementation comes from msvcrt.dll, using the default name of puts. To use a different name for the C# method such as putstring, you must use the EntryPoint option in the DllImport attribute, that is:

[DllImport("msvcrt.dll", EntryPoint="puts")]

For more information on the syntax of the DllImport attribute, see DllImportAttribute Class.

Default Marshaling and Specifying Custom Marshaling for Parameters to Unmanaged Methods

When calling an unmanaged function from C# code, the common language runtime must marshal the parameters and return values.

For every .NET Framework type there is a default unmanaged type, which the common language runtime will use to marshal data across a managed to unmanaged function call. For example, the default marshaling for C# string values is to the type LPTSTR (pointer to TCHAR char buffer). You can override the default marshaling using the MarshalAs attribute in the C# declaration of the unmanaged function.

Example 2

This example uses the DllImport attribute to output a string. It also shows you how to override the default marshaling of the function parameters by using the MarshalAs attribute.

// Marshal.csusing System;using System.Runtime.InteropServices;class PlatformInvokeTest{    [DllImport("msvcrt.dll")]    public static extern int puts(        [MarshalAs(UnmanagedType.LPStr)]        string m);    [DllImport("msvcrt.dll")]    internal static extern int _flushall();    public static void Main()     {        puts("Hello World!");        _flushall();    }}

Output

When you run this example, the string,

Hello World!

will display at the console.

Code Discussion

In the preceding example, the default marshaling for the parameter to the puts function has been overridden from the default of LPTSTR to LPSTR.

The MarshalAs attribute can be placed on method parameters, method return values, and fields of structs and classes. To set the marshaling of a method return value, place the MarshalAs attribute in an attribute block on the method with the return attribute location override. For example, to explicitly set the marshaling for the return value of the puts method:

...[DllImport("msvcrt.dll")] [return : MarshalAs(UnmanagedType.I4)]public static extern int puts( ...

For more information on the syntax of the MarshalAs attribute, see MarshalAsAttribute Class.

Note   The In and Out attributes can be used to annotate parameters to unmanaged methods. They behave in a similar manner to the in and out modifiers in MIDL source files. Note that the Out attribute is different from the C# parameter modifier, out. For more information on the In and Out attributes, see InAttribute Class and OutAttribute Class.

Specifying Custom Marshaling for User-Defined Structs

You can specify custom marshaling attributes for fields of structs and classes passed to or from unmanaged functions. You do this by adding MarshalAs attributes to the fields of the struct or class. You must also use the StructLayout attribute to set the layout of the struct, optionally to control the default marshaling of string members, and to set the default packing size.

Example 3

This example demonstrates how to specify custom marshaling attributes for a struct.

Consider the following C structure:

typedef struct tagLOGFONT {    LONG lfHeight;    LONG lfWidth;    LONG lfEscapement;    LONG lfOrientation;    LONG lfWeight;    BYTE lfItalic;    BYTE lfUnderline;    BYTE lfStrikeOut;    BYTE lfCharSet;    BYTE lfOutPrecision;    BYTE lfClipPrecision;    BYTE lfQuality;    BYTE lfPitchAndFamily;    TCHAR lfFaceName[LF_FACESIZE]; } LOGFONT; 

In C#, you can describe the preceding struct by using the StructLayout and MarshalAs attributes as follows:

// logfont.cs// compile with: /target:moduleusing System;using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential)]public class LOGFONT {     public const int LF_FACESIZE = 32;    public int lfHeight;     public int lfWidth;     public int lfEscapement;     public int lfOrientation;     public int lfWeight;     public byte lfItalic;     public byte lfUnderline;     public byte lfStrikeOut;     public byte lfCharSet;     public byte lfOutPrecision;     public byte lfClipPrecision;     public byte lfQuality;     public byte lfPitchAndFamily;    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]    public string lfFaceName; }

For more information on the syntax of the StructLayout attribute, see StructLayoutAttribute Class.

The structure can then be used in C# code as shown below:

// pinvoke.cs// compile with: /addmodule:logfont.netmoduleusing System;using System.Runtime.InteropServices; class PlatformInvokeTest{         [DllImport("gdi32.dll", CharSet=CharSet.Auto)]      public static extern IntPtr CreateFontIndirect(            [In, MarshalAs(UnmanagedType.LPStruct)]            LOGFONT lplf   // characteristics            );       [DllImport("gdi32.dll")]      public static extern bool DeleteObject(            IntPtr handle            );       public static void Main()       {            LOGFONT lf = new LOGFONT();            lf.lfHeight = 9;            lf.lfFaceName = "Arial";            IntPtr handle = CreateFontIndirect(lf);             if (IntPtr.Zero == handle)            {                  Console.WriteLine("Can't creates a logical font.");            }            else            {                                    if (IntPtr.Size == 4)                        Console.WriteLine("{0:X}", handle.ToInt32());                  else                        Console.WriteLine("{0:X}", handle.ToInt64());                           // Delete the logical font created.                  if (!DeleteObject(handle))                       Console.WriteLine("Can't delete the logical font");            }      }}

Sample Run

C30A0AE5

Code Discussion

In the preceding example, the CreateFontIndirect method is using a parameter of the type LOGFONT. The MarshalAs and In attributes are used to qualify the parameter. The program displays the numeric value returned by the method as a hexadecimal uppercase string.

Registering Callback Methods

To register a managed callback that calls an unmanaged function, declare a delegate with the same argument list and pass an instance of it via PInvoke. On the unmanaged side it will appear as a function pointer. For more information about PInvoke and callback, see A Closer Look at Platform Invoke.

For example, consider the following unmanaged function, MyFunction, which requires callback as one of the arguments:

typedef void (__stdcall *PFN_MYCALLBACK)();int __stdcall MyFunction(PFN_ MYCALLBACK callback);

To call MyFunction from managed code, declare the delegate, attach DllImport to the function declaration, and optionally marshal any parameters or the return value:

public delegate void MyCallback();[DllImport("MYDLL.DLL")]public static extern void MyFunction(MyCallback callback);

Also, make sure the lifetime of the delegate instance covers the lifetime of the unmanaged code; otherwise, the delegate will not be available after it is garbage-collected.

 

 

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkPlatformInvokeTutorial.asp

 

Posted by xhoto

Introduction

MSN messenger is a well known program. It lets you communicate with other users through Instant Messaging. Some people like to write their own MSN messenger, so that they can make some own adjustments and cool features. I have written, together with another student, our own MSN client in C#.  Recently Microsoft no longer supported protocols below MSNP 8. So I had to adjust our program to use MSNP9 (it used MSNP7).

After I have posted an earlier article about MSN, people asked me to give some more information on how to connect to the MSN servers.

So with this little article I would like to explain how you can connect to MSN with the use of the MSNP9 protocol. This article tells you what commands you have to send, and how to react to it. It uses an article that I have posted before. You can find it here.

Using the code

You can use this code in your own program, or you can look and see how you can connect to MSN in C#. The demo programs shows how you can use the following code.

What do we need?

First we use a separate class that will connect to the MSN server. We call it MSNConnection. Next we build another class that handles the commands that we receive from the servers, lets call this class ServerCommand.

Next we need to declare some variables that we will use in the class MSNConnection.

private long            _transactionID = 0;private TcpClient       _socket;private NetworkStream   _stream;private StreamReader    _reader;private StreamWriter    _writer;

The transactionID is sent with almost every message that we send (also in chat sessions). The _reader and _writer are the streams from the socket.

Now we have the above, let's define some functions that will do the work for us. First we need to initialize the socket and StreamReaders.

_transactionID = 0;_socket = new TcpClient(host, port);_stream = _socket.GetStream();_reader = new StreamReader(_stream, Encoding.ASCII);_writer = new StreamWriter(_stream, Encoding.ASCII);_writer.AutoFlush = true;

We call this function ConnectSocket and it takes two parameters (host and port). Every time we make a new connection the transactionId is set to zero. If we make a function that creates the socket, why not make a function that closes the socket. Let's call it dispose.

if( _socket != null ){    _reader.Close();    _writer.Close();    _stream.Close();    _socket.Close();    _socket = null;}

We are making functions that read and write to the StreamReader and StreamWriter. First we define the StreamWriter. We then make a function that builds the string: WriteCommand. It takes 3 parameters: first is the command to send, next the parameters and last the option to leave the transactionId out.

string line;// check what type of format it should beif (bSendId)     line = string.Format("{0} {1} {2}", command, _transactionID, parameters);else    line = string.Format("{0} {1}", command, parameters);// Write the lineWriteLine(line, true);

The function WriteLine eventually writes the string to the StreamWriter. This function has two parameters first is the entire string and next is the option to send only a string and no end character.

if (writeNewLine)    _writer.WriteLine(line);else    _writer.Write(line);// raise the transactionId_transactionID++;

We have defined some writing functions. We also need to read the information. Let's call this function ReadCommand. This function reads from the reader, if there is nothing in the socket then makes an empty ServerCommand, else we make a ServerCommand with the given response.

string  line = _reader.ReadLine();Console.WriteLine("Reading: " + line);if (line == null) {    Console.WriteLine("Nothing received");    return new ServerCommand();}else{    return new ServerCommand(line);}

You noticed that I use the ServerCommand object. Lets look at the ServerCommand class.

private string _cmdID;private string _line;private string[] _params;public ServerCommand(string line){    _line = line;    // always 3 characters command    _cmdID = line.Substring(0, 3);    if (!(_cmdID == "QNG"))    {        _params = line.Substring(4).Split(' ');    }}public ServerCommand(){    _line = "";    _cmdID = "ERROR";}

If we use the constructor with a valid line, then we will get a ServerCommand with the right information. If we get a QNG command then there will be no parameters. The command is always a three letter combination. If we use the constructor with no string, then the program knows that there is something wrong.

The other functions are used for retrieving the data from this class.

public string CommandName{    get { return _cmdID; }}public string Param(int index){    return _params[index];}

Now all the functions are explained above, we can make the Connect function. This function needs two parameters: first is a valid username that has a passport, next is the password for that username.

First we are going to connect to the server.

string  host = "messenger.hotmail.com"; int port = 1863;ConnectSocket(host, port);

Now we are going to write the server commands, the first command we are going to write is the VER command. This command indicates what protocol we are using. We are using protocol MSNP9. We read the result in a new ServerCommand Object.

ServerCommand ServComWriteCommand("VER", "MSNP9 CVRO", true); ServCom = ReadCommand();

Next we are going to check if we received the right information, if not then exit this function.

if (ServCom.CommandName != "VER"){    return 1;}

Now we have to send the CVR command, the parameters are the same like a real MSN messenger client. The server will response with a CVR command and a download place where you can get a newer MSN messenger, we just ignore this.

WriteCommand("CVR",   "0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS " + UserName, true);ServCom = ReadCommand(); 

After this is successful, we send de USR command with a TWN parameter and your username. TWN stands for TWEENER, this is based on the passport authentication.

WriteCommand("USR", "TWN I " + UserName, true);ServCom = ReadCommand();

If the command was not the USR command, it was probably the XFR command, this indicates to us that we have to transfer to another server. In the result is the new host and port, parse it.

string[] arIP = ServCom.Param(2).Split(':');host = arIP[0];port = int.Parse(arIP[1]);

Now disconnect and connect again using the new host and port.

Dispose();

We were operating in a while loop, so the connect sequence starts again. You have to send all the commands again, but this time it is to another server.

If the responsecommand is USR then we are going to connect to this server. The response will hold a ChallengeString, we need this ChallengeString to get a valid ClientTicket.

if (ServCom.CommandName == "USR"){    ChallengeString = ServCom.Param(3);    break;}

With the given ChallengeString we will get a valid clientticket.

string clientticket = GetClientTicket(UserPassword,                                    UserName, ChallengeString);

This step is a rather large step. I have already wrote an article on this part, read all about it right here.

Finally now we have a ticketID, send it to the server.

WriteCommand("USR", "TWN S " + clientticket, true);ServCom = ReadCommand();

If we are in luck, we get the USR |transid| OK message. This indicates that we have successfully connected to the MSN servers.

Let's get our username and our screen name, this information was send together with de USR command.

_UserName = ServCom.Param(2);_ScreenName = ServCom.Param(3);

Last we are going to notify that we are going online, you can put a number of initial status messages here. NLN just means "Online", the rest are:

  • BSY - Busy
  • IDL - Idle
  • BRB - Be Right Back
  • AWY - Away
  • LUN - Out to Lunch
  • PHN - On the Phone
  • FLN - Offline
  • HDN - Hidden
WriteCommand("CHG", "NLN", true);

Now you are connected and everybody who have you in their list will see you online.

Right now, you have to get all the contacts, but that part is too big to explain right here.

Conclusion

Connecting to a MSN server is not that hard, you have to understand what to send and how to reply. Hopefully you have liked this