Angel Hernández

Webcast recording and demos for "Parallel Computing with Native C++ in Microsoft Visual Studio 2010" / Grabación del webcast y demos de "Computación paralela con C++ nativo en Microsoft Visual Studio 2010"

Hi Community,

Please feel free to download the recording and demos from today's Webcast -  "Parallel Computing with Native C++ in Microsoft Visual Studio 2010" . It's in Spanish though Smile 

Regards,

Angel

 


Hola Comunidad,

 

Por favor siéntanse libres de descargar la grabación y demos del Webcast de hoy  "Computación paralela con C++ nativo en Microsoft Visual Studio 2010"

Saludos,

Angel

 

 

How to make your windows obey WPF?

Hi community,

This post can be considered as a follow up post about WPF and Win32. In this opportunity, the requirement was to force every window that does not belong to our application, to remain placed at the bottom edge of our window, so far we’re unable to place another window on top of ours, which is implemented as a toolbar and must be on top of every window, however it’s possible to drag and move any other window underneath our own (specially in a multi-monitor environment)

The solution I came up with is composed of the following Win32 function calls

and the implementation of the following methods.  The one shown below receives our application’s handle and gets the handle for every running window in the system. This information is then filtered via a LINQ query which has two conditions that must be met:

  • The window must be visible
  • The window’s area must be inside the boundaries of our application

Once we’ve executed our query, we  retrieve the window handle through the MainWindowHandle property plus the window’s area (RECT), this information is used in our Where clause

   1: public static void CheckForOverlappedWindows(IntPtr hWnd) {
   2:     Rectangle ownRect, selectedWindow;
   3:  
   4:     var visibleWindows = (from Process currentProcess in Process.GetProcesses()
   5:                           select new {
   6:                               hWnd = currentProcess.MainWindowHandle,
   7:                               Rect = CheckWindowBoundaries(currentProcess.MainWindowHandle)
   8:                           }).Where(match => Win32Support.IsWindowVisible(match.hWnd) &&
   9:                                   IsRectUnderneathOurWindow(hWnd, match.Rect));
  10:  
  11:     Win32Support.GetWindowRect(hWnd, out ownRect);
  12:  
  13:     visibleWindows.ToList().ForEach(overlappedWindow => {
  14:         if (Win32Support.GetWindowRect(overlappedWindow.hWnd, out selectedWindow)) {
  15:             // Place it at the bottom edge of our Window 
  16:                 Win32Support.MoveWindow(overlappedWindow.hWnd, ownRect.Left, ownRect.Bottom - 5,
  17:                  ownRect.Right, (selectedWindow.Bottom - selectedWindow.Top), true);
  18:         }
  19:     });
  20: }

This method returns the area (RECT) of the selected window

   1: public static Rectangle? CheckWindowBoundaries(IntPtr hWnd) {
   2:     Rectangle tempRect;
   3:     Rectangle? retval = null;
   4:  
   5:     if (Win32Support.GetWindowRect(hWnd, out tempRect))
   6:         retval = tempRect;
   7:  
   8:     return retval;
   9: }

And this other method is responsible for determining if the selected windows is inside our window’s boundaries, if this is the case then true is returned otherwise false is returned

   1: private static bool IsRectUnderneathOurWindow(IntPtr hWnd, Rectangle? rect) { 
   2:     Rectangle ownRect;
   3:     bool retval = false;  
   4:  
   5:    if (rect.HasValue && Win32Support.GetWindowRect(hWnd, out ownRect)) 
   6:      retval = (rect.Value.Top < 0 || rect.Value.Top >= ownRect.Top) && rect.Value.Top <= ownRect.Bottom;
   7:  
   8:    return retval;
   9: }

As you can see, we’re making the existing windows “obey” our application based on WPF.

Regards,

Angel

¿Cómo hacer que nuestras ventanas obedezcan a WPF?

Hola comunidad,

El siguiente post es continuación del post anterior sobre WPF y Win32. En esta oportunidad el requerimiento era forzar las ventanas que no pertenezcan a nuestra aplicación a mantenerse en el borde inferior de la misma, hasta ahora no podemos colocar ninguna ventana encima, pero como es una barra de herramientas y está por encima de todas las ventanas, puede darse el caso que se arrastre y coloque debajo de nuestra aplicación (Especialmente en ambientes multi-monitores)

La solución consiste en realizar llamadas a las siguientes funciones en Win32

e implementar los siguientes métodos. El mostrado abajo recibe el handle de nuestra aplicación y recupera el handle de todas las ventanas en ejecución, para luego filtrar esto mediante una consulta de LINQ basado en dos condiciones, las cuáles son:

  • La ventana debe ser visible
  • El área de dicha ventana debe estar dentro de los límites de nuestra aplicación

Cuando ejecutamos nuestra consulta, recuperamos el handle de la ventana a traves de la propiedad MainWindowHandle y el área que ocupa la ventana (RECT), esta información es luego utilizada para filtrar nuestra consulta

   1: public static void CheckForOverlappedWindows(IntPtr hWnd) {
   2:     Rectangle ownRect, selectedWindow;
   3:  
   4:     var visibleWindows = (from Process currentProcess in Process.GetProcesses()
   5:                           select new {
   6:                               hWnd = currentProcess.MainWindowHandle,
   7:                               Rect = CheckWindowBoundaries(currentProcess.MainWindowHandle)
   8:                           }).Where(match => Win32Support.IsWindowVisible(match.hWnd) &&
   9:                                   IsRectUnderneathOurWindow(hWnd, match.Rect));
  10:  
  11:     Win32Support.GetWindowRect(hWnd, out ownRect);
  12:  
  13:     visibleWindows.ToList().ForEach(overlappedWindow => {
  14:         if (Win32Support.GetWindowRect(overlappedWindow.hWnd, out selectedWindow)) {
  15:             // Place it at the bottom edge of our Window 
  16:                 Win32Support.MoveWindow(overlappedWindow.hWnd, ownRect.Left, ownRect.Bottom - 5,
  17:                  ownRect.Right, (selectedWindow.Bottom - selectedWindow.Top), true);
  18:         }
  19:     });
  20: }

Éste método retorna el área (RECT) que ocupa la ventana seleccionada

   1: public static Rectangle? CheckWindowBoundaries(IntPtr hWnd) {
   2:     Rectangle tempRect;
   3:     Rectangle? retval = null;
   4:  
   5:     if (Win32Support.GetWindowRect(hWnd, out tempRect))
   6:         retval = tempRect;
   7:  
   8:     return retval;
   9: }

y éste se encarga de determinar si la ventana seleccionada se encuentra dentro de los límites de nuestra ventana, en caso que sea así retornamos verdadero sino falso

   1: private static bool IsRectUnderneathOurWindow(IntPtr hWnd, Rectangle? rect) { 
   2:     Rectangle ownRect;
   3:     bool retval = false;  
   4:  
   5:    if (rect.HasValue && Win32Support.GetWindowRect(hWnd, out ownRect)) 
   6:      retval = (rect.Value.Top < 0 || rect.Value.Top >= ownRect.Top) && rect.Value.Top <= ownRect.Bottom;
   7:  
   8:    return retval;
   9: }

De esta manera, hago que las ventanas “obedezcan” desde nuestra aplicación basada en WPF.

Saludos,

Angel

Dynamically accessing and handling menus with Microsoft Visual C++ 2008 SP1

Hi community,

I’m currently working on the demos for the upcoming webcast, hence my application has a main menu which at the same time has an option so I can demonstrate the features mentioned in the presentation. In Windows it’s “really straightforward” to manipulate menus and popups as a matter of fact, we can do it as follows: 

  • Obtain a handle to the main menu by calling the GetMenu function
  • Fill the required fields in an MENUITEMINFO structure
  • Reflect the changes by calling the SetMenuItemInfo function
   1: HMENU hMenu;
   2: LPTSTR newText;
   3: MENUITEMINFO menuInfo;
   4:  
   5: newText = _T("This text is dynamically set");
   6:  
   7: menuInfo.dwTypeData = newText;
   8: menuInfo.cbSize = sizeof(menuInfo);
   9: menuInfo.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
  10: menuInfo.fType = MFT_STRING;
  11: menuInfo.wID = ID_OPTIONS_TOBECHANGED;
  12: menuInfo.cch = _tcslen(newText);
  13:  
  14: hMenu = GetMenu(hWnd);
  15:  
  16: SetMenuItemInfo(hMenu, ID_OPTIONS_TOBECHANGED, FALSE, &menuInfo);
  17:  

This is depicted in the image below

image_thumb2

If we want to accomplish the same but using  MFC before installing Visual C++ 2008 Feature Pack then it would be like this

   1: MENUITEMINFO menuInfo;
   2: LPTSTR newText = _T("This text is dynamically set");
   3:  
   4: menuInfo.dwTypeData = newText;
   5: menuInfo.cbSize = sizeof(menuInfo);
   6: menuInfo.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
   7: menuInfo.fType = MFT_STRING;
   8: menuInfo.wID = ID_OPTIONS_TOBECHANGED;
   9: menuInfo.cch = _tcslen(newText);
  10:  
  11: CMenu* menu = theApp.GetMainWnd()->GetMenu();
  12: menu->SetMenuItemInfo(ID_OPTIONS_TOBECHANGED, &menuInfo);

Well if we want to do it after having installed the Feature Pack or Visual Studio .NET 2008, then it would be like:

  • Change scope/visibility of the m_wndMenuBar (CMFCMenuBar) member from protected to public, we can find it in the CMainFrame (CFrameWndEx) class.
   1: // Attributes
   2: public:
   3:     CMFCMenuBar  m_wndMenuBar; // Changed from protected to public
  • Write a routine similar to the one depicted below, so we can iterate and get to the element we’re interested in.
   1: void CWebcast_DemoApp::HandleDemoMenu(int subMenuId, LPWSTR message) {
   2:     CMainFrame* mainWnd;
   3:     CMFCToolBarButton* menuItem;
   4:     CMFCToolBarButton* selectedItem;
   5:     CMFCToolBarMenuButton* menuPopup;
   6:  
   7:     if ((mainWnd = (CMainFrame*) theApp.GetMainWnd()) != NULL) {
   8:         // Now I can get access to the CMFCMenuBar
   9:         menuItem = mainWnd->m_wndMenuBar.GetMenuItem(DEMO_MENU_INDEX); // My Menu items are under index 2
  10:         menuPopup = DYNAMIC_DOWNCAST(CMFCToolBarMenuButton, menuItem);
  11:         const CObList& subItems = menuPopup->GetCommands();
  12:  
  13:         for(POSITION nPos = subItems.GetHeadPosition(); nPos != NULL;) {
  14:             selectedItem = (CMFCToolBarButton*) subItems.GetNext(nPos);
  15:  
  16:             if (selectedItem->m_nID == subMenuId) {
  17:                 selectedItem->m_strText = message;
  18:                 ((CPane*) &mainWnd->m_wndMenuBar)->AdjustSizeImmediate();
  19:                 break;
  20:             }
  21:         }
  22:     }
  23: }

Why? well… because now the “main menu” is not a menu as such but a toolbar instead, thus trying to get a handle to the menu won’t work because there’s no menu, as shown in the following image

image_thumb6[4]

The Feature Pack for Visual C++ 2008 has many features, classes and controls including an implementation for TR1 which is pending on the approval of the new  C++0x standard.

Regards,

Angel

Accediendo y manipulando Menués de manera dinámica con Microsoft Visual C++ 2008 SP1

Hola comunidad,

Actualmente me encuentro trabajando en los demos para el próximo webcast, por ello mi aplicación tiene un menú principal que a su vez tiene una opción que me permite demostrar las características mencionadas en la presentación. En Windows es “relativamente” sencillo manipular los menués y emergentes pues lo podríamos conseguir de la siguiente manera:

  • Obtener el handle al menú principal a través de la función GetMenu
  • Llenar los campos requeridos de una estructura MENUITEMINFO
  • Reflejar los cambios llamando a la función SetMenuItemInfo
   1: HMENU hMenu;
   2: LPTSTR newText;
   3: MENUITEMINFO menuInfo;
   4:  
   5: newText = _T("This text is dynamically set");
   6:  
   7: menuInfo.dwTypeData = newText;
   8: menuInfo.cbSize = sizeof(menuInfo);
   9: menuInfo.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
  10: menuInfo.fType = MFT_STRING;
  11: menuInfo.wID = ID_OPTIONS_TOBECHANGED;
  12: menuInfo.cch = _tcslen(newText);
  13:  
  14: hMenu = GetMenu(hWnd);
  15:  
  16: SetMenuItemInfo(hMenu, ID_OPTIONS_TOBECHANGED, FALSE, &menuInfo);
  17:  

Esto lo podemos ver en la imagen mostrada a continuación

image

Sí quisieramos hacer lo mismo pero haciendo uso de MFC antes de Visual C++ 2008 Feature Pack sería algo como esto

   1: MENUITEMINFO menuInfo;
   2: LPTSTR newText = _T("This text is dynamically set");
   3:  
   4: menuInfo.dwTypeData = newText;
   5: menuInfo.cbSize = sizeof(menuInfo);
   6: menuInfo.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
   7: menuInfo.fType = MFT_STRING;
   8: menuInfo.wID = ID_OPTIONS_TOBECHANGED;
   9: menuInfo.cch = _tcslen(newText);
  10:  
  11: CMenu* menu = theApp.GetMainWnd()->GetMenu();
  12: menu->SetMenuItemInfo(ID_OPTIONS_TOBECHANGED, &menuInfo);

Pues bien si queremos hácerlo después de haber instalado el Feature Pack o el Service Pack 1 de Visual Studio .NET 2008, sería de la siguiente manera:

  • Cambiar la visibilidad del miembro m_wndMenuBar (CMFCMenuBar) de protegido a público, el cuál lo podemos encontrar en la clase CMainFrame (CFrameWndEx).
   1: // Attributes
   2: public:
   3:     CMFCMenuBar  m_wndMenuBar; // Changed from protected to public
  • Escribir una rutina similar a la mostrada abajo, para iterar y llegar al elemento que nos interesa.
   1: void CWebcast_DemoApp::HandleDemoMenu(int subMenuId, LPWSTR message) {
   2:     CMainFrame* mainWnd;
   3:     CMFCToolBarButton* menuItem;
   4:     CMFCToolBarButton* selectedItem;
   5:     CMFCToolBarMenuButton* menuPopup;
   6:  
   7:     if ((mainWnd = (CMainFrame*) theApp.GetMainWnd()) != NULL) {
   8:         // Now I can get access to the CMFCMenuBar
   9:         menuItem = mainWnd->m_wndMenuBar.GetMenuItem(DEMO_MENU_INDEX); // My Menu items are under index 2
  10:         menuPopup = DYNAMIC_DOWNCAST(CMFCToolBarMenuButton, menuItem);
  11:         const CObList& subItems = menuPopup->GetCommands();
  12:  
  13:         for(POSITION nPos = subItems.GetHeadPosition(); nPos != NULL;) {
  14:             selectedItem = (CMFCToolBarButton*) subItems.GetNext(nPos);
  15:  
  16:             if (selectedItem->m_nID == subMenuId) {
  17:                 selectedItem->m_strText = message;
  18:                 ((CPane*) &mainWnd->m_wndMenuBar)->AdjustSizeImmediate();
  19:                 break;
  20:             }
  21:         }
  22:     }
  23: }

¿Por qué? pues porque ahora el “menú principal” no es un menú como tal sino una barra de herramientas, por ende intentar obtener el handle del menú no serviría para nada pues no existe, tal como mostramos en la imagen a continuación

image

Así mismo el Feature Pack, trae consigo muchas características nuevas, clases y controles además de incluir una implementación de TR1 en espera del nuevo estandar C++0x

Saludos,

Angel

Upcoming Webcasts for MSDN LatAm (In Spanish)

 

Hi community,

I'd like to invite you to attend the upcoming webcasts that I'll be presenting during January and February

I look forward to seeing you there

Regards,

Angel

Próximos Webcasts para MSDN LatAm

 

Hola comunidad,

Me gustaría invitarlos a los próximos webcasts que estaré presentando durante los meses de Enero y Febrero

Espero verlos allí

Saludos,

Angel

Lambdas, XML and threads with Visual C++

Hi community,

The next post is about one of the many new features that we'll find in the upcoming release of Microsoft Visual C++ in order to support the new C++0x standard which is still under review.

Now C ++ supports Lambda functions, which are based on the Lambda calculus that we can define as "a formal system designed to investigate function definition, the notion of a function application and recursion". Although expressed from the programming point of view we can say that it is "an anonymous function that can contain expressions and statements that can be used to create delegates or expression trees".

This feature exists in .NET since version 3.0 of the Framework and is an important part for the execution of LINQ queries, hence we now have a new operator => (goes to) and we can see it in the example shown below

   1: string[] words = { "cherry", "apple", "blueberry" };
   2: int shortestWordLength = words.Min(w => w.Length);
   3: Console.WriteLine(shortestWordLength);
   4: // Output: 5

Lambda expressions can be as simple as previously shown or a bit more complex as shown below

   1: public MethodResponse<object, Type, string>? Execute(MethodRequest<string, object[]> request) {
   2:     MethodResponse<object, Type, string>? retval = null;
   3:  
   4:     var methodQry = NodeTypes.SelectMany(TypeNode => 
   5:         TypeNode.Methods, (TypeNode, Method) =>    new {TypeNode, Method})
   6:         .Where(match => match.Method.Name.ToLower().Equals(request.MethodName.ToLower()))
   7:         .Select(match => new {Name = match.Method.Name, MethodFound = match.Method,
   8:                                                     BaseObject = match.TypeNode.BaseObject});
   9:  
  10:     // Put code here to evaluate method signature/precedence
  11:  
  12:     try {
  13:         methodQry.ToList().ForEach(exeReq => 
  14:             retval = new MethodResponse<object, Type, string>() {
  15:                 MethodName = request.MethodName,
  16:                 CachedObject = exeReq.BaseObject.GetType(), 
  17:                 ReturnValue = exeReq.MethodFound.Invoke(exeReq.BaseObject, request.Arguments)
  18:         });
  19:     } catch (Exception ex) {
  20:         if (OnExceptionCaught != null) 
  21:             OnExceptionCaught(this, ex);
  22:     }
  23:     return retval;
  24: }

which belongs to a personal project that I'm currently working on to create dynamic code without relying on the DLR. The name I gave to this project is Simplicity, because it is about "creating dynamic code in a natural and simple way". In the snippet shown, we run a query on methods of various objects that have been combined at runtime, for instance

   1: MethodResponse<object, Type, string>? response = null;
   2: TypeNode testNode = TypeNode.Create(new SimpleClass());
   3: TypeContainer container =  TypeContainer.GetContainer(new List<TypeNode>() {testNode, TypeNode.Create(new BusinessObject())});
   4: MethodRequest<string, object[]> request = new MethodRequest<string,object[]>() { Arguments = null, MethodName = "Speak"};
   5: response = container.Execute(request);
   6:  
   7: // Which is equivalent to NewType C = A + B; but I haven't finished it as yet =)

Well, how can I run a Lambda in C++? The answer is simple as shown below

   1: // Two simple Lambdas
   2:  
   3: [](int x, int y) { return x + y; }
   4:  
   5: [](int x, int y) -> int { int z = x + y; return z + x; }

Now we have [] as the lambda-introducer, which tells the compiler that a lambda expression is beginning. The (int x, int y) is the Lambda parameter declaration, which tells the compiler that an unnamed function must be executed and it ends with {return x + y;} which is the statement that serves as body unnamed (anonymous) function.

The following code snippet makes use of a Lambda that retrieves information from a hash_map, to create three threads and at the same time we pass a reference to a structure called THREADINFO that contains information necessary for the execution of the threads.

   1: // Thread Creation Information
   2: typedef struct ThreadCreationInfo {
   3:     int id;
   4:     HANDLE threadHandle;
   5:     pair<string, int> selected;
   6:     DWORD threadId;
   7: } THREADINFO, *PTHREADINFO;
   8:  
   9:  
  10: hash_map<string, int> threadInfo;
  11:  
  12: DWORD WINAPI DummyThreadFunc(LPVOID lpParam);
  13:  
  14: int _tmain(int argc, _TCHAR* argv[]) {
  15:   int threadCount = 0;
  16:   HANDLE threadsHandle[3];
  17:  
  18:   // Sample thread information (Thread name and loop count)
  19:   threadInfo["Angel"] = 10;
  20:   threadInfo["Mery"]  = 20;
  21:   threadInfo["Flor"]  = 30;
  22:   
  23:   // We grab information about the threads to be created by using a Lambda
  24:   for_each(threadInfo.begin(), threadInfo.end(),  (pair<string, int> selected) {
  25:      threads.push_back((PTHREADINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREADINFO)));
  26:     
  27:       threads.at(threadCount)->id = threadCount + 1;
  28:       threads.at(threadCount)->selected = selected;
  29:  
  30:       threads.at(threadCount)->threadHandle = CreateThread(NULL, 0, DummyThreadFunc, 
  31:                                                           (LPVOID) threads.at(threadCount), 0,
  32:                                                            &threads.at(threadCount)->threadId);
  33:  
  34:       threadsHandle[threadCount] = threads.at(threadCount)->threadHandle;
  35:  
  36:       threadCount++;
  37:   });
  38:  
  39:   // Let's wait for our threads to finish
  40:   WaitForMultipleObjects(threads.size(), threadsHandle, TRUE, INFINITE);
  41:  
  42:   // Free memory allocations    
  43:   for(int nIndex = 0; nIndex < threads.size(); nIndex++) {
  44:        HeapFree(GetProcessHeap(), NULL, threads.at(nIndex));
  45:        CloseHandle(threadsHandle[nIndex]);
  46:   }
  47:   return 0;
  48: }
  49:  
  50:  
  51: DWORD WINAPI DummyThreadFunc(LPVOID lpParam) {
  52:     PTHREADINFO info = reinterpret_cast<THREADINFO*>(lpParam); 
  53:  
  54:     for(int nLoop = 0; nLoop < info->selected.second; nLoop++)
  55:         printf("Running Thread:%s - Loop %d\n", info->selected.first.c_str(),  nLoop + 1);
  56:  
  57:     return 0;
  58: }

 

The output of our application is shown below

image

Attached to this post is the project written in Visual C++ 2010, please feel free to download it and play with it. The project demonstrates how to perform 3 operations with Lambdas:

  • Fetch data from a hash_map
  • Manipulate and process information in an XML file
  • Create threads

I'm currently working on another article about PPL (Parallel Pattern Library) and some other new features in the language.

Regards,

Angel

Lambdas, XML e hilos con Visual C++

Hola comunidad,

El siguiente post es acerca de una de las muchas características nuevas que podemos encontrar en la próxima versión de Microsoft Visual C++ para así soportar el nuevo estándar C++0x que se encuentra en revisión.

Ahora C++ soporta funciones Lambda, la cual está basada en el cálculo Lambda que podemos definir como “un sistema formal diseñado para investigar la definición de función, la noción de aplicación de funciones y la recursión”. Aunque expresado desde el punto de vista de programación podemos decir que es “una función anónima que puede contener expresiones y declaraciones que pueden utilizarse para crear delegados o árboles de expresiones”.

Esta característica existe en .NET desde la versión 3.0 del Framework y es parte importante para le ejecución de consultas de LINQ, para ello se tiene el nuevo operador => (va hacia) y podemos verlo en el ejemplo mostrado a continuación

   1: string[] words = { "cherry", "apple", "blueberry" };
   2: int shortestWordLength = words.Min(w => w.Length);
   3: Console.WriteLine(shortestWordLength);
   4: // Output: 5

Las expresiones Lambda pueden ser tan sencillas como la mostrada anteriormente o más complejas como la mostrada abajo

   1: public MethodResponse<object, Type, string>? Execute(MethodRequest<string, object[]> request) {
   2:     MethodResponse<object, Type, string>? retval = null;
   3:  
   4:     var methodQry = NodeTypes.SelectMany(TypeNode => 
   5:         TypeNode.Methods, (TypeNode, Method) =>    new {TypeNode, Method})
   6:         .Where(match => match.Method.Name.ToLower().Equals(request.MethodName.ToLower()))
   7:         .Select(match => new {Name = match.Method.Name, MethodFound = match.Method,
   8:                                                     BaseObject = match.TypeNode.BaseObject});
   9:  
  10:     // Put code here to evaluate method signature/precedence
  11:  
  12:     try {
  13:         methodQry.ToList().ForEach(exeReq => 
  14:             retval = new MethodResponse<object, Type, string>() {
  15:                 MethodName = request.MethodName,
  16:                 CachedObject = exeReq.BaseObject.GetType(), 
  17:                 ReturnValue = exeReq.MethodFound.Invoke(exeReq.BaseObject, request.Arguments)
  18:         });
  19:     } catch (Exception ex) {
  20:         if (OnExceptionCaught != null) 
  21:             OnExceptionCaught(this, ex);
  22:     }
  23:     return retval;
  24: }

la cual pertenece a un proyecto personal en el que me encuentro trabajando para generar código dinámico sin depender del DLR. El nombre que le he dado a dicho proyecto es Simplicity, ya que se trata de “creación de código dinámico de una manera natural y sencilla”. En el fragmento de código mostrado, ejecuto una consulta sobre métodos de varios objetos que han sido combinado en tiempo de ejecución, por ejemplo

   1: MethodResponse<object, Type, string>? response = null;
   2: TypeNode testNode = TypeNode.Create(new SimpleClass());
   3: TypeContainer container =  TypeContainer.GetContainer(new List<TypeNode>() {testNode, TypeNode.Create(new BusinessObject())});
   4: MethodRequest<string, object[]> request = new MethodRequest<string,object[]>() { Arguments = null, MethodName = "Speak"};
   5: response = container.Execute(request);
   6:  
   7: // Which is equivalent to NewType C = A + B; but I haven't finished it as yet =)

Pues bien, ¿cómo puedo ejecutar un Lambda en C++? La respuesta es sencilla tal como lo mostramos a continuación 

   1: // Two simple Lambdas
   2:  
   3: [](int x, int y) { return x + y; }
   4:  
   5: [](int x, int y) -> int { int z = x + y; return z + x; }

Ahora tenemos [] como el Lambda-Introductor, el cual  le indica al compilador que una expresión Lambda está comenzando. El (int x, int y) es la declaración de parámetros del Lambda, la cual le indica al compilador que una función sin nombre debe ejecutarse para así finalizar con {return x + y;} que es la declaración compuesta que sirve de cuerpo para la función sin nombre (anónima).

El siguiente fragmento de código, hace uso de un Lambda que recupera información de un hash_map para crear tres hilos, al mismo tiempo al crear los hilos pasamos una referencia a una estructura llamada THREADINFO que contiene información necesaria para la ejecución de los hilos.

   1: // Thread Creation Information
   2: typedef struct ThreadCreationInfo {
   3:     int id;
   4:     HANDLE threadHandle;
   5:     pair<string, int> selected;
   6:     DWORD threadId;
   7: } THREADINFO, *PTHREADINFO;
   8:  
   9:  
  10: hash_map<string, int> threadInfo;
  11:  
  12: DWORD WINAPI DummyThreadFunc(LPVOID lpParam);
  13:  
  14: int _tmain(int argc, _TCHAR* argv[]) {
  15:   int threadCount = 0;
  16:   HANDLE threadsHandle[3];
  17:  
  18:   // Sample thread information (Thread name and loop count)
  19:   threadInfo["Angel"] = 10;
  20:   threadInfo["Mery"]  = 20;
  21:   threadInfo["Flor"]  = 30;
  22:   
  23:   // We grab information about the threads to be created by using a Lambda
  24:   for_each(threadInfo.begin(), threadInfo.end(),  (pair<string, int> selected) {
  25:      threads.push_back((PTHREADINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREADINFO)));
  26:     
  27:       threads.at(threadCount)->id = threadCount + 1;
  28:       threads.at(threadCount)->selected = selected;
  29:  
  30:       threads.at(threadCount)->threadHandle = CreateThread(NULL, 0, DummyThreadFunc, 
  31:                                                           (LPVOID) threads.at(threadCount), 0,
  32:                                                            &threads.at(threadCount)->threadId);
  33:  
  34:       threadsHandle[threadCount] = threads.at(threadCount)->threadHandle;
  35:  
  36:       threadCount++;
  37:   });
  38:  
  39:   // Let's wait for our threads to finish
  40:   WaitForMultipleObjects(threads.size(), threadsHandle, TRUE, INFINITE);
  41:  
  42:   // Free memory allocations    
  43:   for(int nIndex = 0; nIndex < threads.size(); nIndex++) {
  44:        HeapFree(GetProcessHeap(), NULL, threads.at(nIndex));
  45:        CloseHandle(threadsHandle[nIndex]);
  46:   }
  47:   return 0;
  48: }
  49:  
  50:  
  51: DWORD WINAPI DummyThreadFunc(LPVOID lpParam) {
  52:     PTHREADINFO info = reinterpret_cast<THREADINFO*>(lpParam); 
  53:  
  54:     for(int nLoop = 0; nLoop < info->selected.second; nLoop++)
  55:         printf("Running Thread:%s - Loop %d\n", info->selected.first.c_str(),  nLoop + 1);
  56:  
  57:     return 0;
  58: }

 

La salida de nuestra aplicación es mostrada abajo

image

Anexo pueden conseguir el proyecto escrito en Visual C++ 2010, por favor sientánse libres de bajarlo y jugar con él. El proyecto demuestra como realizar 3 operaciones con Lambdas:

  • Hacer fetch de un hash_map
  • Manipular y procesar información en un archivo XML
  • Creación de hilos

Actualmente me encuentro trabajando en otro artículo sobre PPL (Parallel Pattern Library) y otras características nuevas del lenguaje.

Espero que sea de utilidad

Saludos,

Angel

 

MVP Award Recipient once again / Una vez más elegido como MVP

Hi community,

I'm happy to announce that Microsoft has awarded me an MVP once again.  I would like to thank, God and all of you for your patience and support.  I look forward to deliver  heaps of articles and cool stuff for this new year 2010.

Thanks again,

Angel


Hola comunidad,

Me alegra anunciar que Microsoft me ha concedido nuevamente el reconocimiento de MVP.  Me gustaría darle las gracias a Dios y a todos ustedes por su paciencia y apoyo. Espero poder entregar montones de artículos y cosas interesantes este nuevo año 2010.

Gracias nuevamente,

Angel

WndProc where are you when I need you the most?

Hi community,

The following post is about something that recently happened to me in my current project, which is based on Microsoft CCF 2009, WPF, WCF and some automation. Among one of the requirements were, preventing any other window from being placed on top of our application's window so this one must be anchored to the top of the screen, thus preventing move it elsewhere.

Well, I thought about putting the code in the window procedure and process the WM_WINDOWPOSCHANGED message to force our window to remain "docked" so it can't be moved, but the only drawback was that our application's main window is of type Window, and it does not expose any WndProc without mentioning the fact that we could not change the current implementation at this point. The class HwndSource does expose the window procedure and the hWnd of the window as well, but what about our current implementation based on the Window class, now what could I do?

The solution was to implement a hook that applies only to our application and processes the  EVENT_OBJECT_LOCATIONCHANGE (0x800B) event. The code is similar the one below

   1: public delegate void HookCallback(IntPtr hWinEventHook, uint Event, IntPtr hWnd, int idObject,
   2:                                   int idChild, uint dwEventThread, uint dwmsEventTime);
   3:  
   4: private void SetUpHook() {
   5:            IntPtr positionHook = IntPtr.Zero; 
   6:            int processId = Process.GetCurrentProcess().Id;
   7:            GCHandle? positionHandler = GCHandle.Alloc(new WindowUtility.HookCallback(HookHandler));
   8:  
   9:            // Set up hook to determine when our application is covered by another window
  10:                if ((positionHook = WindowUtility.SetWinEventHook(WindowUtility.EVENT_OBJECT_LOCATIONCHANGE,
  11:                        WindowUtility.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, (WindowUtility.HookCallback)positionHandler.Value.Target,
  12:                        processId, WindowUtility.ZERO, WindowUtility.WINEVENT_OUTOFCONTEXT)) != IntPtr.Zero) {
  13:                        _currentHooks.Add(Guid.NewGuid(), new HookDetails() {
  14:                                        EventValue = WindowUtility.WINEVENT_OUTOFCONTEXT, HookHandle = positionHook,
  15:                                        ManagedHandler = positionHandler, MaxEvent = WindowUtility.EVENT_OBJECT_LOCATIONCHANGE,
  16:                                        MinEvent = WindowUtility.EVENT_OBJECT_LOCATIONCHANGE, ProcessId = processId,
  17:                                        ThreadId = WindowUtility.ZERO
  18:                                });
  19:                        }
  20:                }
  21:  
  22:  
  23: private void HookHandler(IntPtr hWinEventHook, uint Event, IntPtr hWnd, int idObject,
  24:                          int idChild, uint dwEventThread, uint dwmsEventTime) {
  25:   int titleBarLength = 0;
  26:   StringBuilder windowText = null;
  27:   IntPtr foregroundHwnd = IntPtr.Zero;
  28:  
  29:    // Location change | event 32779 (EVENT_OBJECT_LOCATIONCHANGE = 0x800B) occurs then 
  30:    //                   force docking the window to the top
  31:    
  32:    if (Event == WindowUtility.EVENT_OBJECT_LOCATIONCHANGE) {
  33:           if ((foregroundHwnd = WindowUtility.GetForegroundWindow()) != IntPtr.Zero) {
  34:                titleBarLength = WindowUtility.GetWindowTextLength(foregroundHwnd);
  35:                windowText = new StringBuilder(titleBarLength + 1);
  36:  
  37:           if (WindowUtility.GetWindowText(foregroundHwnd, windowText, windowText.Capacity) > WindowUtility.ZERO &&
  38:               windowText.ToString().ToLower().Equals(WindowUtility.OFFICE_CLASS)) {
  39:                    WindowUtility.CloseWindow(foregroundHwnd);
  40:           }
  41:  
  42:          // Let's set a new style to the window (Hide Icon in Task Switcher)  
  43:          if (!_newStyleSet) {
  44:                 WindowStyle = WindowStyle.ToolWindow; // Same as WS_EX_TOOLWINDOW
  45:                 _newStyleSet = true;
  46:          }
  47:  
  48:         // let's re-dock our application bar
  49:         applicationBar = new ApplicationBar(this);
  50:         applicationBar.RegisterBar(true);
  51:          } 
  52:       }
  53:    }
  54:  
  55:  
  56:  protected override void OnClosing(System.ComponentModel.CancelEventArgs e) {
  57:    if (!appLoaded)
  58:          e.Cancel = true;
  59:    else {
  60:      // Cleaning up hook related stuff
  61:      _currentHooks.ToList().ForEach(hook => {
  62:                    WindowUtility.UnhookWinEvent(hook.Value.HookHandle);
  63:                    hook.Value.ManagedHandler.Value.Free();
  64:          });
  65:       }
  66:   }
  67:  

The only application that could cause problems was the office bar, so if it is placed on top of our window, then we proceed to minimize it. It was also requested that the application icon was not shown in the Task switcher window, for this we could change the window extended styles through SetWindowLong function in conjunction with WS_EX_TOOLWINDOW style, yet with WPF is as simple as 

   1: WindowStyle = WindowStyle.ToolWindow; 

As mentioned earlier, the Window class does not expose the hWnd of the window, but we can get it as follows

   1: private void Form_Loaded(object sender, RoutedEventArgs e) {
   2:    IntPtr hWnd =  Process.GetCurrentProcess().MainWindowHandle;
   3: }

 Although the hook solution works seamlessly, I was still curious about doing it through the window procedure, my idea was the following: 

  • Have a method that would serve as the window procedure
  • Get the address of that Method
  • Change the window procedure and use that method

In order to test this, I created a solution based on WPF and changed the project's properties to allow unsafe code (unsafe). In C/C + + we can get the memory address of a function via the address-of operator (reference)

   1: typedef float (*FUNCPTR) (float,float);
   2:  
   3: float Add(float a, float b);
   4:  
   5: int main() {
   6:    FUNCPTR ptr = &Add;
   7:    float result = ptr(5, 5); 
   8:    return 0;
   9: }
  10:  
  11: float Add(float a, float b) {
  12:   return a + b;
  13: }

But unfortunately this is not possible in .NET, because we'll incur in an CS0211 error and if you want to get the address in memory of a given type we will incur in an CS0208 error, but in both cases this is not "completely true" as you can see in the following image

image

From the "Watch 1" window, I can get the pointer and address of the method, but why then the following line in my source code will not compile? The mysterious world of VS. NET 

image 

It is also possible to obtain the address of a managed type as follows 

   1: GCHandle pinnedCallBack = GCHandle.Alloc(new WndProcCallback[] {WndProc});
   2:  
   3: GCHandle pinnedArray = GCHandle.Alloc(pinnedCallBack , GCHandleType.Pinned);
   4:  
   5: // Get address of pinned array
   6: IntPtr pinAddress = pinnedArray.AddrOfPinnedObject(); 
   7:  
   8: // Get address of callback (delegate)
   9: IntPtr callbackAddress = Marshal.UnsafeAddrOfPinnedArrayElement((WndProcCallback[])(((GCHandle)(pinnedArray.Target)).Target), 0);

Returning to the main idea, my intention was to get the address of my new method and through the SetWindowLong function set it as the new window procedure. 

   1: Win32Support.SetWindowLong(hWnd, Win32Support.GWL_WNDPROC, wndProcAddress);

When my application runs, I show the address in memory of the current window procedure, the array containing my delegate and the delegate itself as depicted in the image below

image

 Note the following:

  • The Information about the window procedure is the same, I mean, what Microsoft Spy++ and my application returns

  • Even when my application inherits from the Window class, Spy reflects something different which is a not documented class called HwndWrapper

As mentioned before, The HwndWrapper class is not documented so it gets my attention that's why I launched the CLR Profiler to search for its window procedure and determine who allocated it

image

Window Procedure (MS.Win32.NativeMethods.WndProc)

image 

The Window class depends on HwndWrapper and HwndSource, but why not exposing the WndProc then?

Once I found it, I propose to change the existing window procedure in order to avoid not using any hook as mentioned at the beginning of the post but ... It did not work :-| so I ran WinDbg and realized that the addresses returned by the CLR are "invalid" because after running SetWindowLong (which runs without any error according to its return value and after checking the GetLastError function). Below is shown the application's WndProc

image

When I tried to set the new window procedure, I got an exception of type C0000005 - Access Violation, which translates into a heap that has been corrupted, as shown in the image below

image

Before jumping to any conclusion, I decide to verify that the address returned by the CLR is the same as the method I tried to set as the window procedure, so I execute this command WPFAPP bm! * in WinDbg to get the methods within my application's process and their memory addresses

image

Oops ... The address I've previously got is not there. Interestingly, there is a feature in the Debugger Engine that allows me to enumerate the methods of a given process and that's the GetSymbolEntriesByName function.

At the end, I finally had to leave the hook implementation, and if I want to have control over the window procedure then derive my Window from HwndSource so avoiding "add" any extra functionality to the Window class.

WPF allows us to create rich user interfaces but at the same time things that were simple to do with Win32, it just simply becomes cumbersome and difficult to implement which is an irony because in spite of the new names and frameworks and stuff, everything running underneath is still Win32.

Regards,

Angel

¿WndProc en donde estás cuando te necesito?

Hola comunidad,

El siguiente post es acerca de algo que recientemente me sucedió en mi proyecto actual, el cual está basado en Microsoft CCF 2009, WPF, WCF y algo de automatización. Entre uno de los requerimientos estaban, el no permitir que ninguna otra ventana se pudiera colocar sobre la ventana de nuestra aplicación además que ésta debe anclarse al tope superior de la pantalla, evitando así que pueda moverse a otra parte.

Pues bien, me dije puedo colocar el código en el procedimiento de ventana y procesar el mensaje WM_WINDOWPOSCHANGED  para así obligar a nuestra ventana que no pueda moverse, pero el único inconveniente era que la ventana principal de nuestra aplicación es de tipo Window y no expone ningún WndProc sin mencionar que no podíamos cambiar la implementación a estas alturas por HwndSource que si expone el procedimiento de ventana e inclusive el hWnd de la ventana, entonces, ¿ahora qué podía hacer?

La solución fue implementar un gancho (hook) que aplica solo a nuestra aplicación y procesamos el evento EVENT_OBJECT_LOCATIONCHANGE (0x800B). El código es similar al mostrado a continuación

   1: public delegate void HookCallback(IntPtr hWinEventHook, uint Event, IntPtr hWnd, int idObject,
   2:                                   int idChild, uint dwEventThread, uint dwmsEventTime);
   3:  
   4: private void SetUpHook() {
   5:            IntPtr positionHook = IntPtr.Zero; 
   6:            int processId = Process.GetCurrentProcess().Id;
   7:            GCHandle? positionHandler = GCHandle.Alloc(new WindowUtility.HookCallback(HookHandler));
   8:  
   9:            // Set up hook to determine when our application is covered by another window
  10:                if ((positionHook = WindowUtility.SetWinEventHook(WindowUtility.EVENT_OBJECT_LOCATIONCHANGE,
  11:                        WindowUtility.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, (WindowUtility.HookCallback)positionHandler.Value.Target,
  12:                        processId, WindowUtility.ZERO, WindowUtility.WINEVENT_OUTOFCONTEXT)) != IntPtr.Zero) {
  13:                        _currentHooks.Add(Guid.NewGuid(), new HookDetails() {
  14:                                        EventValue = WindowUtility.WINEVENT_OUTOFCONTEXT, HookHandle = positionHook,
  15:                                        ManagedHandler = positionHandler, MaxEvent = WindowUtility.EVENT_OBJECT_LOCATIONCHANGE,
  16:                                        MinEvent = WindowUtility.EVENT_OBJECT_LOCATIONCHANGE, ProcessId = processId,
  17:                                        ThreadId = WindowUtility.ZERO
  18:                                });
  19:                        }
  20:                }
  21:  
  22:  
  23: private void HookHandler(IntPtr hWinEventHook, uint Event, IntPtr hWnd, int idObject,
  24:                          int idChild, uint dwEventThread, uint dwmsEventTime) {
  25:   int titleBarLength = 0;
  26:   StringBuilder windowText = null;
  27:   IntPtr foregroundHwnd = IntPtr.Zero;
  28:  
  29:    // Location change | event 32779 (EVENT_OBJECT_LOCATIONCHANGE = 0x800B) occurs then 
  30:    //                   force docking the window to the top
  31:    
  32:    if (Event == WindowUtility.EVENT_OBJECT_LOCATIONCHANGE) {
  33:           if ((foregroundHwnd = WindowUtility.GetForegroundWindow()) != IntPtr.Zero) {
  34:                titleBarLength = WindowUtility.GetWindowTextLength(foregroundHwnd);
  35:                windowText = new StringBuilder(titleBarLength + 1);
  36:  
  37:           if (WindowUtility.GetWindowText(foregroundHwnd, windowText, windowText.Capacity) > WindowUtility.ZERO &&
  38:               windowText.ToString().ToLower().Equals(WindowUtility.OFFICE_CLASS)) {
  39:                    WindowUtility.CloseWindow(foregroundHwnd);
  40:           }
  41:  
  42:          // Let's set a new style to the window (Hide Icon in Task Switcher)  
  43:          if (!_newStyleSet) {
  44:                 WindowStyle = WindowStyle.ToolWindow; // Same as WS_EX_TOOLWINDOW
  45:                 _newStyleSet = true;
  46:          }
  47:  
  48:         // let's re-dock our application bar
  49:         applicationBar = new ApplicationBar(this);
  50:         applicationBar.RegisterBar(true);
  51:          } 
  52:       }
  53:    }
  54:  
  55:  
  56:  protected override void OnClosing(System.ComponentModel.CancelEventArgs e) {
  57:    if (!appLoaded)
  58:          e.Cancel = true;
  59:    else {
  60:      // Cleaning up hook related stuff
  61:      _currentHooks.ToList().ForEach(hook => {
  62:                    WindowUtility.UnhookWinEvent(hook.Value.HookHandle);
  63:                    hook.Value.ManagedHandler.Value.Free();
  64:          });
  65:       }
  66:   }
  67:  

La única aplicación que podía causar problemas era la barra de office, por lo que si esta es colocada sobre nuestra ventana, entonces procedemos a minimizarla. También era requerido que el icono de la aplicación no fuese mostrado en la ventana las tareas, para esto podíamos cambiar los estilos extendidos de la ventana a través de la función SetWindowLong en conjunto con el estilo WS_EX_TOOLWINDOW, sin embargo con WPF es tan sencillo como

   1: WindowStyle = WindowStyle.ToolWindow; 

Como mencione al principio, la clase Window no expone el hWnd de la ventana, pero si deseamos obtener este lo podemos hacer de la siguiente manera

   1: private void Form_Loaded(object sender, RoutedEventArgs e) {
   2:    IntPtr hWnd =  Process.GetCurrentProcess().MainWindowHandle;
   3: }

Aunque la solución del gancho funciona sin inconvenientes, estaba aún con la curiosidad de hácerlo a través del procedimiento de ventana, mi idea era la siguiente:

  • Tener un método que hiciera las veces de procedimiento de ventana
  • Obtener la dirección de dicho método
  • Cambiar el procedimiento de ventana y utilizar mi método

Para ello creé una solución basada en WPF, cambié las propiedades del proyecto para permitir código inseguro (unsafe). En C/C++ puedo obtener la dirección de memoria de una función a través del operador de dirección (referencia)

   1: typedef float (*FUNCPTR) (float,float);
   2:  
   3: float Add(float a, float b);
   4:  
   5: int main() {
   6:    FUNCPTR ptr = &Add;
   7:    float result = ptr(5, 5); 
   8:    return 0;
   9: }
  10:  
  11: float Add(float a, float b) {
  12:   return a + b;
  13: }

pero lamentándolo mucho en .NET eso no es posible, porque incurriríamos en un error CS0211 y en caso de querer obtener la dirección en memoria de un tipo administrado obtendríamos un error CS0208, pero en ambos casos no es “completamente cierto” y se puede ver en la siguiente imagen

image

Desde la ventana de “Inspecciones” puedo obtener el puntero y la dirección del método, pero ¿por qué entonces la siguiente línea en mi código fuente no me deja compilar?  El misterioso mundo de VS .NET

image 

Así mismo, es posible obtener la dirección de un tipo gestionado de la siguiente manera

   1: GCHandle pinnedCallBack = GCHandle.Alloc(new WndProcCallback[] {WndProc});
   2:  
   3: GCHandle pinnedArray = GCHandle.Alloc(pinnedCallBack , GCHandleType.Pinned);
   4:  
   5: // Get address of pinned array
   6: IntPtr pinAddress = pinnedArray.AddrOfPinnedObject(); 
   7:  
   8: // Get address of callback (delegate)
   9: IntPtr callbackAddress = Marshal.UnsafeAddrOfPinnedArrayElement((WndProcCallback[])(((GCHandle)(pinnedArray.Target)).Target), 0);

Retomando la idea principal, mi intención era obtener la dirección del nuevo procedimiento de ventana y a través de la función SetWindowLong apuntar a dicho procedimiento.

   1: Win32Support.SetWindowLong(hWnd, Win32Support.GWL_WNDPROC, wndProcAddress);

Entonces ejecuto mi aplicación, muestro las direcciones en memoria del procedimiento de ventana actual, el arreglo que contiene mi delegado (callback) y el callback en sí tal como es mostrada en la imagen a continuación

image

Nótese lo siguiente:

  • La información sobre el procedimiento de ventana es la misma, es decir, lo que nos muestra Microsoft Spy++ y la aplicación que escribí
  • Mi aplicación deriva de la clase Window, pero Spy muestra una clase llamada HwndWrapper (que no está documentada)

La clase HwndWrapper no está documentada por lo que me llama la atención así que decido, ejecutar mi aplicación con CLR Profiler para ver si consigo el procedimiento de ventana así como quién asigna a esté

image

Procedimiento de Ventana (MS.Win32.NativeMethods.WndProc)

image 

La clase Window depende de HwndWrapper y HwndSource, pero ¿por qué no exponer el WndProc?

Una vez descubierto esto, me propongo a cambiar el procedimiento de ventana para así no utilizar el gancho mencionado al principio del post… Pero no funciona :-|  por lo que ejecuto WinDbg, y me doy cuenta que las direcciones que me regresa el CLR son “inválidas”  ya que después de ejecutar SetWindowLong (que por cierto se ejecuta sin errores, por el valor que retorna y lo que me devuelve GetLastError). A continuación muestro el WndProc de la aplicación

image

Al establecer el nuevo procedimiento de ventana, recibo una excepción de tipo C0000005 – Violación de Acceso, que se traduce en un montículo que se ha corrompido como es mostrado en la siguiente imagen

image

Antes de llegar a una conclusión, decido verificar que la dirección regresada por el CLR coincide con la del método que quiero establecer como procedimiento de ventana, para ello ejecuto el comando bm WPFAPP!* desde WinDbg y puedo ver los métodos y su dirección de memoria

image

Oops… La dirección que tengo no aparece ahí. Lo interesante es que hay una función en el Debugger Engine que me permite enumerar los métodos de un proceso dado. La función GetSymbolEntriesByName.

Al final tuve que dejar la implementación con el gancho que había hecho previamente, si quiero tener control sobre el procedimiento de ventana entonces derivo de HwndSource y me evito de estar “agregando” funcionalidad a la clase Window.

WPF nos permita hacer interfaces de usuario muy ricas y todo lo demás, pero al mismo tiempo las cosas que eran sencillas de hacer con Win32 se hacen engorrosas ó simplemente díficiles de implementar y lo irónico es que aún por debajo de todos los nombres nuevos y marcos de trabajo, lo que se ejecuta es Win32.

Saludos,

Angel

 

Webcast recording and demos for "A lap around ASP.NET 4.0 and Visual Studio 2010" / Grabación del webcast y demos de "Una vuelta por ASP.NET 4.0 y Visual Studio 2010"

Hi Community,

Please feel free to download the recording and demos from yesterday's Webcast -  "A lap around ASP.NET 4.0  and Visual Studio 2010" . It's in Spanish though Smile 

Regards,

Angel

 


Hola Comunidad,

Por favor siéntanse libres de descargar la grabación y demos del Webcast de ayer "Una vuelta por ASP.NET 4.0 y Visual Studio 2010"

Saludos,

Angel

 

Assembler Language in .NET and some other ideas

Hi Community,

This post is about something not very recent in .NET and it’s been available for a while, but the first time I read about it I couldn’t blog it because I didn’t have a blog back then Stick out tongue and since I’m currently reading this book once again "The art of assembly language" (I think that I’m reading it for the third time… It just contains too much information) so I thought it’s worthy to mention it. Even when .NET is  managed code, in the end the CPU understands  machine code which can be represented through  assembler language. This happens the same with the rest of other languages (managed and non-managed). Back in  2001, someone had the brilliant idea of doing  ASP.NET with  assembler language.  The article can be found  here and below a sample page is depicted

The few things I learned about assembler language was back in 1995, thanks to my mate Virginia when she was about to earn her degree in Bsc. Systems Engineering and I was a freshman in Uni. I used to spend a lot of time with Microsoft C/C++ 7.0 (MFC 1.0 was bundled in it) and I thought it was cool to place inline code inside  __asm, at the same time I was learning VB 4.0 and in my spare time I played  Heretic and MK II... I remember my mom calling me to go and have lunch Stick out tongue *sigh* What a wonderful time!!!... There’s one thing I’ve been trying to keep from that time and throughout the years and it’s been like a golden rule: "whatever you do, do it with passion and… there’s no a better way to learn something new than by playing with it”  and that’s probably why I never get bored of PCs, technology and related stuff.

Changing of topics, some days ago one of our customers had a new requirement “I’d like to detect when an active session is about to expire and store the existing cart in CRM", this is something very easy and straightforward to do in ASP.NET, where I can put some code in the Global.asax and intercept the Session_End event but what I’m talking about is a SharePoint based solution with form based authentication enabled and as we all MUST know by now, SharePoint supports this authentication scheme since  version 2007, because it has always relied on  NTLM and Kerberos.  Anyways I had a couple of approaches which I mention below: 

  • Every single SharePoint application is an instance of SPHttpApplication which in turn inherits from HttpApplication, so I said  "Nah... this is a piece of cake", I just need to modify the Global.asax and write some inline code to handle Session_End  but it doesn’t work Sad so I thought about creating a new project and explicit inherit from SPHttpApplication but it doesn’t work either…  So I gave it a try to another alternative…

  • Write an HttpModule which contains a singleton and at the same time it keeps a data structure updated and in sync by a  critical section at the moment of a session timing out, code is shown below
  • using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.ApplicationRuntime;
    using System.IO;
    using Microsoft.SharePoint.Security;
    using System.Runtime;
    using System.Runtime.InteropServices;
    using System.Web.SessionState;
     
     
    namespace Demo {
        public class MyCustomApplication : IHttpModule {
            #region IHttpModule Members
            private SyncedInfo _synced = null;
            private GCHandle? _allocatedMem = null;
     
            private GCHandle? AllocatedMemory {
                get {
                    return _allocatedMem;
                }
                set {
                    _allocatedMem = value;
                }
            }
     
            private SyncedInfo Singleton {
                get {
                    return _synced;
                }
                set {
                    _synced = value;
                }
            }
     
            public void Dispose() {
                if (AllocatedMemory != null) {
                    AllocatedMemory.Value.Free();
                }
            }
     
            public void Init(HttpApplication context) {
                if (Singleton == null) {
                    Singleton = new SyncedInfo(context.Modules["Session"]);
                    AllocatedMemory = GCHandle.Alloc(Singleton);
                }
            }
            #endregion
        }
     
        [Serializable]
        public class SyncedInfo {
            protected SessionStateModule _sessionModule;
            protected HttpContext _currentContext = HttpContext.Current;
     
            public SyncedInfo(IHttpModule context) {
                _sessionModule = (SessionStateModule)context;
                _currentContext.Application["UserData"] = new Dictionary<string, string>();
                _sessionModule.Start += Session_Start;
                _sessionModule.End += Session_End;
            }
     
            public bool Push(string customer, string selectedData) {
                bool retval = false;
                object userData = _currentContext.Application["UserData"];
     
                try {
                    lock (userData) {
                        if (!((Dictionary<string, string>)userData).ContainsKey(customer)) {
                            ((Dictionary<string, string>)userData).Add(customer, selectedData);
                        } else {
                            ((Dictionary<string, string>)userData)[customer] = selectedData;
                        }
                        retval = true;
                    }
                } catch { } // Swallow the exception
                return retval;
            }
     
            public KeyValuePair<string, string>? Pop(string customer) {
                KeyValuePair<string, string>? retval = null;
                object userData = _currentContext.Application["UserData"];
     
                try {
                    lock (userData) {
                        if (((Dictionary<string, string>)userData).ContainsKey(customer)) {
                            retval = new KeyValuePair<string, string>(customer, ((Dictionary<string, string>)userData)[customer]);
                            ((Dictionary<string, string>)userData).Remove(customer);
                        }
                    }
                } catch { retval = null; } // Swallow the exception
                return retval;
            }
     
            private void Session_End(object sender, EventArgs e) {
                // Serialize data here (Pop)
     
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate() {
                    WriteActivity(false);
                }));
     
            }
     
            private void Session_Start(object sender, EventArgs e) {
                // Push should be call from the App (UI)
     
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate() {
                    WriteActivity(true);
                }));
            }
     
            private void WriteActivity(bool state) {
                string fileName = @"c:\log.txt";
     
                try {
                    using (StreamWriter logWriter = (!File.Exists(fileName) ? File.CreateText(fileName) : File.AppendText(fileName))) {
                        logWriter.WriteLine(string.Format("Session {0} at {1}", new object[] { (state ? "Started" : "Ended"), DateTime.Now }));
                        logWriter.Flush();
                        logWriter.Close();
                    }
                } catch { } // Swallow exception
            }
        }
    }

This approach should work, it does as a matter of fact, when Session_Start is triggered but it doesn’t fire when the session expires and in my humble opinion this is quite annoying because  SharePoint is taking away from me something that ASP.NET provides, this is valid when security relies on Windows and “a valid ticket” is always available, but what about form based authentication?

In conclusion, I can do ASP.NET with assembler language (according to the previously mentioned article) but I can’t intercept any event related to a  session timing out in SharePoint Sad  How cool is that!!!!

Regards,

Angel

Lenguaje Ensamblador en .NET y algunas otras ideas

Hola Comunidad,

El siguiente post es sobre algo no tan nuevo en .NET que leí hace un tiempo atrás, pero para ese entonces no tenía blog Stick out tongue y como actualmente estoy leyendo de nuevo este libro "El arte del lenguaje ensamblador" (creo que por tercera vez, porque contiene demasiada información) pensé que sería interesante mencionarlo. Aunque .NET es código gestionado al final de cuentas lo que entiende el procesador es lenguaje de máquina que puede representarse simbólicamente a traves del lenguaje Ensamblador, lo mismo pasa con los demás lenguajes (gestionados y no gestionados). En el año 2001 ha alguien se le ocurrió la idea de hacer ASP.NET usando lenguaje ensamblador.  El artículo completo lo pueden ver acá y abajo pueden ver un ejemplo de como luce el código de la página

Lo poco que aprendí sobre lenguaje Ensamblador fue por allá en el año 1995, gracias a mi amiga Virginia que ya estaba por graduarse de Ingeniero de Sistemas y yo estaba recién entrando en universidad. Me la pasaba horas haciendo cosas con Microsoft C/C++ 7.0 (que traía consigo MFC 1.0) por lo que me parecía chévere poner código inline dentro del __asm al mismo tiempo estaba aprendiendo VB 4.0 y en los ratos libres jugando Heretic y MK II... Mientras mi mamá me peleaba para que fuera a comer Stick out tongue que buenos tiempos aquellos... de verdad que si... Una cosa que he tratado mantener con los años es eso de "hacer las cosas con pasión y aprender jugando" por eso creo que no me aburro de la computadora.

Cambiando de tema, en días pasados un cliente hizo un requerimiento, "quiero detectar cuando la sesión haya expirado y guardar el carrito de compras en CRM", claro... en ASP.NET puedo escribir algo en el Global.asax e interceptar el evento Session_End y es sencillo, pero esto es una solución basada en SharePoint que hace uso de autenticación basada en formas y como es bien sabido SharePoint viene a soportar este tipo de autenticación  a partir de la versión 2007, porque siempre ha utilizado NTLM y Kerberos para ello. En fin, se me ocurrieron un par de ideas las cuales menciono a continuación:

  • Toda aplicación basada en SharePoint es una instancia de SPHttpApplication que a la vez deriva de HttpApplication, al estar consciente de esto me dije "Nah... sencillo" con modificar el Global.asax y escribir código para el evento Session_End lo consigo... No funciona Sad entonces pensé en crear un proyecto y explicitamente derivar de SPHttpApplication  y tampoco funciona... Por lo que pensé en otra alternativa...

  • Crear un HttpModule que contiene un singleton y este a su vez mantiene una estructura que mediante una región crítica permite su actualización al “expirar alguna sesión”, el código es mostrado a continuación
  • using System;
    using System.ComponentModel;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.ApplicationRuntime;
    using System.IO;
    using Microsoft.SharePoint.Security;
    using System.Runtime;
    using System.Runtime.InteropServices;
    using System.Web.SessionState;
     
     
    namespace Demo {
        public class MyCustomApplication : IHttpModule {
            #region IHttpModule Members
            private SyncedInfo _synced = null;
            private GCHandle? _allocatedMem = null;
     
            private GCHandle? AllocatedMemory {
                get {
                    return _allocatedMem;
                }
                set {
                    _allocatedMem = value;
                }
            }
     
            private SyncedInfo Singleton {
                get {
                    return _synced;
                }
                set {
                    _synced = value;
                }
            }
     
            public void Dispose() {
                if (AllocatedMemory != null) {
                    AllocatedMemory.Value.Free();
                }
            }
     
            public void Init(HttpApplication context) {
                if (Singleton == null) {
                    Singleton = new SyncedInfo(context.Modules["Session"]);
                    AllocatedMemory = GCHandle.Alloc(Singleton);
                }
            }
            #endregion
        }
     
        [Serializable]
        public class SyncedInfo {
            protected SessionStateModule _sessionModule;
            protected HttpContext _currentContext = HttpContext.Current;
     
            public SyncedInfo(IHttpModule context) {
                _sessionModule = (SessionStateModule)context;
                _currentContext.Application["UserData"] = new Dictionary<string, string>();
                _sessionModule.Start += Session_Start;
                _sessionModule.End += Session_End;
            }
     
            public bool Push(string customer, string selectedData) {
                bool retval = false;
                object userData = _currentContext.Application["UserData"];
     
                try {
                    lock (userData) {
                        if (!((Dictionary<string, string>)userData).ContainsKey(customer)) {
                            ((Dictionary<string, string>)userData).Add(customer, selectedData);
                        } else {
                            ((Dictionary<string, string>)userData)[customer] = selectedData;
                        }
                        retval = true;
                    }
                } catch { } // Swallow the exception
                return retval;
            }
     
            public KeyValuePair<string, string>? Pop(string customer) {
                KeyValuePair<string, string>? retval = null;
                object userData = _currentContext.Application["UserData"];
     
                try {
                    lock (userData) {
                        if (((Dictionary<string, string>)userData).ContainsKey(customer)) {
                            retval = new KeyValuePair<string, string>(customer, ((Dictionary<string, string>)userData)[customer]);
                            ((Dictionary<string, string>)userData).Remove(customer);
                        }
                    }
                } catch { retval = null; } // Swallow the exception
                return retval;
            }
     
            private void Session_End(object sender, EventArgs e) {
                // Serialize data here (Pop)
     
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate() {
                    WriteActivity(false);
                }));
     
            }
     
            private void Session_Start(object sender, EventArgs e) {
                // Push should be call from the App (UI)
     
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate() {
                    WriteActivity(true);
                }));
            }
     
            private void WriteActivity(bool state) {
                string fileName = @"c:\log.txt";
     
                try {
                    using (StreamWriter logWriter = (!File.Exists(fileName) ? File.CreateText(fileName) : File.AppendText(fileName))) {
                        logWriter.WriteLine(string.Format("Session {0} at {1}", new object[] { (state ? "Started" : "Ended"), DateTime.Now }));
                        logWriter.Flush();
                        logWriter.Close();
                    }
                } catch { } // Swallow exception
            }
        }
    }

Esta solución debería funcionar, de hecho lo hace cuando Session_Start es disparado pero no cuando la sesión expira lo cual me molesta pues SharePoint me está quitando algo ofrece ASP.NET,  quizás esto no aplica cuando la seguridad está basada en Windows pero puede darse el caso con autenticación basada en formas sí.

Entonces es posible hacer ASP.NET con lenguaje Ensamblador (según el artículo antes mencionado) pero no puedo interceptar el cierre de una sesión en SharePoint Sad  Que les parece!!!!

Saludos,

Angel

Upcoming MSDN Webcast: A lap around Microsoft ASP.NET 4.0 and Microsoft Visual Studio 2010 / Próximo Webcast en MSDN: Una vuelta por Microsoft ASP.NET 4.0 y Microsoft Visual Studio 2010

Hi Community,

I'll be presenting the following MSDN Webcast (Saturday, 28th November 2009 @ 7:00 AM - Australia Time)

I look forward to seeing you there Wink

Regards,

Angel


Hola Comunidad,

Estaré presentando el siguiente MSDN Webcast (Viernes, 27 de Noviembre de 2009 (05:00 p.m. - Hora Colombia) - (05:30 p.m. - Hora Venezuela))

Espero verlos ese día Wink

Saludos,

Angel

Visual Studio Documentary / Documental de Visual Studio

Hi Community,

Grabbed from Channel 9

Regards,

Angel


Hola Comunidad,

Tomado de  Channel 9

Saludos,

Angel


 

Part I

Click here to play this video

Part II

Click here to play this video

Angel on dnrTV / Angel en dnrTV (dotNet Rocks TV)

Hi Community,

I just finished my presentation on dnrTV, thanks to Carl Franklin and Scott Hanselman. This session was about "Using Native Code in .NET" and we covered

  • Hooks      
  • Memory Mapped Files

However, I'm planning to organize some other sessions to cover a bit more about this topic (e.g.: Virtual Memory, Device I/O, Error Reporting and Application Recovery and more). I'll keep you updated on this.

Please, feel free to download the source code attached to this post

Regards,

Angel


Hola Comunidad,

Acabo de terminar mi presentación para  dnrTV, gracias a  Carl Franklin y Scott Hanselman. El tópico de esta sesión fue  "Using Native Code in .NET" y cubrimos

  • Hooks      
  • Memory Mapped Files

Sin embargo, estoy planeando organizar otras sesiones para hablar un poco más de este tema  (por ejemplo, Virtual Memory, Device I/O, Error Reporting and Application Recovery and more). Los mantendré informados al respecto.

Por favor, siéntanse libres de descargar el código adjunto a este post

Saludos,

Angel

WWSAPI (Windows Web Services API) + Interop + WPF… How cool is that!!!

A couple of nights ago I was reading about some of the new features in Windows 7 SDK and I can honestly say “They’re a lot”, as a matter of fact, I mentioned some of them in one of my previous Tech-Ed session this year. Despite of all these new features, there’s one that got my attention from the beginning and it was WWSAPI, because there wasn’t any support for Web Service from native code, except for a couple of existing toolkits including gSOAP that can be implemented  on Windows, Linux and Mac OSX.  WWSAPI was first introduced at  PDC 2008 and it will be formally released along Windows 7, although previous versions of the operating system starting from XP SP2 can get it via Windows Update when becomes available. I first tested it when Windows 7 was still RC but I didn’t post about it because I was expecting for Windows 7 to be released or about to be released.

Having said that, last weekend I created a solution to demo  WWSAPI in conjunction with .NET. The solution structure is depicted below

Solution 

  • NativeTester: Console application (C++) which calls our Dynamic Link Library (DLL)
  • RSSFeedService: Web Service (C#) which retrieves RSS feeds, parse them and returns a well-formed XML
  •  RSSViewer: WPF application (C#) which consumes the Web Service plus invokes our Dynamic Link Library (DLL)
  • Tester: WinForm application (C#) which consumes the Web Service plus invokes our Dynamic Link Library (DLL)
  • WWSAPIDemo: Dynamic Link Library (C++) which implements  WWSAPI and it’s invoked from .NET via Interop

Along with the code you can find MSDN.xml which contains the RSS feeds from MSDN Australia, even when the code references  http://localhost/MSDN.xml, you can change the Url and retrieve any given RSS, in my case I deployed the previously mentioned file to my local IIS.

Many of you might be wondering about, how can I generate a proxy based on the Web Service via C++?  and the answer is quite simple, the new Windows 7 SDK provides us with an utility that does this for us, WSUTIL.exe. After executing it, we have as a result two files (an .H and a .CPP). The strings are treated as  WCHAR* by default which in turn is Unicode and every single string in .NET are Unicode as well, I’ll comment a bit more about this later.  

wsutil

Having the Web Service published already on IIS, we better start working on the Dynamic Link Library which implements WWSAPI. Below we can see its header file

#include "stdafx.h"
 
#define EXPORT extern "C" __declspec(dllexport)
 
#define MAX_SIZE  128000 //128Kb
#define TRIM_SIZE 512
 
EXPORT WCHAR* GetFeeds(WCHAR* szUrl, int cbResults);
 
EXPORT void GetItem(WCHAR* szUrl, WCHAR* szItemName);
And this is the method responsible for connecting against the Web Service and retrieves the RSS feeds 
// Get feeds from a given Url through WWSAPI
EXPORT WCHAR* GetFeeds(WCHAR* szUrl, int cbResults) {
    WCHAR* temp = NULL;
    WS_HEAP* heap = NULL;
    WCHAR retval[MAX_SIZE]; // 128Kb (It should be enough to avoid WS_E_QUOTA_EXCEEDED error)
    WS_ERROR* error = NULL;
    ULONG propertiesCount = 0;
    WS_SERVICE_PROXY* proxy = NULL;
    WS_CHANNEL_PROPERTY channelProps[2]; 
    WS_STRING serviceUrl = WS_STRING_VALUE(L"http://localhost/DemoSvc/RSSFeedService.asmx");
    WS_ENDPOINT_ADDRESS endpoint = { serviceUrl}; 
    WS_ENVELOPE_VERSION soapVersion = WS_ENVELOPE_VERSION_SOAP_1_1; // Our Webservice is WsiProfiles.BasicProfile1_1 compliant
    WS_ADDRESSING_VERSION addressingVersion = WS_ADDRESSING_VERSION_TRANSPORT;
 
    // Set channel's properties
    channelProps[propertiesCount].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION;
    channelProps[propertiesCount].value = &soapVersion;
    channelProps[propertiesCount].valueSize = sizeof(soapVersion);
    propertiesCount++;
 
    // Set addressing's properties
    channelProps[propertiesCount].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
    channelProps[propertiesCount].value = &addressingVersion;
    channelProps[propertiesCount].valueSize = sizeof(addressingVersion);
    propertiesCount++;
 
    // Can we create an WsError and WsHeap objects?
    if (SUCCEEDED(WsCreateError(NULL, NULL, &error)) && SUCCEEDED(WsCreateHeap(MAX_SIZE, TRIM_SIZE, NULL, NULL, &heap, error))) {
        // Can we create a proxy based on the service?
        if  (SUCCEEDED(WsCreateServiceProxy(WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL, NULL, 
            channelProps, propertiesCount, &proxy, error))) {
                // Can we open the proxy object?
                if  (SUCCEEDED(WsOpenServiceProxy(proxy, &endpoint, NULL, error))) {
                    // If we're able to invoke the service then copy the results to another variable because if
                    // we don't we lose the response after freeing the heap
                    if (SUCCEEDED(RSSFeedServiceSoap12_RetrieveFeeds(proxy, szUrl, cbResults, &temp, heap, NULL, NULL, NULL, error))) 
                        wcscpy_s(retval, temp);
                }
        }
    }
 
    // Deallocate and free resources
    if (error != NULL)
        WsFreeError(error);