Tag: Windows

Activación de XDebug en XAMPP para depuración con Netbeans

Uno de los problemas de desarrollar en PHP, es que se interpreta en el lado del servidor y lo que devuelve es la información procesada de la lógica de PHP. Esto nos lleva a la problemática de que es poco útil inundar de trazas  de PHP que escriban en el HTML resultante de vuelta, los estados concretos de las variables procesadas durante la ejecución de la lógica programada.

Esto nos obliga a poner algún tipo de servicio de depuración que nos interrumpa la ejecución del intérprete de PHP y nos mande la información del estado de ejecución de cada punto de ruptura o de parada (breakpoint) que queramos añadir.

Uno de los frameworks de depuración más extendidos es XDebug, que además de ofrecer capacidades de depuración (debugging) también  ofrece características de análisis de rendimiento (profiling). Este framework se integra muy bien con todos las soluciones de servidor PHP,  como es mi caso concreto de XAMPP y mi entorno de desarrollo integrado Netbeans.

Para integrarlo lo primero que tenemos que hacer es localizar el fichero de configuración "php.ini" que contiene la información de configuración del intérprete de PHP que se encuentra en el directorio "xampp/php". Abrimos el fichero con un editor de texto cualquiera y buscamos la existencia de "[XDebug]" y descomentamos las siguiente líneas quitando el punto y coma de delante de cada línea para conseguir las siguiente configuración:

[XDebug]
zend_extension = php_xdebug.dll
xdebug.remote_enable = 1
xdebug.remote_handler = dbgp
xdebug.remote_host = localhost
xdebug.remote_port = 9000

En el caso de no estar todas las líneas añade las que falten y si no encuentras nada que te referencie a XDebug, añádelo. En las últimas versiones de XAMPP sigue estando incluido XDebug, pero no hay rastro de él en el fichero de configuración. No obstante comprueba que existe en el directorio "xampp/php/ext" la libería dinámica "php_xdebug.dll".

Si alguno le echa un ojo al resto del fichero "php.ini", se dará cuenta que existen un apartado de extensiones dinámicas (Dynamic Extensions), donde se referencian otras librerías dinámicas del directorio "xampp/php/ext", cargadas con  "extension=", en vez de "zend_extension=". Esto es debido a que se carga usando el motor Zend. Si no lo respetáis, no os funcionará a pesar de que PHP os lo reconozca.

Para que la configuración tenga efecto guardamos el fichero y reniniciamos Apache si estaba ya funcionando. Si todo está correcto, entrando en la siguientes direcciones:

... deberíamos poder encontrar XDebug y poder ver toda la configuración.

php_xdebug

Ahora vayamos a Netbeans, quien por defecto ya viene con XDebug preconfigurado. En "Herramientas-->Opciones-->PHP-->Debugging", comprobamos que "Debugger Port" sea el 9000 (el que configuramos en el fichero php.ini) y desmarcamos, si lo estuviera, la opción "Stop at First Line" para que no entre en modo depuración en la primera línea del proyecto, sino cuando encuentra un breakpoint.

netbeans-php-debugging-config

Ahora si marcamos en cualquier parte del código con un breakpoint y lanzamos el proyecto en modo depuración netbeans-debug, la ejecución parará en el breakpoint marcado, pudiendo continuar la ejecución paso a paso si lo necesitásemos, supervisando la lógica y valores tomados durante la ejecución.

xdebug_break_point

Como habéis podido ver, el depurado XDebug configurado en XAMPP  e integrado con Netbeans, resulta de los más útil, dotándonos de una herramienta de depuración perfecta para trabajar en nuestros proyectos de PHP.

Corregir colores ANSI en la consola de Windows 10 tras la actualización Windows Anniversary

La actualización de Windows Aniversario por fin llegó a mi equipo y aunque en general parece ser más robusto y seguro, era imposible no encontrarse con nuevos fallos introducidos a causa de esta enorme actualización. No obstante por la curva de fallos real del software, en cada actualización se introducen nuevos fallos no existentes anteriormente o mal solventados.

curva_fallos_software

Obviamente en esta actualización no iba a ser menos, dado el calado tan ambicioso de la actualización. El fallo que he detectado se corresponde a la interpretación de los colores ANSI de la consola de Windows. Concretamente el problema reside en que no se procesan los códigos ANSI de escape, que antes estaba activado por defecto gracias al flag de la consola ENABLE_VIRTUAL_TERMINAL_PROCESSING.

Esto supone un problema para todas las librerías y códigos de Python que usaban los colores ANSI para cambiar de color la letra y fondo de la consola de manera trasnaprente en todos los sistemas.

Ejemplo de la problemática que se empieza a notar en algunas librerías:

https://github.com/pyreadline/pyreadline/issues/46

Ante este problema se me ocurrieron 2 formas de arreglarlo.

 


Solución 1


cmder-main

La primera pasa por añadir un frontend a la maltrecha consola de comandos de Windows y pensé en Cmder por ser un proyecto que además es portable. De esta forma con un lanzador .BAT/.CMD es posible lanzar sobre Cmder lo que queramos y dejar a un lado la problemática de los colores.

La solución consiste en descargar Cmder en su versión portable y añadir el siguiente .BAT que nos permita lanzar Cmder y ejecutar comandos en su inicio:

@echo off
set CMDER_ROOT=%~dp0
start %CMDER_ROOT%\vendor\conemu-maximus5\ConEmu.exe /icon "%CMDER_ROOT%\cmder.exe" /title Cmder /loadcfgfile "%CMDER_ROOT%\config\ConEmu.xml" /cmd cmd /k "%CMDER_ROOT%\vendor\init.bat cd %CD% && cd .. && %~1"

Este archivo que puedes llamar "cmder.bat" debe estar al mismo nivel de directorio que el ejecutable "Cmder.exe". En este caso además se asume que Cmder está en una carpeta en la raíz del proyecto y la consola se posiciona en el nivel inmediatamente superior al que se encuentra "cmder.bat" y "Cmder.exe".

La forma de usar "cmder.bat" asumiendo que está en la carpeta "cmder" sería la siguiente:

start /B cmder.bat "python main.py" ^&^& timeout 5 ^&^& exit

En este caso se lanza un programa en Python, cuyo archivo de ejecución principal es "main.py". Con el parámetro "/B" se lanza la aplicación sin crear una nueva ventana. Adicionalmente se le indica con "^&^& timeout 5" que la consola espere 5 segundos antes de procesar la salida de la consola gracias a "^&^& exit". El resultado sería algo similar a esto:

cmder-launch

 


Solución 2


La segunda solución pasa por añadir un parche en la librería de Python que usa colores ANSI o en su defecto en el "main" de la aplicación. Las líneas de Python que debes añadir para corregir el problema específico de la interpretación de los colores ANSI de la consola de Windows tras la actualización de Windows Aniversario, es la siguiente:

import os
import platform

if os.name == 'nt' and platform.release() == '10' and platform.version() >= '10.0.14393':
    # Fix ANSI color in Windows 10 version 10.0.14393 (Windows Anniversary Update)
    import ctypes
    kernel32 = ctypes.windll.kernel32
    kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

Gracias a la librería ctype que proporciona tipos de datos compatibles con C, se pueden hacer llamadas a DLLs o librerías compartidas. Esencialmente lo que se hace es habilitar la flag ENABLE_VIRTUAL_TERMINAL_PROCESSING.

De esta forma los colores de la consola pasan de verse así:

ansi_win_before

A verse así:

ansi_win_after

¡Mucho mejor!, ¿no?

Dejo a continuación la referencia al Fix completo publicado en Gist de GitHub:

ANSIColorFix.py

 

Ambas soluciones resuelven la problemática del color ANSI en la consola de Windows tras la actualización Aniversario del sistema. No obstante la primera solución puede ser menos invasiva al no requerir de cambios en el código, pero la segunda es una solución de enfoque más nativo, ofreciendo una solución transparente a los desarrolladores que hacen uso de las librerías afectadas por este problema.

Añadir fecha y hora al nombre de un archivo en la consola de comandos de Windows

Habitualmente suelo trabajar con la consola de comandos de Windows y con scripts .BAT. Una de las tareas mas habituales es generar outputs en forma de fichero y una buena práctica suele ser añadir al nombre del fichero la fecha y la hora.

Una forma sencilla de mostrar la fecha en la consola de comandos de Windows es poner el siguiente comando:

echo %date%

Y la forma de mostrar la hora es:

echo %time%

Sabiendo esto podemos pasar al siguiente paso para poder añadirlo al nombre de un fichero. Como has podido observar al obtener la fecha, la obtenemos con el signo "/" intercalado entre el día, mes y año. Del mismo modo la hora aparece separada por el signo ":" , para separar las horas, los minutos y los segundos. Además la parte de los segundo viene con "," para marcar los decimales para las décimas de segundo. Los tres símbolos citados, no están permitidos a la hora de incluirlos en un nombre de un fichero en Windows, por lo que procedemos a quitarlos de la siguiente manera:

echo MyFile_%date:~-4,4%-%date:~-7,2%-%date:~-10,2%_%time:~0,2%-%time:~3,2%-%time:~6,2%.txt

Si analizamos el código, lo que se hace es una concatenación de valores que se imprimen como nombre. La fecha se le da la vuelta porque a la hora de ordenar por nombre, a nombres iguales se puede ordenar por años con una simple ordenación por orden alfabético. En el caso de la hora no es necesario darle la vuelta.

Para cada variable date o time se cogen los caracteres que nos interesan de la siguiente forma:

%variable:~startIndex,numChars%

startIndex determina la posición desde la que se empiezan a coger los caracteres dentro de la variable. El índice empieza en 0 y también puede ser negativo el índice, indicando la posición de inicio desde el final de la variable.

numChars determina el número de caracteres que se van a coger desde el startIndex fijado.

cmd-win-append-date-time

De esta forma y extrapolándolo  a otros comando, es posible añadir fecha y hora, sólo fecha o solo hora al nombre de un fichero de un output de un comando.

OpenCV – Mouse Event Handler (parte 2)

Continuando la entrada "OpenCV - Mouse Event Handler (parte 1)", que ya publiqué hace un tiempo, os traigo la segunda parte que da cierre al manejo de eventos del ratón con OpenCV. Si en la primera parte me centraba en el manejo puro de los eventos del ratón, en esta entrada hablaré sobre la combinación de eventos de ratón con eventos de teclado.

opencv_mouse-event_display

La combinación de eventos de teclado con los eventos de ratón, son muy útiles por ejemplo cuando queremos asegurarnos que las acciones con el ratón no son fortuitas, y por ello se asegura la acción del ratón con la pulsación de alguna tecla. Un ejemplo común puede ser el pulsar la tecla "CRTL" o "SHIFT" cuando se hace click con el ratón. Otro ejemplo puede ser la de diferenciar dos acciones distintas desde un click de ratón, gracias a la pulsación combinada con distintas teclas.

El siguiente ejemplo toma como partida el ya expuesto en la entrada de la parte 1 y modifica la función "mouseEventHandler" de la siguiente forma:

void mouseEventHandler(int event, int x, int y, int flags, void* param)
{
     if ( flags == (EVENT_FLAG_CTRLKEY + EVENT_FLAG_LBUTTON) )
     {
          cout << "Left mouse button is clicked while pressing CTRL key - position (" << x << ", " << y << ")" << endl;
     }
     else if ( flags == (EVENT_FLAG_SHIFTKEY + EVENT_FLAG_RBUTTON) )
     {
          cout << "Right mouse button is clicked while pressing SHIFT key - position (" << x << ", " << y << ")" << endl;
     }
     else if ( event == EVENT_MOUSEMOVE && flags == EVENT_FLAG_ALTKEY)
     {
          cout << "Mouse is moved over the window while pressing ALT key - position (" << x << ", " << y << ")" << endl;
     }
}

Cada vez que se produzca alguno de los siguientes eventos:

  • EVENT_FLAG_LBUTTON
  • EVENT_FLAG_RBUTTON
  • EVENT_FLAG_MBUTTON
  • EVENT_FLAG_CTRLKEY
  • EVENT_FLAG_SHIFTKEY
  • EVENT_FLAG_ALTKEY

Se invocará a la función callback “mouseEventHandler“. En este caso, en la sucesión de los distintos “if” que permite identificar el tipo de evento, se incluye además  una condición de teclado. En el caso de los clicks izquierdo y derecho del ratón, se puede combinar las flags de pulsación del ratón con los del teclado, aplicando una suma aritmética de los valores. En el caso del movimiento del ratón, esto no es aplicable, ya que el movimiento del teclado es de tipo "EVENT" y el de la tecla es de tipo "EVENT_FLAG". A causa de ello se realiza una operación lógica entre los resultados obtenidos en las comparaciones de cada  tipo.

opencv_mouse-event_key-event_display

A continuación dejo el código completo de la arquitectura básica para el manejo de eventos con pulsaciones de teclado:

OpenCV_Mouse_Event_Handler_2.cpp