Run 'Process Viewer' from web

Spoon delivers your apps instantly to any Window desktop, with no downloads, installs, or hassles.
I prepared Process Viewer runs from the Browser by the help of Spoon.

  • Click to the "Install Plugin" button if you do not install the Spoon plug-in yet.
  • Click to the Start button to start the Process Viewer

To get more information about Spoon, or if you want to run your own applications from web with the Spoon you can visit www.spoon.net


Spoon: Run apps instantly from the web

Spoon, which is developed by Code Systems (Xenocode) was released. You can access and try it from the http://www.spoon.net address.

So what is spoon?

Spoon allows users to run applications instantly from their web browsers with a single click. Spoon takes only minutes to deploy and embeds directly into your existing web site.
Spoon allows most apps to launch after downloading less than 10% of the app. Adaptive background downloading continues during execution.

KEY BENEFITS
• Run Apps Directly on Your Site
Create a Flash-like experience from standard Windows applications.

• Eliminate Long Downloads
Innovative streaming technology allows most applications to launch with less than 10% of the content transferred.

• No Code Changes
Spoon works with existing, unmodified applications. No source code is required.

• Zero Installation
Give your users single click, zero-setup access to your entire app portfolio.

• Boost Conversions and Revenue
Replace downloads and setups with instant, in-browser execution.

• New Monetization Opportunities
Present advertising, chat, upsells, and other revenue-generating content alongside your apps.

• Run Anywhere
Apps are available wherever your users go – on the road, locked-down desktops, and even portable USB devices.

HOW IT WORKS
Spoon uses machine learning technology to automatically decompose complex applications into smaller functional and data units. These pieces are adaptively selected for background transfer based on observed behavior as the user progresses through the application.
Spoon is tightly coupled with the industry-leading Xenocode® application virtualization engine. Virtualization packages applications into single, pre-configured executables that run instantly in isolated “sandboxes”, eliminating installation and dependencies.

Have fun ...

Windows Applicationlarını Webden Çalıştırma

Konuya başlamadan önce uzun zamandır siteyi ihmal ettiğim için herkesten özür dilerim. İş yoğunluğundan kaynaklı zaman problemim nedeni ile siteye aylardır yazı ekleyemiyordum. Her neyse bari güzel bir bilgilendirme yazısı yazayımda hatamı az da olsa telafi etmeye çalışayım.

Hepimizin sürekli dillendirdiği bir düşüncedir, Windows Appliationlarını Web den çalıştırmak. Bununla ilgili birçok çalışma yapıldığını da duymuşuzdur hepimiz. Ancak Windows Applicationlarının yapısı ve çalışma mantığının Web sayfalarından çok farklı olması nedeni ile bu konuda çok birşey yapılamamaktadır. Bir windows application da bulunan nesneler (button, checkbox, combobox, listview vs.) birer Window nesneleridir. Kendi aralarında iletişimlerini Windows Messaging denilen bir yapı ile mesajlaşarak yaparlar. Webde ise html nesneler explorer ve benzer browserlarda gösterilirken DOM nesnelerine dönüştürülüp COM nesneleri şeklinde çalışırlar.

Bir Windows Application developerı olarak bunu yıllardır defalarca düşünmüşümdür. Yani bir şekilde Windows Applicationlarını Webden çalıştırmak her zaman istediğim bir şeydi.

Bir kaç ay önce, Kenji Obata, Code Systems yada diğer adı ile Xenocode'un kurucusu bana bu fikirden söz ettiğinde oldukça heyecanlanmıştım. Kenji'nin planı hali hazırda varolan VM (Virtual Machine) lerinide kullanarak istenilen Windows Application'ı Webden çalıştırmaktı. Bana bunun ne kadar mümkün olduğunu, mümkünse bunu yazıp yazamayacağımı sorduğunda ben çok düşünmeden bu işin olabileceğini söyledim. Şimdi bu proje hayatta, ve test aşamasında. Xenocode'un VM ürünü sayesinde virtualize edilmiş herhangi bir program istenildiği takdirde Web'den Surface denilen yapı sayesinde çalıştırılabiliyor.

Şimdi çoğunuzun, arka planda programı indirip çalıştırıyorlardır dediğinizi tahmin ediyorum. Doğru arka planda istenilen bu windows application download edilip çalıştırılıyor. Ancak bu 2 farklı modda yapılıyor.

1 - Normal Mode: Bu modda virtualize edilmiş programı arka planda indirip webde çalıştırıyoruz.

2 - Streaming Mode: Bu moda ise application'ın gerekli yerlerinin indirilip çalışması şeklinde oluyor. Yani Xenocode XStream teknoloji sayesinde programın tamamı gelmeden program çalıştırılıyor. Buda ornegin 1GB lik bir programin %5 lik kısmı geldiğinde çalışıyor olmasını sağlıyor. Düşünün Türkiye gibi internette hız diye birşeyden söz edilemeyen bir ülke için ne büyük bir avantaj. Çok büyük bir programı çalıştırıyorsunuz ve 1 dakka içinde program download edilmiş gibi çalışıyor ve siz kullanmaya başlıyorsunuz. Siz kullandıkça bulunduğunuz yere göre analiz yapıp sonra yapacağınız muhtemel işlemler için gerekli yerleri arka planda indirmeye devam ediyor. Örneğin geçen gün bir demo için hazırlanan oldukça yüklü bir oyunu (177MB) 1 dakikadan kısa bir sürede webden hemde ADSL bağlantısı ile çalıştırıp oynadım. Oldukça zevkli bir tecrübe idi. İstediğiniz programı sadece 1 dakika içinde hemde zahmetsiz bir şekilde bilgisayarınızda çalıştırmak fikir olarak bile insana harika geliyor, bunu birde tecrübe etmek çok daha zevkli.


Ayrıca cache mekanizması sayesinde indirilen bu program localde cachleniyor ve sonraki girişlerinizde sizi indirme belasından kurtarıyor.

Evet bu ürünler sayesinde artık Windows Applicationlarını Web üzerinden hemde download/setup etmeye gerek kalmaksızın çalıştırabiliyoruz. Hemde bunu yaparken programın bilgisayarınıza zarar vermesini engellemek adına tamamen ayrılmış bir ortamda programlar çalıştırılıyor. İndirdiğiniz programın yapacağı ayar değişiklikleri, registry kayıtları tamamen virtual bir ortamda yapılıyor. Yani İşletim sistemize ve bilgisayarınıza zarar vermesi tamamen engellenmiş oluyor.

Bu ürünlerin geliştirilmesi halen devam ediyor. Oldukça profesyonel, çoğunluğu Microsoft'tan ayrılma bir ekip tarafından bir çok şart gözününde bulundurularak geliştirilmeye devam ediliyor, ancak bu hali ilede oldukça başarılı diyebiliriz. Burada şunuda unutmamak gerekir, bu platformun Surface (Windows Applicationlarını Webde çalıştırma) kısmını geliştiren biri olarak şunu söyleyebilirim ki, gerçekten bu tarz bir ürün geliştirmek oldukça zordur. Dünya üzerinde standart ve standart olayan birçok windows application var ve tüm bunları ortak bir yapı içinde çalıştırmaya çalışmak oldukça zahmetli bir iş, hali ile bu ürünün elbetteki şu aşamada bazı sıkıntıları olacaktır, ancak genel ilerleyiş ve varolan sistem içerisinde oldukça başarılı olduğunu çok rahat söyleyebilirim. Microsoft'un bile backward compability konusunda harcadığı emeği düşündüğümüzde bu işin zahmeti daha rahat anlaşılabilir.

Ürün hakkında daha detaylı bilgi almak için Xenocode'un web adresine bakabilirsiniz. Orada birçok virtualize edilmiş programı setup etmenize gerek olmaksızın çalıştırabilirsiniz. Özellikle web developerlar için tüm Browserlara tek sayfadan setup etmeksizin ulaşabilecekleri ve kendi sitelerini farklı browserlarda rahatlıkla test edebilecekleri Browsers page'ini tavsiye ederim. İlk hazırladığımızda oldukça ses getirmişti. XStream ve Surface'le çalışan örnekler ise şu anda demo aşamasındalar ve birçok stability testlerinden geçiyorlar, sanıyorum bir kaç hafta içerisinde XStream ve Surface modunda çalışan applicationlarıda yine Xenocode'un web sitesinde public kullanıma açmış olacağız. Şu aşamada indireceğiniz programlar setup gerektirmeyen Virtualize edilmiş programlar olacaktır.

XStream ve Surface stabil hale geldiğinde yapılacak duyuruyu yine buradan sizlere bildireceğim, o zamana kadar müsadenizle.

Şimdilik herkese kolay gelsin, İyi çalışmalar


Tavsiye

Bugün sevgili arkadaşım Oğuz YAĞMUR'un blogunda Kral Çıplak! mı? yazısın okudum. Aylardır hatta yıllardır içimde biriken ama kibarlık olsun diye çok dillendiremediğim bir konuyu Oğuz oldukça formal bir dille ve güzel bir anlatımla yazmış. Yazıyı okuyunca hemen bende bu konuda birşeyler yazmak istedim. Ama Oğuz yazısında bence bu konuda söylenebilecekleri güzelce söylemiş. Çok kurcalamaya gerek yok. Sizede tavsiyem o yazıyı mutlaka okuyun.


Process Viewer 1.0.7.0

(UPDATED on 18/09/2008)
    Added: Child Windows on Window Tooltip, Opacity setting for Tooltip Window
(UPDATED on 15/09/2008)
    Added: Window Tooltip, shows window information during 'Find Window' 
(UPDATED on 09/09/2008)
    Added: Modifications and ModifiedMsg added to the Breakpoints.
    Modification: Indicates that which sections of the message will be modified if the Action is AutoChangeParameters.
    ModifiedMsg: If a breakpoint's action is AutoChangeParameters and Modification has the Message bit,
                          then PV will change the incoming message to the given message.
                          For ex: You can change the WM_LBUTTONDOWN to WM_RBUTTONDOWN automatically for the target window.
    Multilanguage: (English, Turkish)

Process Viewer 1.0.7.0 (PV) is ready to download. Download Source Codes | Watch Sample Movie (v1.0.5.0)
Below I try to explain what is PV and how it is working. Also I put some screenshots of the PV.
Breakpoints management window

I finished PV 2 days ago, but I was really very sleepy (it was about 4 AM and I had to go to work in the morning) so I postpone this writing to a later time. Anyway today I have some time to write something about PV. What it is? What it is for? How it works?
First I will explain what PV is then I will try to explain its codes a little bit more.

 What is PV?

I can say that PV is a program like Microsoft Spy++. Unlikely to Spy++ it allows you to edit some properties of the Controls and also allows you to manage its window messages. You can change Text, Visibility, Enabled, Window Styles and Window Ex Styles properties of a control by using PV during runtime. Therewithal you can ignore window messages, change incoming message to a different message or edit parameters of any window messages by putting breakpoints to the control’s window procedure with PV.



How can I use PV?
It is really very simple to use PV. Run PV.exe and you will see the active Processes, currently running in your desktop, in the Windows List at the left of the program. Expand any process which you are interested in. You will see the Windows (Controls) which are belong to that process in a hierarchical list. Whenever you select a Window from the list PV will highlight its area in the screen even the window is not visible at the moment. If a Window is a container window which contains inner windows in it you will see inner windows under the owner (parent) window node, so you can expand parent window and see inner windows of it.

There is also Find Window button at the top of the PV which will help you to find Controls and select them easily. Just click to the Find Window button and Drag it over the Controls while you are pushing the Left mouse button. PV will highlight the Control region which mouse currently on it. To select a window, release mouse button when the mouse cursor is on that control. Window will be selected automatically in the Windows List. If window is not in the list (this might be, because PV generates Windows List while it is opening so if the window you try to select was created after you opened PV then this window won't be in the list), PV will shows an alert to you that the window is not in the windows list at the moment, if you chose “Yes” button it will automatically refreshes the Windows List and finds your control.

When you select a window from the windows list you will see its properties in the PropertyGrid at the right. You can change Visible, Enabled, Text, WindowStyles and WindowExStyles properties of that window by using PropertyGrid. Also you can change the window’s Bounds, Size and Location by the same way. If you wish to see the Messages of that control, click to the Listen Messages button at the top toolbar. A panel which contains a TextBox will appear at the bottom of the PV which will shows you the messages of that control. If you want to put breakpoints to the current window’s message procedure click to the Edit Breakpoints button. Breakpoint Management window will be shown and you can add breakpoints to that window by using this window. Select a window message from the list (you can filter messages by writing your message name to the filter textbox) to see breakpoint properties for that message. Select your action (None, Ignore, Manuel Edit, Auto Change) by using PropertyGrid for the selected message(s). You can do same things for the other messages which you are interested in. To remove a message breakpoint just set its action to “None”. After you finished you can close the Breakpoints window by clicking “Okey” button. From now on your breakpoints will be activated and whenever a message, which you define an action for that, arrives to that window PV will do the action which you select for that message.

For example; If you chose WM_LBUTTONDOWN, which system sends to the control when mouse left button is down on that control, from the message list and select ‘Ignore’ action then WM_LBUTTONDOWN message will never send to the control. Or if you choose ManuelEditParameters action for the WM_LBUTTONDOWN then PV will shows you Edit Parameters Window to choose your action against this message when this message arrives to the control. Either you can ignore this message or you can change the wParam and lParam parameters of the message. WPARAM (4 bytes) and LPARAM (4 bytes) of a message contain message specific parameters and they have different meanings according to the Message. If we speak about the WM_LBUTTONDOWN message, the parameters will be;
wParam: Indicates whether various Virtual Keys (MK_LBUTTON, MK_RBUTTON, MK_CONTROL, MK_MBUTTON, MK_XBUTTON1, MK_XBUTTON2) are down. WParam can be one or more of these values.
lParam: Lo-Order of the lParam specifies the X-Coordinate of the cursor and Hi-Order of the lParam indicates the Y-Coordinate of the cursor. Here Lo-Order means first 2 bytes of the lParam and Hi-Order means the last 2 bytes of the lParam.
If you choose Manuel Edit Parameters action for the WM_LBUTTONDOWN then you can change the parameters of It whenever system sends this message to the target window. If you choose AutoChangeParameters action then PV will change wParam and lParam of that message automatically as you defined.

Examples with Breakpoints;

Example 1:
 1 – Open Visual Studio .NET
 2 – Select Main Menu of the VS.NET by using Find Window button of the PV.
 3 – Click “Listen Messages” button to start message hook for the main menu
 4 – Click “Edit Breakpoints” button to set breakpoints
 5 – Select WM_LBUTTONDOWN from the message list and select AutoChangeParameters action for this message.
       Set Modifications to the WParam and LParam (Indicates PV will modify only WParam and LParam of a message before it send to the hooked window)
       Set XParam to the 1 (LoWord:1, HiWord:0) and LParam to the 851998 (LoWord:30, HiWord:13). Click Okey button.
 6 – Click anywhere in the Main Menu, you will see that always File menu is shown.
This is because PV change the LParam to the HiWord:13 and LoWord:30 which means (X=30, Y=13) the cursor position is over the File menu. So main menu opens File menu always because it thinks that File menu has been clicked.

Example 2:
1 – Open Visual Studio .NET
 2 – Select Main Menu of the VS.NET by using Find Window button of the PV.
 3 – Click “Listen Messages” button to start message hook for the main menu
 4 – Click “Edit Breakpoints” button to set breakpoints
 5 – Select WM_LBUTTONDOWN from the message list and select AutoChangeParameters action for this message.
       Set Modifications to the Message and set ModifiedMsg to the WM_RBUTTONDOWN. Click Okey button to set the breakpoints.
 6 – Click anywhere in the Main Menu, you will see that even you click to the Left button of the mouse the main menu always opens its Context Menu.
This is because PV change the WM_LBUTTONDOWN message to he WM_RBUTTONDOWN.




I think this is enough for “How We Use PV?” Let us speak about the “How PV do this?”
We can split this question in to two sections. One is “How PV finds Windows?” and second is “How PV Listens and Edit Messages of a Control?”
For the first question PV uses EnumChildWindows method to enumerate child windows of a Window. It first tries to find the Desktop Window’s child windows and then it finds the inner windows. After it finds the windows, it uses GetClassName, GetWindowThreadProcessId and GetParent methods to find the ClassName, ProcessId, ThreadId and Parent Window Handle of these windows. 



For the second question “How PV Listen and Edit Messages of a Control?”; it is a little bit harder than the first section. To make this, first I wrote a C++ (Native) dll which sets hook on WH_CALLWNDPROC for the given window’s thread. Why I wrote this dll with C++? Actually listening a control’s Windows Messages, is simple. Every control has a Window Procedure method which system sends messages to that method. We can learn the address of this method by using GetWindowLong method with the GWL_WNDPROC option. To change the window procedure method of a control is also very simple;
SetWindowLong(windowHandle, GWL_WNDPROC, [our procedure Method]). By using this method we can replace the message procedure method of a control to our method. So whenever system sends a message to this control it will comes to our method and we can do anything we want in this method. To redirect this message to the original window procedure, we can use CallWindowProc function. But the problem with this is; SetWindowLong method works only for the windows which are belongs to same process. It means that we can use this method for the controls which are in the same process with us. So if we want to change windows procedure of a control we have to be in the same process. How we can handle this problem? To handle this problem I wrote a native dll which will be injected to the target process and we will run the SetWindowLong function from that dll within the target process. Injecting a dll to another application is also a pain for us. There are some solutions for this problem;
1 – We can use SetWindowsHookEx method to set a WH_CALLWNDPROC hook. By setting a hook Windows will automatically Loads our hook dll to all processes. But the problem with this method is, we don’t know the target process is .NET or not. So we have to write a native dll for this hook operation. Because if the target process is not .NET this means there is no CLR attached to that process and our .NET dll won’t be worked within this process. When we call SetWindowsHookEx function systems attach the dll, which contains the hook method, to all processes. At this point; you have to know that for each process, system creates a new instance of our dll and attach it to every process.
2 – LoadLibrary method which is in kernel32.dll loads a library to the caller application. So if we make a call to that function within the target process we can load our library to the target application. How we can call LoadLibrary function within another application? To solve this problem we can use CreateRemoteThread function which is in the kernel32.dll. CreateRemoteThread function creates a remote thread within a given process and runs the given method. To use CreateRemoteThread function we have to also know the address of the target method which we want to run in the target processes memory block. Actually this is hard to find the address of a function in a remote application. GetProcAddress function returns the address of a method, but when we call this method this will be the address of that method within our application because again GetProcAddress will return the address of the function according to the caller process memory. But here is a good trick with the LoadLibrary. LoadLibrary method is in the kernel32.dll and kernel32.dll will always load to the same address for all the windows applications according to nature of windows. So if we take the address of the LoadLibrary function within our application’s memory, this address also will be same for other applications too. So we can take the address of the LoadLibrary and call this method by using CreateRemoteThread method within target process. This will load our dll to the target procedure.

Anyway there are too many details about dll injection so I pass it simply for now. May be we can talk about this later more detailed. In PV I have been used the first way to make dll injection. I wrote a C++ (Native) dll which starts WH_CALLWNDPROC hook on the target process. WH_CALLWNDPROC installs a hook procedure which monitors the messages before the system sends them to the destination window. When the first time that system sends a message to our target window we changed the target window’s message procedure method by using SetWindowLong function. Actually we are using hook operation for two cases; one is injecting our native dll to the target process and second triggering procedure changing method (calling SetWindowLong) from that dll. Therefore SetWindowLong function will be called by the target process. As I said above we can do this in some different ways but I chose this way. Because this way needs less native codes than the others and I want to write less native codes in this example.

// In the PV
[DllImport("ProcessViewer.Hooks.dll")]
public static extern int StartHook(IntPtr hWnd, IntPtr notifyWindow);
 
[DllImport("ProcessViewer.Hooks.dll")]
public static extern void EndHook();

// In the native dll

PROCESSVIEWERHOOKS_API int WINAPI StartHook(HWND hWnd, HWND notifyParent)
{
       originalWindowProcedure = 0;
 
       // Load our libary and get its handle
       HINSTANCE phookDll = LoadLibrary((LPCTSTR)_T("ProcessViewer.Hooks.dll"));
 
       EndHook();
 
       hookWindow = hWnd;
       notifyWindow = notifyParent;
 
       // get Thread Id of the Window, which we will hook
       DWORD threadId = GetWindowThreadProcessId(hWnd, NULL);
       // get address of our Hook method in this dll
       HOOKPROC proc = (HOOKPROC)GetProcAddress(phookDll, "MessageHookProcedure");
       // set Hook (This will injects our dll in to all process
       // which are created by the given thread)
       hhk = SetWindowsHookEx(WH_CALLWNDPROC,
                                               proc,
                                               phookDll,
                                               threadId);
 
       return (DWORD)hhk;
}


// this is our WH_CALLWNDPROC hook method
LRESULT CALLBACK MessageHookProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
       if (originalWindowProcedure == 0)
       {
             // the first time this method is called
             // for the our hooked window, replace its window procedure
             // to our procedure method
             // do this just for the control which we wnat to listen its messages
             CWPSTRUCT* str = (CWPSTRUCT*)lParam;
             if (str->hwnd == hookWindow)
             {
                    // take original windows procedure of this control
                    originalWindowProcedure = GetWindowLong(hookWindow, GWL_WNDPROC);
                    // set new windows procedure
                    SetWindowLong(hookWindow, GWL_WNDPROC, (LONG)OnMessage);
             }
       }
       return CallNextHookEx(hhk, nCode, wParam, lParam);
}

// ends hook operation
PROCESSVIEWERHOOKS_API void WINAPI EndHook()
{
       // if we have been taken procedure of the window,
       // set its procedure to the its original
       if (originalWindowProcedure)
             SetWindowLong(hookWindow, GWL_WNDPROC, originalWindowProcedure);
       if (hhk != NULL)
             UnhookWindowsHookEx(hhk);
       originalWindowProcedure = 0;
       hhk = NULL;
}

From now on any message that system sends to the target window will come to our method because system thinks that window procedure method for that control is our method. Now we need to send this message to the PV to process it. At this point I used VM_COPYDATA message to transfer message to the PV. But to whom I will send this message? I wrote a Listener Control in the PV and I pass its handle to the hook dll while PV starts the hook operation. Hook dll sets this passed handle to a shared variable in it. This way every instance of the native dll has the same value for that variable. So native dll in the target process also has the same variable which holds our listener controls handle. From the native dll which handles the target window’s messages I redirect messages to the Listener Control which is in the PV. Whenever a new WM_COPYDATA messages send to the Listener Control it resolves the original message from the LParam of that message and process it according to our Breakpoints. LParam of the WM_COPYDATA message contains a COPYDATASTRUCT which has original message in it is lpData field.

private class ListenerControl : Control
{
       static int HM_MESSAGE_RESULT;
 
       public ListenerControl()
       {
             HM_MESSAGE_RESULT = NativeMethods.RegisterWindowMessage(
                                                        "ProcessViewer_MessageResult");

             Parent = MainForm;
       }
 
       protected override void WndProc(ref Message m)
       {
             if (m.Msg == (int)NativeMethods.Msgs.WM_COPYDATA)
             {
                    // message was sended by ProcessViewer.Hooks.dll from the Hooked application when
                    // a new message comes to that window
 
                    // LPARAM of this message contains a COPYDATASTRUCT which has HOOK_MSG struct in it
                    NativeMethods.COPYDATASTRUCT cdata = 
                           (NativeMethods.COPYDATASTRUCT)m.GetLParam(
                                             typeof(NativeMethods.COPYDATASTRUCT));
                    // This is the information of the message which is sended to the hooked window
                    NativeMethods.HOOK_MSG msg = (NativeMethods.HOOK_MSG)
                                             Marshal.PtrToStructure(cdata.lpData,
                                                  typeof(NativeMethods.HOOK_MSG));
 
                    // process message and set its result (0 ignore, 1 do nothing,
                    // other values replace parameters)
                    m.Result = MainForm._SubClass.ProcessMessage(m.WParam, ref msg);
                    Marshal.DestroyStructure(m.LParam, typeof(NativeMethods.COPYDATASTRUCT));
             }
             else if (m.Msg == HM_MESSAGE_RESULT 
                    && Properties.Settings.Default.HandleMessageResults)
             {
                    // this message sended by hooked window to give
                    // information about the result of a message
                    MainForm._SubClass.ProcessMessageResult(m.WParam.ToInt32(), m.LParam);
             }
             else
             {
                    base.WndProc(ref m);
             }
       }
}



While PV processing message native dll is waiting for the result and does its action according to this result which comes from the PV. If we don’t have a breakpoint for that message PV returns 1 which means “send message to the original window procedure”.  If we have a breakpoint for this message which the action is “Ignore message”, then PV returns 0 to the native dll and it ignores that message. The hard section of breakpoints is what if we have the “Edit Parameters Manually“ or “Auto Change Parameters” actions for that message. It is hard because we need to transfer changed parameters to the native dll which is running in the target application. We solve this problem by allocating a memory block in the target applications memory by using VirtualAllocEx function. Then we write our changed values to that block by using WriteProcessMemory function. These functions allow us to allocate a memory block in the target application memory block and write to this block. Now we have the address of that memory so we can pass this address to the native dll as the address of new wParam and lParam values. If native dll takes a return value differs from 1 and 0 it knows that this is a memory address which contains new wParam and lParam values. So it reads new values of the parameters from this address and redirects message to the original window procedure by using these parameters. This way we changed the parameters of the message. We can also use this WriteProcessMemory and VirtualAllocEx methods to transfer message from native dll to PV instead of using VM_COPYDATA. But I transfer data by using VM_COPYDATA because VM_COPYDATA message is for transferring data between two processes. Why I don’t use WM_COPYDATA message for transferring result of the message from PV to the native dll instead of using WriteProcessMemory function? The answer is simple. Because I send the incoming message to the PV, by using SendMessage function from window procedure method in the native dll. Thread which calls the SendMessage function will block until it takes a result. So if I try to send return value by using SendMessage to the target window this will be a deadlock.

IntPtr WriteToTargetProcessMemory(IntPtr wParam, IntPtr lParam, NativeMethods.Msgs modifiedMsg)
{
       // Open hooked window's process
       IntPtr hProcess = NativeMethods.OpenProcess( 
                                                 NativeMethods.PROCESS_VM_OPERATION 
                                                 | NativeMethods.PROCESS_VM_READ 
                                                 | NativeMethods.PROCESS_VM_WRITE,
                                                 false, _Window.ProcessId);
       // allocate memory from target proces's memory block
       // 12 bytes : 4 modified msg + 4 wParam + 4 lParam
       IntPtr memAddress = NativeMethods.VirtualAllocEx(hProcess, IntPtr.Zero, 
             12, NativeMethods.MEM_COMMIT, 
             NativeMethods.PAGE_READWRITE);
       if (memAddress == IntPtr.Zero)
             return IntPtr.Zero;
 
       int written = 0;
       // write our new parameter values to the tarhet process memory
       bool hr = NativeMethods.WriteProcessMemory(hProcess, memAddress, 
                                                  new int[] {(int)modifiedMsg, wParam.ToInt32(), 
                                                              lParam.ToInt32()}, 
                                                      12, out written);
       // close handle
       NativeMethods.CloseHandle(hProcess);
 
       if (!hr)
             return IntPtr.Zero;
       return memAddress;
}


// In the native dll
// new window procedure for the selected window
LRESULT CALLBACK OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
       // prepare message information, for sending it to our ProcessViewer program
       HOOK_MSG message;
       message.msg = msg;
       message.wParam = wParam;
       message.lParam = lParam;
 
       // this is for the WM_COPYDATA message,
       // WM_COPYDATA transfers data between 2 process by using this structure
       COPYDATASTRUCT cdata;
       cdata.dwData = 0;
       cdata.cbData = sizeof(message);
       cdata.lpData = &message;
 
 
       // send a WM_COPYDATA to our ProcessViewer which will give information about the message
       // to our program
       LRESULT result = SendMessage(notifyWindow, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cdata);
       // return values, 1: ignore message, 0 do nothing,
 
      // different from 0 and 1 : memory address of data which contains the changed wParam and lParam
       if (result == 1)
             return 0;
       if (result != 0)
       {
             // if result is not 0 or 1
             // this means we are going to change the wParam and lParam
             // which we write new values of these variables to the
             // address (result indicates this address) in the hooked program's memory
             HOOK_RESULT* hr = (HOOK_RESULT*)result;
             msg = hr->msg;
             wParam = hr->wParam;
             lParam = hr->lParam;
       }
       // send message to original window procedure
       LRESULT ret = CallWindowProc((WNDPROC)originalWindowProcedure, hWnd, msg, wParam, lParam);
       // send message to the ProcessViewer application which 
       // give information about the result of the message
       SendMessage(notifyWindow, HM_MESSAGE_RESULT, msg, ret);
       return ret;
}

This is simply how PV works. Of course we can write this procedure in different ways but as I said above I’m trying to write this example by using .NET.

Anyway it is just a two night’s code and I think it is a good start for Spying windows. Have fun!!!


FlagsEditor: Suport for <Enum> : uint

If an enum's underlying type is uint, FlagsEditor threw an invalidcast exception. I have been fixed it and upload new version of the FlagsEditor to the Server. You can download it from here...


Lutz Roeder’s .NET Reflector

Bundan 3 yıl kadar once Xenocode’dan Kenji Obata benle irtibata geçip o zamanlar henüz daha Beta aşamasında olan Fox’u satın almak istediğinde çok bocalamıştım. Acaba Fox’u satsam mı? Yoksa open source yapıp kodlarını mı dağıtsam? Yada hiç bir sey yapmayıp aynen devam edip Fox’u tekbaşıma geliştirme devam mı etsem?

O zamanlar Lutz Roederle de bu konuyu konuşmuştuk, o Fox gibi bir decompile aracının Open Source olmasını çok mantıklı bulmuyordu. Hatta bu tarz tool ların mümkünse kodlarının yayılmamasından yanaydı. Her neyse o zamanlar şartlar beni Fox’u Xenocode’a satmaya mecbur bıraktı diyebilirim. Bu satış sonrasında Fox’un iki yeni sürümünü Xenocode için yazdıktan sonra Fox’un geldiği yeri görünce sattığıma pişman bile olmuştum. Hiç beklemediğim kadar gelişmişti Fox ve keşke satmasaydım demiştim.
More...

How to permit multiple selections for Enum properties?

PropertyGrid will use default editor for the properties which’s type is enum. This default editor does not allow multiple selections even the Enum has Flags attribute.
I have been prepared a new Editor for this kind of properties. You can download the source codes from here

Download Source Codes


Our editor’s code is as follows;
internal class FlagsEditor : UITypeEditor
{
       FlagsEditorControl editor = null;

       public FlagsEditor()
       { }

       // our editor is a DropDown editor
       public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
       {
             return UITypeEditorEditStyle.DropDown;
       }

       public override object EditValue(ITypeDescriptorContext context, 
                                        IServiceProvider provider, object value)
       {
             // if value is not an enum than we can not edit it
             if (!(value is Enum))
                    throw new Exception("Value doesn't support");

             // try to figure out that is this a Flags enum or not ?
             Type enumType = value.GetType();
             object[] attributes = enumType.GetCustomAttributes(typeof(FlagsAttribute), true);
             if (attributes.Length == 0)
                    throw new Exception("Editing enum hasn;t got Flags attribute");

             // check the underlying type
             Type type = Enum.GetUnderlyingType(value.GetType());
             if (type != typeof(byte) && type != typeof(sbyte)
                    && type != typeof(short) && type != typeof(ushort)
                    && type != typeof(int)&& type != typeof(uint))
                    return value;

             if (provider != null)
             {
                    // use windows forms editor service to show drop down
                    IWindowsFormsEditorService edSvc = provider.GetService(
                                    typeof(IWindowsFormsEditorService))
                                  as IWindowsFormsEditorService;
                    if (edSvc == null)
                           return value;
                    if (editor == null)
                           editor = new FlagsEditorControl(this);
                    // prepare list
                    editor.Begin(edSvc, value);
                    // show drop down now
                    edSvc.DropDownControl(editor);
                    // now we take the result
                    value = editor.Value;
                    // reset editor
                    editor.End();
             }
             return Convert.ChangeType(value, type);
       }

}


In this code FlagsEditorControl is a UserControl which PropertyGrid hosts it in a drop down during the edit operation.
You can change your design by changing this Control.

To use this editor for a property, we have to write Editor Attribute to that property as the below;
// set editor of this property to our FlagsEditor
[Editor(typeof(FlagsEditor), typeof(UITypeEditor))]
public FileAttributes FlagsAttribute
{
       get { return _FlagsAttribute; }
       set { _FlagsAttribute = value; }
}

What is the problem of .NET with the EnableWindow?

EnableWindow function enables or disables the mouse and keyboard input to the specified control. You can use this function from user32.dll as the follows;

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool EnableWindow(HandleRef hWnd, bool enable);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool EnableWindow(IntPtr hWnd, bool enable);


But .NET Framework’s Control class, it is the base class to create a custom control in .NET, manages its Enable property a little bit different from the unmanaged Controls and Windows. Normally we can understand a control’s enable status from its Window Styles. If it contains WS_DISABLED flag this means that the given control is disabled otherwise it is enabled. But .NET Framework’s Control class does not use this WS_DISABLED flag. Instead it uses its own mechanism to understand that it is Enabled or not? So when we use EnableWindow function on a .NET Control it just enables the window and set its flags. But .NET still uses its own state flag which we can only change it by using Enabled property of that class. So .NET Framework Control still things that it is not enabled.
Therefore it is painted as disabled and does not accept mouse inputs. Actually default window procedure of this control started to accept mouse messages but again Control class’s own mechanism checks that is this control Enabled property before processing the mouse message.
Although Control which is enabled by EnableWindow function does not accept mouse messages, it begins to accept keyboard messages. Because there is no limitation in .NET Control class for the keyboard messages like mouse messages.

Here is the .NET's codes;
private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
{
       MouseButtons buttons1 = Control.MouseButtons;
       SetState(0x8000000, true);
       if (!GetStyle(ControlStyles.UserMouse))
       {
             DefWndProc(ref m);
       }
       else
       {
             if ((button == MouseButtons.Left) && GetStyle(ControlStyles.Selectable))
             {
                    FocusInternal();
             }
       }
       if (buttons1 == Control.MouseButtons)
       {
             if (!GetState2(0x10))
             {
                    CaptureInternal = true;
             }
             // Here checks Enabled property to process mouse events
             if ((buttons1 == Control.MouseButtons) && Enabled)
             {
                    OnMouseDown(new MouseEventArgs(button, clicks, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
             }
       }
}

public bool Enabled
{
       get
       {
             // uses 3rd bit of the state flag to indicate the Enabled value
             if (!GetState(4))
             {
                    return false;
             }
             if (ParentInternal == null)
             {
                    return true;
             }
             return ParentInternal.Enabled;
       }
       set
       {
             bool value = Enabled;
             // sets the 3rd bit of the state flag
             SetState(4, value);
             if (value != value)
             {
                    if (!value)
                    {
                           SelectNextIfFocused();
                    }
                    OnEnabledChanged(EventArgs.Empty);
             }
       }
}

internal bool GetState(int flag)
{
       // state is a field
       return (state & flag) != 0;

}

Code extracted by Xenocode Fox .NET Decompiler

Something about CollectionEditor

Today I wrote a simple example which shows how we can use CollectionEditor of the .NET. In addition to this I also made a simple example which shows how to implement custom CollectionEditor which allows us to add more than one item to the collection.

Download Example Sources

Download Example

public class ExampleComponent : Component{
       ArrayListCollection _ArrayListItems = new ArrayListCollection();
       List<Button> _ListItems = new List<Button>();
       List<Control> _MultipleItems = new List<Control>();

 
      public ExampleComponent()
       { }

       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains only Control objects in an ArrayList")]
       [Category("Behaviour")]
       public ArrayListCollection ArrayListItems
       {
             get { return _ArrayListItems; }
       }

       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains only Button objects in a List<Button> collection")]
       [Category("Behaviour")]
       public List<Button> ListItems
       {
             get { return _ListItems; }
       }

       // custom editor attribute
       [Editor(typeof(CustomCollectionEditor), typeof(UITypeEditor))]
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains ListView, Button and CheckBox items in a List<Control> collection")]
       [Category("Behaviour")]
       public List<Control> MultipleItems
       {
             get { return _MultipleItems; }
       }

       public class ArrayListCollection : ArrayList
       {
             // CollectionEditor searches collection type's Index property and finds its property type.
             // It uses this type to add new items
             public new Control this[int index]
             {
                    get { return base[index] as Control; }
             }
       }

       // Custom collection editor.
       // by using this editor we can add ListView, Button and
       // CheckBoxes to the same collection
       public class CustomCollectionEditor : CollectionEditor
       {
             public CustomCollectionEditor()
                    : base(typeof(List<Control>))
             {}

             // override this method if you have to do custom initializing
             // operations. For example, if you have to use a constructor which
             // takes arguments you can create your own items here ...
             // or may be you have to do some initializing operations ...
             protected override object CreateInstance(Type itemType)
             {
                    if (itemType == typeof(CheckBox))
                    {
                           CheckBox checkbox = new CheckBox();
                           checkbox.Text = "My Text, hede";
                           return checkbox;
                    }
                    Control control = base.CreateInstance(itemType) as Control;
                    control.Text = "Other, hede";
                    return control;
             }

             // if you want to use a custom collection editor form,
             // you have to override this method and return your form here
             protected override CollectionEditor.CollectionForm CreateCollectionForm()
             {
                    return base.CreateCollectionForm();
             }

             // here you can return a text which will be appeared in the list
             // for the given item
             protected override string GetDisplayText(object value)
             {
                    Control control = value as Control;
                    return string.Format("{0} - {1}", control.GetType().Name, control.Text);
             }

             // we allow 3 types can be added to our collection
             protected override Type[] CreateNewItemTypes()
             {
                    return new Type[] { typeof(ListView), typeof(Button), typeof(CheckBox) };
             }
       }

}


Extending PropertyGrid: Adding custom PropertyTab and PropertyDescritors

Property Tab Example  Download Example
Most of the programmers who uses Visual Studio .NET knows PropertyGrid which is the main control in the Properties Window of the Visual Studio.

PropertyGrid’s default PropertyTab (System.Windows.Forms.PropertyGridInternal.PropertiesTab) shows properties and their current values of the given object. If we want to make some customizations we can use Browsable, DefaultValue, Description, Category, Localizable etc. attributes. For example you can hide a Property by adding Localizable(false) attribute to that property.

If you want to make more customization which you cannot do with these attributes you can create your own PropertyTab and add it to the PropertyGrid.  I made an example which filters properties according to my custom attribute(OzcanPropertyAttribute). Withal it shows hidden properties as a read-only property in the PropertyGrid. You can download example with the source codes here.

To create you custom PropertyTab for the PropertyGrid, you have to derive you class from PropertyTab class. Then you have to override its GetProperties method.
You can add your custom PropertyTab to your PropertyGrid like;

private class CustomPropertyTab : PropertyTab
{
    public
CustomPropertyTab()
    { }

    public override PropertyDescriptorCollection GetProperties(object component,
                                            Attribute
[] attributes)
    {
        PropertyInfo[] properties = component.GetType().GetProperties(
                                            BindingFlags.Instance | BindingFlags
.Public);
        List<PropertyDescriptor> filtereds = new List<PropertyDescriptor
>();
        PropertyDescriptorCollection propertyDescriptions = TypeDescriptor
.GetProperties(
                                                                component, attributes);
        Type myAttributeType = typeof(OzcanPropertyAttribute
);

        List<string> ignoreds = new List<string
>();
        for (int
i = 0; i < properties.Length; i++)
        {
            if (properties[i].IsDefined(myAttributeType, true
))
            {
                filtereds.Add(propertyDescriptions[properties[i].Name]);
            }
            else
            {
                ignoreds.Add(properties[i].Name);
            }
        }

        // now add a custom property descriptor to show hidden properties
        PropertyDescriptorCollection coll = new PropertyDescriptorCollection
(
                                                filtereds.ToArray());
        if (FormMain
.Instance._Settings.ShowHiddenProperties)
            coll.Add(new
CustomPropertyDescriptor(ignoreds.ToArray()));
        return
coll;
    }

    public override
Bitmap Bitmap
    {
        get
        {
            return
Properties.Resources.finance_16;
        }
    }

    public
override string TabName
    {
        get { return "Ozcan Properties Tab"
; }
    }
}

If you want to make more customization you can create your own PropertyDescriptors and create your own PropertyDescriptorCollection which contains these PropertyDescriptors. Check example source codes for how to implement custom PropertyDescriptors.

I think this is enough for now (it is 1:14 AM, i still have some other jobs to finish), in the future we can make more complicated example about this subject.


How to make Multilanguage supported Category and Description Attributes?

If you have written any .NET components you must be familiar with Category and Description attributes. We use Category attribute to identify the property’s category and Description attribute is for the short description of that property. But because of the nature of Attributes in .NET we cannot pass any parameter to these attributes for Multilanguage support.

[Category(Properties.Resources.MyCategory)]
[Description(Properties.Resources.MyDescription)]
public int MyProperty { … }

This kind of usage is not allowed for .NET, because we are only allowed to give constant values to the attributes constructor.  So how can we use these attributes as Multilanguage?

Solution is simple;
Deriving two new attributes from Category and Description attributes will handle our problem. Because PropertyGrid uses PropertyDescriptors which resolves properties description and category from these two attributes, so if we derived our new attributes from DescriptionAttribute and CategoryAttribute this will also continue to work for PropertyGrid and all kind of grids which uses PropertyDescriptors.

Our new attributes will be;

[AttributeUsage(AttributeTargets.All)]
internal class SRDescriptionAttribute :
DescriptionAttribute
{
    bool ps = false
;

    public SRDescriptionAttribute(string
description) : base(description)
    {    }

    public override string
Description
    {
       
get
       
{
            if
(!ps)
            {
                ps = true
;
                // Here we read the multilanguaged text from the resources
                // by using given Description text as Key
                base.DescriptionValue = Properties.Resources.ResourceManager.GetString(base
.Description);
            }
            return base
.Description;
        }
    }
}


[AttributeUsage(AttributeTargets.All)]
internal sealed class SRCategoryAttribute :
CategoryAttribute
{
    public SRCategoryAttribute(string
category) : base(category)
    {  }

    protected override string GetLocalizedString(string
value)
    {
        // Here we read the multilanguaged text from the resources
        // by using given Category text as Key
        return Properties.Resources
.ResourceManager.GetString(value);
    }
}



Now we can use these attributes. The only thing that we have to do is giving the resource names as the description and category to the attributes.

Usage:
[SRCategory(“Cat_MyCategory”)]
[SRDescription(“Des_MyProperty”)]
public int MyProperty { … }
* Cat_MyCategory and Des_MyProperty are the names of resources in the resource file.

Actually as you see, for the Category attribute GetLocalizedString method and for the Description attribute Description property were both was written as virtual, which means that derived classes can override them (They wish Smile so).


How to create TFS WorkItems programmatically

If you are using Team Foundation Server with Visual Studio, it will be useful for you to integrate your projects bug system with the TFS Work Items system. You can write a simple module for your program which will handles the exceptions and collects needed information and send them to the TFS.

So how can we do something like that? First you have to write an error management module which will handles exceptions, errors, etc. and generates understandable information from them. After generating this information lastly you have to send this information to the TFS.

In addition to this it will be helpful if you create your error information title unique in some cases to check that is this bug already entered as a Work Item Bug or not? For example you can combine type of the exception and last stack frame(s) which this error occurred in.

Anyway let us write a simple code which will enter our error as Work Item Bug to the TFS by programmatically. The code is so simple; you can also find more complicated codes on the web. 

const string USERNAME = "XXXX";
const string PASSWORD = "XXXX";
const string DOMAIN = "MyDomain";
const string TFS_SERVER = "http://mytfsserver:8080";
const string PROJECT = "LANCET";

protected void Page_Load(object sender, EventArgs e)
{
 string title = Request.QueryString["Title"];
 string description = Request.QueryString["Description"];
 string email = Request.QueryString["Email"];
 string force = Request.QueryString["Force"];
 if (string.IsNullOrEmpty(force))
  force = "1";

 try
 {
  NetworkCredential account = new NetworkCredential(USER_NAME, PASSWORD, DOMAIN);
  TeamFoundationServer server = new TeamFoundationServer(TFS_SERVER, account);
  Project project = null;

  server.Authenticate();
  WorkItemStore store = new WorkItemStore(server);
  project = store.Projects[PROJECT];
  if (project == null)
   throw new Exception("Project could not found");
  string wiql = "SELECT [System.Id], [System.Title], [System.Description] " +
     "FROM WorkItems " +
     "WHERE [System.TeamProject] = '" + PROJECT + "' " +
     "AND [System.Title] = '" + title + "'";
   
  WorkItemCollection collection = store.Query(wiql);
  StringBuilder tmp = new StringBuilder();
  tmp.Append(title);
  if (!string.IsNullOrEmpty(description))
  {
   tmp.Append("\r\n");
   tmp.Append("-----------------------------------------------------------------");
   tmp.AppendLine();
   tmp.AppendLine(description);
  }
  if (!string.IsNullOrEmpty(email))
  {
   tmp.AppendLine();
   tmp.Append("-----------------------------------------------------------------");
   tmp.AppendLine();
   tmp.AppendLine(email);
  }
  if (collection.Count == 0 || force == "1")
  {
   WorkItem item = new WorkItem(project.WorkItemTypes["bug"]);
   item.Title = title;
   item.AreaPath = @"CPM\Inbox";
   item.State = "Active";
   item.Description = tmp.ToString();
   item.Save();
  }
  else
  {
   WorkItem item = collection[0];
   item.Open();
   item.State = "Active";
   item.History += "\r\n\r\n" + DateTime.Now.ToString()
     + " ----------------------------------------------------\r\n" + tmp.ToString();
   item.Save();
  }
  Response.Write("SUCCESS - Bug successfully inserted to the TFS");
 }
 catch (Exception ex)
 {
  Response.Write("ERR-" + ex.Message);
 }
}

As you see here, first we try to connect to the TFS server with the given network credentials, then we search for the project which will own this bug. After that we are trying to search that is there any Work Item which has the same title (which is unique for us). If we find an existing entry than we re-activate that task and add a history to it. If we don’t find any entry for this title then we add a new Bug case for this. Actually as I said before the code is so simple, you can change it according to your necessity.

Finally we have to talk about one more thing. What if the machine which our program runs on and generates exception does not have any access privileges to the TFS server machine? Because of some security reasons you may don’t want to open your system. In this case you can use a Website to solve this problem. Create a local web page which takes needed information from Request and runs the code above. So you can call this web page from your program and everything will be worked fine.


Project Lancet

Project Lancet which will be a .NET Assembly Level Editor is started ...


More ...










How to protect an assembly from decompiling

When I was newbie in .NET, it was a shocked for me to learn that .NET assemblies can be decompile. But today I know that this is a normal situation for a language which is compiling to an intermediate language. As we know that, after compiling a .NET project the output will be in MSIL (Microsoft Intermediate Language). And during the application lifecycle this codes will be compiled to Native Codes by the JIT (Just-In-Time Compiler) when they first used and cached in that computer for the future usages. Anyway this is another subject for us how JIT works, but here the problem is our assemblies are in MSIL format which has about 229 opcodes and all these opcodes has a standard working procedure. So if we know these opcodes and how they are working, we can produce the .NET codes by reverse engineering. This is simply what decompilers do. But why there are no stable decompilers for the native exes? The answer is simple, because there are no metadata for the native exes. In the .NET I can say that, metadata of that assembly is really very important to resolve the Type and Member structures of that assembly. Anyway there are a lot of decompilers for the .NET which can decompile codes as same as with the original codes. Xenocode Fox Decompiler and Reflector are the most know ones.
Below is an example which shows us what a decompiler can do.

Original Code Decompiled Code
private void btnRun_Click(object sender, EventArgs e)
{
    Stopwatch watch = new Stopwatch();
   
    int iteration = 0;
    if (!int.TryParse(txtNumIteration.Text, out iteration))
        iteration = 10000000;
    int value = 0;
    if (!int.TryParse(txtNumParam.Text, out value))
        value = 50;
    IExample ex = null;
    int caseCount;
    switch (cmbCases.SelectedIndex)
    {
        case 0:
            caseCount = 5;
            ex = new Example5();
            break;
        case 1:
            caseCount = 10;
            ex = new Example10();
            break;
        case 2:
            caseCount = 20;
            ex = new Example20();
            break;
        case 3:
            caseCount = 50;
            ex = new Example50();
            break;
        default:
            caseCount = 99;
            ex = new Example99();
            break;
    }
    int r = 0;
    watch.Start();
    for (int i = 0; i < iteration; i++)
    {
        r = ex.GetSwitchResult(value);
    }
    watch.Stop();
    long swResult = watch.ElapsedMilliseconds;
    watch.Start();
    for (int i = 0; i < iteration; i++)
    {
        r = ex.GetIfResult(value);
    }
    watch.Stop();
    AppendItem(iteration, caseCount, value, swResult, watch.ElapsedMilliseconds);
}
private void btnRun_Click (object sender, EventArgs e)
{
     int caseCount;
     Stopwatch watch = new Stopwatch();
     int iteration = 0;
     if (!int.TryParse(txtNumIteration.Text, out iteration))
     {
          iteration = 10000000;
     }
     int value = 0;
     if (!int.TryParse(txtNumParam.Text, out value))
     {
          value = 50;
     }
     IExample ex = null;
     switch (cmbCases.SelectedIndex)
     {
          case 0:
          {
               caseCount = 5;
               ex = new Example5();
               break;
          }
          case 1:
          {
               caseCount = 10;
               ex = new Example10();
               break;
          }
          case 2:
          {
               caseCount = 20;
               ex = new Example20();
               break;
          }
          case 3:
          {
               caseCount = 50;
               ex = new Example50();
               break;
          }
          default:
          {
               caseCount = 99;
               ex = new Example99();
               break;
          }
     }
     int r = 0;
     watch.Start();
     for(int i = 0; i < iteration < i++)
     {
          r = ex.GetSwitchResult(value);
     }
     watch.Stop();
     long swResult = watch.ElapsedMilliseconds;
     watch.Start();
     for (int i = 0;i < iteration; i++)
     {
          r = ex.GetIfResult(value);
     }
     watch.Stop();
     AppendItem(iteration, caseCount, value, swResult, watch.ElapsedMilliseconds);
}
Decompiled code was generated by using Xenocode Fox



As you see here, the output is nearly as same as the original code when we decompile the assembly with Xenocode Fox.

So the question is how we can protect our assemblies from decompiling. Actually the answers is simple, except we don’t make our .net assemblies native, we cannot. By one way or other decompilers can decompile our codes back to the source codes. But against the decompilers there are Obfuscators which helps us to protect our codes from decompiling. If we have to explain what an obfuscator do, simply, Obfuscators changes the names of our Types and Members (properties, methods, fields, events etc.) to unreadable or unmeaning full names in the metadata of our assembly. By this way when someone decompiles our codes they can only see the unmeaning full class and member names which is really hard to understand the code. Generally we make the type and member names as understandable. For example if we write a class which indicates a User’s information, we will probably make the class name as User. So after decompiling the person who decompiles the code, sees this User class and he/she understands that this class is for the user information. So if we change the name of this class to an understandable name (for ex: xbc3453vbgf345) then it will be really hard to understand what this class is for. Except from changing the type and member names some obfuscators also can make .net assemblies as native, or some of them can injects useless codes to our methods which cause our methods hard to understand.

There are a lot of Obfuscators like Xenocode PostBuild, CodeVeil, Salamander etc. I’m using PostBuild to obfuscate my codes and I can say that it is really enough to protect my assemblies. Not only changing the type and member names but also we can make our assemblies Native by using PostBuild, or we can allow it to injects some codes which protects our methods to be decompiled (by injecting some untargeted branches) etc. etc. Making our assemblies as native will stops cares about decompiling. Code injection will obstruct Reflector and Fox to decompile that methods. PostBuild also can make our assemblies smaller by compressing and removing unused metadata by dead code elimination. This will increase our assemblies’ performance. Anyway you can check PostBuild by downloading its trial version. More About Xenocode Postbuild | Download PostBuild Evaluation

As conclusion, I can say that using a good obfuscator is enough to protect our codes. There is no need to care about decompilers. Even I develop a decompiler, I still continue to develop my other projects by using .NET and I have no care about this.

Power of Switch Comparing with If-Else

Switch vs IfMost of the people know that switch works like if-else blocks. The only difference between the switch and if-else is its being for the many conditional states, and also writing switch is more simple than if-else block. This knowledge is really a big mistake because switch has a different algorithm and working-procedure comparing to if-else block. To demonstrate this, I wrote a simple example which indicates the performance differences between switch and if-else in many different situations. Download the source codes of this demonstration example and than let's speak about it a little bit more. 

First let me explain the details of this Example. In the example, there are three arguments, which we are using in our tests.
These arguments are as follows;

# of iterations: Indicates that how many times we are testing the same situation. We cannot understand the difference of time by only one test because of the CPU's speed. CPU will do the switch or if-else operations in a very short time. So to understand the real difference, we need to do the same test again and again. Then we have to check the time difference in total.
Parameter (Search Value): In the example, there is an if-else or a switch block which is searching from 1 - [# of cases]. Here the Parameter will indicates that in which case or else-if block our value is in. If you give the parameter a value of 1, this means that first case or first if block will return true. If you give a 99, this means that the 99th case or else-if block will return true. Actually this is the number of how many if-else conditions will be checked.
# of cases: This number indicates the total number of the conditions, which means how many cases or if-else block we have.

After giving these arguments; if you click to the Run Test button, it will make a test by using the given arguments and add a line to the results, which indicates properties and results of the test.

The above picture is showing the results of my 7 tests. Now let's speak about these tests and than let me explain why the result is this way.
In the tests 1, 2 and 3 the arguments of the tests are same. The only difference is the Search Value which I try to select from the beginning, from the middle and finally from the end of the conditional block. As we see in the column for the switch, it does not matter what we are searching for. The time is nearly the same for each test (88, 86, 87). But for the if-else block, the time will dramatically increase according to the Search value. If we are searching for a number which is at the bottom of the if-else block, it takes too long; and if we select a number which is from the beginning of if-else block, it takes less time. But even for the smaller and for the bigger numbers, switch is always faster than if-else block.

To talk about other tests, we only change the # of case. This means the only difference is the number of the total conditional operations. But again the results show us that the switch is faster than if-else block, and number of conditions it is very important for the if-else block but not very important for the switch.

As I say at the beginning, most of the people think that switch works same as if-else block but this test shows us it is not true. So how does switch work?

Switch has a very simple but good algorithm. When we write a switch, it will automatically loads the first case's value, then calculates the index number of the target case block, and adds an array of addresses of case block in the IL. For example:

public void GetSwitchResults(int value)
{
    switch (vaue)
    {
        case 1:
            return 1;
        case 2:
            return 2;
        case 3:
            return 3;
        case 4:
            return 4;
        case 5:
            return 5;
        default:
            return int.MinValue;
    }
}
.method public hidebysig newslot 
virtual final instance int32 
GetSwitchResult(int32 valuecil managed
{
     // Code Size: 63 byte(s)
     .maxstack 2
     .locals init (
          int32 num1,
          int32 num2)
     L_0000: nop 
     L_0001: ldarg.1 
     L_0002: stloc.1 
     L_0003: ldloc.1 
     L_0004: ldc.i4.1 // loads the first cases value (1)
     L_0005: sub // calculation [our value - first value]
     L_0006: switch (L_0021,L_0025,L_0029,L_002D,L_0031)
     L_001f: br.s L_0035 // address of default case
     L_0021: ldc.i4.1 // case 1
     L_0022: stloc.0 
     L_0023: br.s L_003D
     L_0025: ldc.i4.2  // case 2
     L_0026: stloc.0 
     L_0027: br.s L_003D
     L_0029: ldc.i4.3 // case 3
     L_002a: stloc.0 
     L_002b: br.s L_003D
     L_002d: ldc.i4.4 // case 4
     L_002e: stloc.0 
     L_002f: br.s L_003D
     L_0031: ldc.i4.5 // case 5
     L_0032: stloc.0 
     L_0033: br.s L_003D
     L_0035: ldc.i4 -2147483648 // default case
     L_003a: stloc.0 
     L_003b: br.s L_003D
     L_003d: ldloc.0 
     L_003e: ret 
}
IL codes generated by Xenocode Fox 2007

The IL output of the left code above will look like as the right one. When compiling the code, switch puts a target for each case. And during runtime when we give a number to the switch, it checks the difference between the first case and our value, and the result indicates the index of the target case. So if the index is in one of the cases, it directly branches to the given case's address. Actually the calculation formula is [our value] - [first case's value], which returns us the index of our target case in the target cases array. You can see this in the IL. During the compile, compiler will generates the needed calculation codes just before the switch.

Let me explain it a little bit more with an example: Considering the code above, if we give a value 2, it will do the following action. 2 - 1 = 1. So second address (because of 0 based indexing) in the targets list is the starting address of our case block. So it directly goes to the L_0025 which the case 2:begins. Considering the value 3, the calculation will be like 3 - 1 = 2. So it goes to the third address in the target list, and so this address is L_0029(begins of the case 3).

There are 2 problems here. One of them is about the default case because although there are 5 cases and one default case (total 6), there are only 5 targets in the addresses array. And the second problem is what happens if the number does not fall between in any of the cases (for ex: 23, it does not exists in the cases list). For the first problem: If there is a default case in a switch, compiler will adds a br.s [TARGET] after the switch instruction which the TARGET indicates the starting address of the default case. If there is no default case, compiler will again add a br.s [TARGET] after the switch, but this time TARGET will indicates the ending address of switch.

For the second problem: After the calculation, if the result (index of the target case) is not a valid index for our target cases array, then switch does not do anything, so the next instruction (which br.s [TARGET] as we explain above) will execute and it will directly go to the default case if exists; otherwise it goes out of the switch. For example if the value is -1, then the calculation will be -1 - 1 = -2 which is not a valid index. So this value will directly go to the default case. It is also the same as for the value 6. After the calculation, the index will be 5 but our targets array has only 5 elements, so 5 is not a valid index for our switch again.

Now let's go into the switch deeper. As we see in these examples, there might be a subtract operation on the switch condition to make the first value as zero. So this means that switch condition must be an integral type, which can be int16, int32, int64, enum etc. You cannot use float or double values in the switch cases. For example, the following code will not compile:

switch (a) // a is float
{
     case 0.1f:
         break;
     case 0.2f:
         break;
}


Compiler won't compile the switches as how we write them. It may add some codes to the switch or may directly remove the switch and instead of it, it adds an if-else block to the IL. This will be done by the compiler automatically according to the number and values of the switch's cases and condition of the switch. Check the following examples:
Code After Compile
switch (a)
{
    case 1:
        break;
    case 3:
        break;
    case 4:
        break;
    case 5:
        break;
}
 switch (a)
{
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    case 4:
        break;
    case 5:
        break;
}
Switch cases must increase one by one continuously. If one item could not be found (here case 2), compiler will add an empty case for that number. Because of the calculation each element indicates a target. So there must be a target for the case 2, otherwise switch algorithm will not work. But this doesn't mean that every time we use switch compiler fills the empty cases. In some situations, it can convert the switch to if - else block. Here it is not important for the compiler how we write the orders of the cases. It will first sorts the cases according to the case values, and then it will check the empty spaces.

Code After Compile
switch (a)
{
    case 5:
        break;
    case 24:
        break;
    case 28:
        break;
}
if (a == 5)
{

}else if (a == 24)
{

}else if (a == 28)
{

}
Here in this example, compiler must add too many cases to fill all the empty spaces but instead of adding cases, compiler will compile this code as if-else block.

What about char and string cases? Can we use them or not?
For the char cases, I can say that yes. Because chars can be converted to int, so compiler can use char types in the switches without doing anything.
For the string cases, I can say again yes but this not common. That’s to say, again compiler decide this. In some cases, it converts them to if - else block (especially if the number of cases is small, for ex- 3 cases). And in some cases it will compile them as switch cases. So how can it be? As I said before, switches need integral types as cases conditions, and string is not an integral type. So how can this take place?

For the strings, compiler adds a Dictionary<string, int> item to a Compiler Generated class in that assembly. Then it will add the string values as string into that dictionary as int KeyValuePair which string is the case value and int is the order of the case. And during the runtime it will first try to get the int value of that string from the dictionary, and then use that value in the switch.

Anyway using switches (for more conditional operations) in the .NET will be better than using if - else block. Of course, if the conditions are constant values and type of the value is one of the integral types or string.

Xenocode PostBuild - The application failed to initialize properly (0xc000007b)

In one of my public projects, I used Xenocode PostBuild to obfuscate my codes. PostBuild is a very popular and common Obfuscation Tool for the .NET assemblies. When I worked for the Xenocode, I saw that the developers of PostBuild are really very good at doing their jobs. Most of them had worked for the Microsoft before. So I can say that if you need an obfuscation tool, you can use Xenocode PostBuild obfuscation tool without thinking a second.

But after I obfuscated my binaries with Postbuild, I started to get an error as "The application failed to initialize properly (0xc0000077b)". Actually this error does not occur in all computers, it just occurs in computer which has .NET Framework 3.0. After working on this problem a little bit more, I finally solved the bug. The problem was because of the "Enable Output Compression" options in the Postbuild. By enabling this option, you will allow Postbuild to compress your assemblies and inject some codes to perform on-the-fly decompression. When I unchecked the Enable Output Compression option and re-obfuscate it, the problem is gone.

So the solution for this exception is simple. Just disable "Enable Output Compression" option and re-obfuscate your assemblies.
Also let me tell where this option is in the Postbuild. Go to the Optimize tab and it is there at the bottom of the page

!!! NOTE: Kenji, who is from Xenocode, wrotes a comment and said that this bug was fixed in the latest version of the Xenocode PostBuild. So if you are using a version newer than 5.2.6839, there won't be a problem. But if you got this error, then try to download the latest patch from the Xenocode, so you can obfuscate your assemblies with the compression option.


What is the best way to declare static fields?

Today I wrote a simple application, which shows what the difference is between initializing a static field in the explicit static constructor and doing the same during the declaration time (inline). I know that even when we initialize our static fields inline, the compiler will add an implicit static constructor to that class and initialize static values in that method. But this example showed me that there is really a long time difference between initializing static fields inline and in explicit static constructor. Here are a screenshot from the example - in this example BeforeFieldInit means that the static fields are initialized inline and NotBeforeFieldInit means that static fields are initialized in the explicit static constructor:

Screen Capturing Example

Download Example Code

Declaring a static field and initializing its value in an explicit static constructor.

using System;

namespace
BeforeFieldInitExample
{
    public class
NotBeforeFieldInit
    {
        // here there is only decleration of the static field
        public static int
A;

        static
NotBeforeFieldInit()
        {
            // Initialization of A's values is here in the explicit static constructor
            A = 0;
        }
    }
}


Initializing a static fields value during the decleration (inline).

using System;

namespace
BeforeFieldInitExample
{
    public class
BeforeFieldInit
    {
        public static int
A = 0;
    }
}


These two code groups will work as the same and produce the same result. Actually when we compile the second code, the output will be as the same with the first code. I mean, during the compiling time the compiler will create an implicit static constructor for the BeforeFieldInit class and initialize the field's value in that method. So it will be the same with the first code.

But there is a small difference between these codes. The difference can only be seen by checking the IL codes of these types.

For the first example, IL code of the class NotBeforeFieldInit will be as follows:

.class public auto ansi NotBeforeFieldInitClass
            extends
object
{
    .
method public hidebysig specialname
            rtspecialname instance
            void .ctor() cil managed
    {
        // Code Size: 7 byte(s)
        .maxstack
8
        L_0000: ldarg.0
        L_0001: call instance
void object::.ctor()
        L_0006: ret
    }

    .
method private hidebysig specialname
            rtspecialname static
            void .cctor() cil managed
    {
        // Code Size: 22 byte(s)
        .maxstack
8
        L_0000: nop
        L_0001: ldc.i4.0
        L_0002: stsfld int32 BeforeFieldInitExample.NotBeforeFieldInitClass::A
        L_0007: ldc.r8 9
        L_0010: stsfld float64 BeforeFieldInitExample.NotBeforeFieldInitClass::B
        L_0015: ret
    }

    .field public static
int32 A
    .
field public static
float64 B
}


And for the second example, which the name of the class is BeforeFieldInit's IL code will be as runs:
.class public auto ansi
            beforefieldinit // here beforefieldinit mask is added
                BeforeFieldInitClass

        extends object
{
    .
method public hidebysig specialname
            rtspecialname instance
            void .ctor() cil managed
    {
       // Code Size: 7 byte(s)
        .maxstack
8
        L_0000: ldarg.0
        L_0001: call instance
void object::.ctor()
        L_0006: ret

    }

    .method private hidebysig specialname
            rtspecialname static
            void .cctor() cil managed
    {
        // Code Size: 21 byte(s)
        .maxstack
8
        L_0000: ldc.i4.0
        L_0001: stsfld int32 BeforeFieldInitExample.BeforeFieldInitClass::A
        L_0006: ldc.r8 9
        L_000f: stsfld float64 BeforeFieldInitExample.BeforeFieldInitClass::B
        L_0014: ret

     }

    .field public static int32 A
    .
field public static
float64 B
}

IL codes generated by Xenocode Fox 2007

As you see in the IL the only difference between these two codes is the second class's having the beforefieldinit flag. So what is this flag doing?

beforefieldinit flag tells to the JIT that this class's static fields are initialized inline. If a class has no beforefieldinit flag, then JIT compiler will automatically check whether explicit static constructor is called before. This means that whenever you want to try to access any static member of this class or try to create a new instance of this class, JIT will automatically calls the explicit static constructor. Therefore you will loose performance because whenever you try to access a static member, JIT also checks whether static constructor is invoked before. But in the second example if we add a beforefieldinit flag to our class, this means that our static members are initialized inline, so JIT does not need to check whether static constructor is invoked before. This is the main reason that causes performance difference between those two classes. When we wrote an explicit static constructor and initialize our fields' values, the compiler will not add beforefieldinit flag to that class. But if we initialize our static fields inline, then compiler will add an implicit static constructor and initialize our static fields there and also add the beforefieldinit flag to our class.

So always, try to use inline field initialization for the static fields if you can.

How to Capture Screenshot and Paste Any Image to the Screen

Screen Capturing ExampleFor a very long time ago (about 4 years...), in one of my projects, I needed to capture the screenshot which must have to support both full screen capturing and specific regional capturing.

Also I need to paste that captured image back to the screen programmatically. At that moment I solved my problem by using some WinApi methods in the user32.dll and gdi32.dll. Here I want to share that code with you. You can also download the example source codes.

To use this code;
Use CaptureScreen() method to capture whole screen;
Use CatureRegion(Region) to capture only the given region of the screen;
Use PasteToScreen(Bitmap, Region) method to paste any image to the given region on to the screen.

Download Source Codes and Demo Exe 

Here are the codes ...

public class NativeMethods
{
    ///
<summary>
   
///
Takes a screenshot of full screen
   
///
</summary>
   
/// <returns>Return the Bitmap of the Screen
</returns>
   
public static Bitmap
CaptureScreen()
    {
        return CaptureRegion(null
);
    }

    /// <summary>
    ///
Takes a Screen Shot of the given rectangle.
    ///
</summary>
    /// <param name="rct">Rectangle area which we try to get the screen shot.
</param>
    /// <returns>Return the Bitmap of the screen defined rectangle.
</returns>
    public static Bitmap CaptureRegion(Rectangle
rct)
    {
        return CaptureRegion(new Region
(rct));
    }

    /// <summary>
    ///
Takes a screen shot of the given region.
    ///
</summary>
    /// <param name="rgn">Region that which we try to get the picture of it.
</param>
    /// <returns>
Returns the Bitmap of the given region.
    ///
Bitmap Size will be equal to the GetBounds() of the Region.
    ///
Any other points that they are not in the region and
    /// which are in the Bounds will be as Color.Transparent.
</returns>
    public static Bitmap CaptureRegion(Region
rgn)
    {
        IntPtr
hSDc, hMDc;
        IntPtr
hBtm, hOldBtm;
        Size imgSize = Size
.Empty;
        int
xCoor = 0, yCoor = 0;
        if (rgn == null
)
        {
            hSDc = CreateDC("DISPLAY", string.Empty,string.Empty, string
.Empty);
            hMDc = CreateCompatibleDC(hSDc);
            imgSize = new Size
(GetDeviceCaps(hSDc, 8),
            GetDeviceCaps(hSDc, 10));

            GraphicsPath p = new GraphicsPath
();
            p.AddRectangle(new Rectangle
(0, 0, imgSize.Width, imgSize.Height));
            rgn = new Region
(p);
        }
        else
        {
            hSDc = GetDC(IntPtr
.Zero);
            SelectClipRgn(hSDc, rgn.GetHrgn(Graphics
.FromHdc(hSDc)));
            hMDc = CreateCompatibleDC(hSDc);

            RECT myBox = new RECT();
            GetClipBox(hSDc, ref
myBox);
            imgSize = new Size
(myBox.Width, myBox.Height);
            xCoor = myBox.left;
            yCoor = myBox.top;
        }

        hBtm = CreateCompatibleBitmap(hSDc,
                imgSize.Width, imgSize.Height);
        hOldBtm = SelectObject(hMDc, hBtm);
        BitBlt(hMDc, 0, 0, imgSize.Width, imgSize.Height,
                hSDc, xCoor, yCoor, RasterOperations
.SRCCOPY);
        hBtm = SelectObject(hMDc, hOldBtm);

        DeleteDC(hSDc);
        DeleteDC(hMDc);

        Bitmap bmp = Bitmap.FromHbitmap(hBtm);
        RectangleF rct = rgn.GetBounds(Graphics
.FromImage(bmp));
        RectangleF[] rcts = rgn.GetRegionScans(new Matrix
());
        for (int
i = 0; i < rcts.Length; i++)
        {
            rcts[i].X -= rct.X;
            rcts[i].Y -= rct.Y;
        }

        for (int x = 0; x < bmp.Width; x++)
        {
            for (int
y = 0; y < bmp.Height; y++)
            {
                bool isIn = IsInRectangles(rcts, (float)x, (float
)y);
                if
(!isIn)
                    bmp.SetPixel(x, y, Color
.Transparent);
            }
        }
        DeleteObject(hBtm);
        return
bmp;
    }

    /// <summary>
    ///
Checks that is in region.
    ///
</summary>
    public static bool IsInRegion(Region rgn, Point
pt)
    {
        RectangleF[] rcts = rgn.GetRegionScans(new Matrix
());
        return
IsInRectangles(rcts, pt);
    }

    public static bool IsInRectangles(RectangleF[] rcts, Point
pt)
    {
       return IsInRectangles(rcts, (float)pt.X, (float
)pt.Y);
    }

    /// <summary>
    ///
 Checks that is Point in Rectangles (Scans of Region).
    ///
</summary>
    public static bool IsInRectangles(RectangleF[] rcts, float x, float
y)
    {
        for (int
i = 0; i < rcts.Length; i++)
        {
            if
(rcts[i].Contains(x, y))
            {
                return true
;
            }
        }
        return false
;
    }

    public unsafe static void PasteToScreen(Bitmap bmp, Region rgn)
    {
        if (bmp == null || rgn == null
)
            return
;
        IntPtr hDc = GetDC(IntPtr
.Zero);
        Graphics g = Graphics
.FromHdc(hDc);
        RectangleF rctF = rgn.GetBounds(Graphics
.FromHdc(hDc));
        Rectangle rct = new Rectangle((int)rctF.X, (int)rctF.Y,
                                   (int)rctF.Width, (int
)rctF.Height);
        g.SetClip(rgn, CombineMode
.Replace);
        g.DrawImage((Image
)bmp, rct);
        DeleteDC(hDc);
        g.Dispose();
    }

    // NATIVE METHODS
    [DllImport("gdi32.dll"
)]
    public static extern int BitBlt(IntPtr srchDC, int srcX, int
srcY,
                        int srcW, int srcH, IntPtr desthDC, int destX,
                        int destY, RasterOperations
op);

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern IntPtr CreateDC(string lpDriverName,
                        string
lpDeviceName,
                        string lpOutput, string
lpInitData);

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern IntPtr CreateCompatibleDC(IntPtr
hDC);

    [DllImport("gdi32.dll"
)]
    public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetDC(IntPtr
hWnd);

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern int GetClipBox(IntPtr hDC, ref RECT rectBox);    

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern int SelectClipRgn(IntPtr hDC, IntPtr
hRgn);

    [
DllImport("gdi32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC,
                                           int nWidth, int nHeight);

    [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr
hObject);

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern bool DeleteDC(IntPtr hDC);

    [DllImport("gdi32.dll", CharSet = CharSet
.Auto)]
    public static extern IntPtr DeleteObject(IntPtr
hObject);

    [
DllImport("user32.dll")]
    public static extern IntPtr SetTimer(IntPtr hWnd, int nIDEvent,
                                    int uElapse, TimerProc
lpTimerFunc);

    public delegate void TimerProc(IntPtr hWnd, int msg, IntPtr wParam,
                                      IntPtr
lParam);

    [DllImport("user32.dll"
)]
    public static extern bool KillTimer(IntPtr hwnd, int idEvent);


    public enum RasterOperations :
uint
    {
        SRCCOPY = 0x00CC0020,
        SRCPAINT = 0x00EE0086,
        SRCAND = 0x008800C6,
        SRCINVERT = 0x00660046,
        SRCERASE = 0x00440328,
        NOTSRCCOPY = 0x00330008,
        NOTSRCERASE = 0x001100A6,
        MERGECOPY = 0x00C000CA,
        MERGEPAINT = 0x00BB0226,
        PATCOPY = 0x00F00021,
        PATPAINT = 0x00FB0A09,
        PATINVERT = 0x005A0049,
        DSTINVERT = 0x00550009,
        BLACKNESS = 0x00000042,
        WHITENESS = 0x00FF0062
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct
RECT
    {
        public int
left;
        public int
top;
        public int
right;
        public int
bottom;

        public
int Width
        {
            get { return
right - left; }
        }

        public int
Height
        {
            get { return
bottom - top; }
        }
    }
}


How to Find SQL Servers on a Network

Most of us developing our programs by using MSSQL Server, and it is a necessary for us to make SQL Server selectable in the Options Dialog. But here the problem is how we can find the SQL Servers in the network ?

There are two different way we can use for searching the network for the available Sql Servers.

1 - There is a class in the .NET Framework which name is SqlDataSourceEnumerator in the System.Data.Sql namespace. We can use that class, and get the sql servers easly:

DataTable sqls = SqlDataSourceEnumerator.Instance.GetDataSources();

In this method we can only get the Sql Server machines on a network. But in the second method we can also search the Terminal machines, server machines etc.

2 - We can use NetServerEnum function in the netapi32.dll. The following code demonstrates us how we can find SQL Servers in a network...

public class NativeMethods
{
    public const uint
ERROR_SUCCESS = 0;
    public const uint
ERROR_MORE_DATA = 234;
    

   
[
DllImport("netapi32.dll", EntryPoint = "NetServerEnum"
)]
    public static extern int
NetServerEnum(
            [MarshalAs(UnmanagedType
.LPWStr)]
            string
servername,
            int
level,
            out IntPtr
bufptr,
            int
prefmaxlen,
            ref int
entriesread,
            ref int
totalentries,
            SV_101_TYPES
servertype,
            [MarshalAs(UnmanagedType
.LPWStr)]
            string
domain,
            int resume_handle);
 
    

   
[DllImport("netapi32.dll", EntryPoint = "NetApiBufferFree"
)]
    public static extern int NetApiBufferFree(IntPtr buffer);

    [StructLayout(LayoutKind.Sequential)]
    public struct
SERVER_INFO_101
    {
        [MarshalAs(UnmanagedType
.U4)]
        public PLATFORM_ID
sv101_platform_id;
        [MarshalAs(UnmanagedType
.LPWStr)]
        public string
sv101_name;
        [MarshalAs(UnmanagedType
.U4)]
        public uint
sv101_version_major;
        [MarshalAs(UnmanagedType
.U4)]
        public uint
sv101_version_minor;
        [MarshalAs(UnmanagedType
.U4)]
        public SV_101_TYPES
sv101_type;
        [MarshalAs(UnmanagedType
.LPWStr)]
        public string
sv101_comment;
    }

    public enum SV_101_TYPES :
uint
    {
        SV_TYPE_WORKSTATION = 0x00000001,
        SV_TYPE_SERVER = 0x00000002,
        SV_TYPE_SQLSERVER = 0x00000004,
        SV_TYPE_DOMAIN_CTRL = 0x00000008,
        SV_TYPE_DOMAIN_BAKCTRL = 0x00000010,
        SV_TYPE_TIME_SOURCE = 0x00000020,
        SV_TYPE_AFP = 0x00000040,
        SV_TYPE_NOVELL = 0x00000080,
        SV_TYPE_DOMAIN_MEMBER = 0x00000100,
        SV_TYPE_PRINTQ_SERVER = 0x00000200,
        SV_TYPE_DIALIN_SERVER = 0x00000400,
        SV_TYPE_XENIX_SERVER = 0x00000800,
        SV_TYPE_SERVER_UNIX = 0x00000800,
        SV_TYPE_NT = 0x00001000,
        SV_TYPE_WFW = 0x00002000,
        SV_TYPE_SERVER_MFPN = 0x00004000,
        SV_TYPE_SERVER_NT = 0x00008000,
        SV_TYPE_POTENTIAL_BROWSER = 0x00010000,
        SV_TYPE_BACKUP_BROWSER = 0x00020000,
        SV_TYPE_MASTER_BROWSER = 0x00040000,
        SV_TYPE_DOMAIN_MASTER = 0x00080000,
        SV_TYPE_SERVER_OSF = 0x00100000,
        SV_TYPE_SERVER_VMS = 0x00200000,
        SV_TYPE_WINDOWS = 0x00400000,
        SV_TYPE_DFS = 0x00800000,
        SV_TYPE_CLUSTER_NT = 0x01000000,
        SV_TYPE_TERMINALSERVER = 0x02000000,
        SV_TYPE_CLUSTER_VS_NT = 0x04000000,
        SV_TYPE_DCE = 0x10000000,
        SV_TYPE_ALTERNATE_XPORT = 0x20000000,
        SV_TYPE_LOCAL_LIST_ONLY = 0x40000000,
        SV_TYPE_DOMAIN_ENUM = 0x80000000,
        SV_TYPE_ALL = 0xFFFFFFFF
    }

    public enum PLATFORM_ID :
uint
    {
        PLATFORM_ID_DOS = 300,
        PLATFORM_ID_OS2 = 400,
        PLATFORM_ID_NT = 500,
        PLATFORM_ID_OSF = 600,
        PLATFORM_ID_VMS = 700
    }
}


We can use the following native methods as follows;

public List<string> GetSqlServers()
{
    List<string> servers = new List<string>();
    int
readed = 0;
    int
total = 0;

    do
    {
        IntPtr
buffer;
        NativeMethods.SERVER_INFO_101
server;
        int retVal = NativeMethods.NetServerEnum(null, 101, out
buffer, -1,
                                ref readed, ref
total,
                                NativeMethods.SV_101_TYPES.SV_TYPE_SQLSERVER, null
, 0);

       
if
(retVal == NativeMethods.ERROR_SUCCESS ||
                    retVal == NativeMethods
.ERROR_MORE_DATA ||
                    readed > 0)
        {
            int
handle = buffer.ToInt32();
            for (int
i = 0; i < readed; i++)
            {
                server = (NativeMethods.SERVER_INFO_101)Marshal
.PtrToStructure(
                                    new IntPtr(handle),
                                    typeof(NativeMethods.SERVER_INFO_101
));

                handle += Marshal
.SizeOf(server);
                servers.Add(server.sv101_name);
            }
        }
        NativeMethods
.NetApiBufferFree(buffer);
    }
    while
(readed < total && readed != 0);

    return
servers;
}


In this example if you call the GetSqlServers method, this will return you the list of the SQL Servers on the network.

Not only for the SQL Servers also you can find any other group of computers by using NetServerEnum method. The SV_101_TYPES enumeration identifies the type of the computer, which you can search for. If you use another value of this enum in GetSqlServers method, you will get the computers list of that kind.

For example; if you are searching for Teminal Servers on the network, use SV_TYPE_TERMINALSERVER while calling NetServerEnum method in the GetSqlServers method. This will returns you the Terminal Servers on the network.

Search

Calendar

<<  March 2010  >>
MonTueWedThuFriSatSun
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
View posts in large calendar

Disclaimer

© 2007 - 2009
Ozcan DEGIRMENCI
All rights reserved. The content can be used elsewhere given that the source is properly acknowledged.