lunes, diciembre 03, 2012

VFP: Obtener el nombre del PC en ambiente Terminal Server

Siempre he dicho que en lo simple esta la belleza del Universo y hoy vi esto confirmado una vez mas.

Es un escenario cada vez mas común el de ejecutar sistemas administrativos mediante sesiones de Terminal Server.  En este escenario, la función SYS(0) devuelve el nombre del equipo donde se esta ejecutando la sesión de TS y NO el equipo "cliente", que seria el que en definitiva nos interesaría. Este problema lo había resuelto hace tiempo mediante llamadas al API de TS que me permitían obtener el nombre del equipo cliente.

Pero hoy, el gran Maestro Luis Maria Guayan me ha sorprendido con una forma mucho mas simple y elegante de resolver el problema:


IF UPPER(LEFT(GETENV("SESSIONNAME"),3)) == "RDP" 
  lcPC = GETENV("CLIENTNAME")
ELSE
  lcPC = GETENV("COMPUTERNAME")
ENDIF



Increíblemente simple!!



viernes, noviembre 02, 2012

OSX: Kernel Panics por CIJScannerRegister

La verdad, los usuarios de OSX no estamos acostumbrados al equivalente Apple de la pantalla azul de la muerte, tan familiar en el mundo Windows.  De hecho, ni siquiera recuerdo cuando fue la última vez que una de mis Mac tuvo un Kernel Panic (que asi se llaman en OSX) y, por norma, mi laptop pasa MESES sin siquiera necesitar de un reboot.

Asi que imaginen mi frustración cuando, de repente, mi laptop empezó a generar Kernel Panics varias veces por semana.  Una de esas veces, afecto mi disco de fuentes y se imaginarán el desastre.

Anoche dejé la laptop encendida realizando un backup en línea, solo para conseguirme esta mañana con que el equipo se había apagado luego de un Kernel Panic.  Asi que dije "basta!" y recurrí a San Google para intentar ver si alguien mas estaba sufriendo del mismo problema.

Resulto que si. Y el sospechoso común era un proceso llamado CIJScannerRegister.  Resulta que este proceso, relaciondo con impresoras Cannon, ya estaba instalado en mi equipo desde que hice el fresh install de Snow Leopard pero, por alguna razón, luego de actualizar a Lion empezó a causar problemas con el kernel del sistema operaivo.

Dado que yo no uso impresoras Cannon y mucho menos scanners de esa o cualquier otra marca, la solución para mi fue tan simple como renombrar el driver para evitar que se cargue, tal como indican aqui.

Apenas hice el cambio hoy, asi que habra que esperar a ver si, efectivamente, este CIJScannerRegister era el causante de mis problemas o si, por el contrario, tendre que seguir buscando otros sospechosos.

Actualización Nov 5

Van ya 3 dias sin ningún tipo de problemas ni Kernel Panics. Incluso, la portatil se ha calentado menos y la bateria dura un poco mas. Creo que este CIJScannerRegister me estaba causando mas problemas de los que pense en un inicio.  Tambien el hecho de haber eliminado el Flash Player quizas este teniendo algo que ver aqui.


Actualización Dic 1

A casi un mes del tema no he tenido mas Kernel Panics ni ningún otro problema.  De hecho, eliminé el panel Fan Control y le di un reset al SMC de mi MBP para que los ventiladores cayeran de nuevo en control del firmware original de Apple y todo volvió a ser como siempre debió haber sido: una laptop estable y extremadamente silenciosa.



jueves, agosto 23, 2012

Plugin de Java en OSX Lion

Hoy intenté entrar a una página que usa applets de Java y me conseguí con la sorpresa de un recuadro blanco con la leyenda "disabled plugin". Inicialmente pense que era un problema con Google Chrome, pero pronto me di cuenta que tenia que ser un problema a nivel de sistema, pues lo mismo sucedia con Safari. 

Una rápida busca en Google me indicó que, por alguna razón, el proceso de instalación de OSX Lion desactiva este plugin en todos los navegadores.

La solución?
  1. Abra una ventana de Terminal
  2. Escriba o pegue este comando:
    /Applications/Utilities/Java\ Preferences.app/Contents/MacOS/Java\ Preferences
  3. Marque la opción "Enable applet plug-in and Web Start applications"
  4. Reinicie su navegador de internet

Fuente:


lunes, julio 30, 2012

Web 2.0: Mi primer sitio web con JQuery y Bootstrap

La historia es que mi esposa tiene una tia que es monja de las Carmelitas Descalzas del convento San Rafael en Santiago, y la hermana encargada de las cuestiones tecnológicas me preguntó que si podia hacer una página web para el convento.  Nada del otro mundo; solo una página de portada, galeria, ubicación y contacto.

La ocasión me pareció propicia para intentar dar mis primeros pasos en el mundo de JQuery y Bootstrap y así ver que tan útil son dichas herramientas a la hora de crear interfaces de usuario en Web al estilo HTML5.

La experiencia fue traumática, ya que me recordo lo realmente poco que se sobre HTML y Javascript, pero con un poco de ayuda de Google pude sacar adelante el proyecto.  El diseño básico de la página lo hice con iWeb y algo de PHP, y luego cree una especie de página de administración donde una persona autorizada puede entrar y cambiar ciertos contenidos de la pagina de forma dinámica.

Para este módulo de administración utilizé exclusivamente Bootstrap como base para la diagramación y la interfaz gráfica y, debo decir, la experiencia fue todo un placer.  Bootstrap pone las cosas de manera realmente sencilla y el resultado final es simplemente espectacular.

Por su parte, JQuery hace muy sencillo la manipulación de elementos dentro del HTML asi como la ejecución de código en forma asincrónica.  De hecho, todo el modulo de administración funciona en un solo HTML, usando DIVs para cada sección que, en otros casos, habrían sido paginas individuales.

Aca les dejo algunas imagenes de este modulo de administración en bootstrap + JQuery.  El sitio web en si pueden verlo en http://www.carmelitassanrafael.cl.



Pantalla de Login. La validación se hace mediante Javascript

La barra de tabs es generada y manejada automáticamente por Bootstrap; yo solo tuve que crear los DIVs para cada sección

Bootstrap incluso maneja elementos de interfaz visual para la validación de formularios, y una libreria de soporte permite crear reglas en forma declarativa, a fin de facilitar el proceso de validación de formularios.


lunes, marzo 12, 2012

Consejos de un viejo programador

Esto lo encontré en un post del grupo de programadores de Visual Foxpro y no pude mas que estar de acuerdo con todo lo planteado por este sabio programador, mayormente por propia experiencia. El texto original en inglés lo pueden ver aqui.

He estado programando durante un tiempo muy largo. Tanto que es increíblemente aburrido para mí. En el momento en que escribí este libro, sabía cerca de 20 lenguajes de programación y podía aprender otros nuevos en alrededor de un día a una semana dependiendo de lo raro que eran. Finalmente, esto sólo se volvió aburrido y no podía mantener mi interés más. Esto no significa que creo que la programación es aburrida, o que usted va a pensar que es aburrido, sólo que me parece que ya no es tan interesante en este punto de mi viaje. 
Lo que descubrí después de este viaje de aprendizaje es que no son los lenguajes lo que importa, sino lo que haces con ellos. En realidad, yo siempre lo supe, pero me distraía con los lenguajes y lo olvidaba periódicamente. Ahora ya no se me olvida, y usted tampoco debería hacerlo. 
Qué lenguaje de programación aprendes y usas, no importa. No se deje atrapar por la religion que acompaña a los lenguajes de programación lo que sólo te cegará a su verdadero propósito de ser tu herramienta para hacer cosas interesantes. 
La programación como una actividad intelectual es la única forma de arte que te permite crear arte interactivo. Puede crear proyectos que otras personas pueden jugar, y usted puede hablar con ellos indirectamente. Ninguna otra forma de arte es asi de interactiva. Las películas fluyen al público de forma directa. Las Pinturas no se mueven. El Código va en ambos sentidos. 
La programación como una profesión es sólo moderadamente interesante. Puede ser un buen trabajo, pero tu podrías hacer la misma cantidad de dinero y ser más feliz poniendo un restaurante de comida rápida. Harías mucho mejor usando la programación como tu arma secreta en otra profesión. 
Las personas que pueden programar en el mundo de las empresas de tecnología son una entre mil y no se les respeta. Las personas que pueden programar en biología, medicina, el gobierno, sociología, física, historia y matemáticas son respetadas y pueden hacer cosas increíbles para avanzar en esas disciplinas. 
Por supuesto, todos estos consejos no tienen sentido. Si te ha gustado aprender a escribir software con este libro, usted debe tratar de usarlo para mejorar su vida de cualquier manera posible. Salga y explore esta nueva, extraña y maravillosa búsqueda intelectual que casi nadie en los últimos 50 años ha sido capaz de explorar. Puede ser que también lo disfrute mientras pueda.

Por último, diré que el aprender a crear software te cambia y te hace diferente. No mejor ni peor, solo diferente. Usted puede encontrar que la gente te trata con aspereza porque puedes crear un software, tal vez usando palabras como "nerd". Tal vez usted encontrará que usted porque usted puede desbaratar su lógica ellos odian discutir con usted. Usted puede incluso encontrar que el simple conocimiento de cómo funciona una computadora lo vuelve molesto y extraño para ellos.
Para todo ello sólo tengo un consejo: Todos ellos pueden irse al infierno !
El mundo necesita más personas raras que sepan cómo funcionan las cosas y que les encante averiguarlo
Cuando te traten así, sólo recuerda que este este es tu viaje, no el de ellos. Ser diferente no es un delito, y las personas que te dicen que lo es, solo tienen celos de que hayas adquirido una habilidad que ellos nunca, ni en el mas loco de sus sueños podrían adquirir.
Tu sabes programar. Ellos no. Eso es muy muy cool !

lunes, febrero 20, 2012

VFP: Manejador de eventos en tiempo de ejecucion

Hay muchas situaciones en las que terminamos necesitando que una instancia de una clase propia pueda ejecutar codigo arbitrario en uno o mas de sus eventos, como por ejemplo en clases que se instancian en tiempo de ejecucion en lugar de hacerlo en tiempo de diseño.

Habiéndome topado con estos casos muchas veces, hace unos dias terminé escribiendo una clase que me permite añadir un manejador de eventos dinámicos a cualquier clase de forma sencilla. El primer paso es crear un manejador de eventos en la clase. Para esto le añadimos una propiedad que contendrá la instancia del manejador de eventos, la cual es creada en el constructor de la clase (evento Init):

THIS.Events = CREATEOBJECT("VEEventHandler")

Lo siguiente es definir los eventos que estarán disponibles y la forma de manejar los mismos. La clase permite dos formas de manejar los eventos declarados cuando estos son invocados.

Usando una clase controller
Consiste en asociar un metodo de una clase controladora al evento declarado de modo que, cuando se invoque el evento indicado este procesa a invocar el metodo indicado en la clase controladora. La principal ventaja de este metodo es que la asociacion entre el evento y su controlador puede ser modificada sin que esto afecte el código existente. La forma de definir estos eventos seria así:

THIS.Events.Add("sayHello","Hello",oController)

Lo que estamos diciendo aqui es:
define un evento llamado "sayHello" el cual, cuando sea invocado, llamará al método "Hello" del objeto "oController".

Usando codigo dinámico
Consiste en asociar un codigo VFP válido al evento, de modo que cuando este sea invocado se ejecute el método asociado al evento. La ventaja principal de este método es que no necesitamos de un segundo objeto que maneje los eventos y ademas el código asociado al evento puede cambiar dinámicamente sin afectar el resto del codigo de la aplicación. La forma de definir estos eventos es:

THIS.Events.Add("sayHi",cSayHiCode)


Como invocar los eventos
Una vez definidos los eventos que estarán disponibles en la clase, lo único que queda es invocarlos cuando sea necesario. La clase ofrece dos formas de invocar estos eventos:

Invocación directa
Consiste en invocar el evento directamente por su nombre:

miObjeto.Events.sayHello.Raise("World!")

El método Raise acepta hasta 10 parámetros, los cuales son pasados al método del controller asociado al evento, o a la sentencia PARAMETERS o LPARAMETERS del código asociado al mismo.

Invocación indirecta
Esta forma permite invocar el evento indirectamente, mediante un string que identifica el nombre del evento:

miObjeto.Events.Raise("sayHello","Mundo!")

El primer parámetro del metodo Raise recibe el nombre del evento a invocar y a partir de ahi los parámetros son pasados directamente al evento.

La clase con su código fuente y ejemplos puede ser descargada desde aqui.


NOTA IMPORTANTE
Mucha de la funcionalidad proporcionada por esta clase, sobre todo usando la figura de controllers, puede ser implementada de forma nativa en VFP a partir de la introducción del comando BINDEVENTS.  La ventaja que da esta clase es que la misma es compatible con cualquier versión de VFP (solo usando eventos manejados por controller; los eventos con código dinámico requieren de VFP 7 o superior).

sábado, febrero 04, 2012

VFP: Un parser para JSON


Para los que, como yo, nunca hayan escuchado hablar de JSON, se trata de una tecnologia ampliamente usada en la web para el intercambio de datos entre sistemas desconectados. Básicamente es lenguaje muy simple que permite definir objetos y su contenido. Los parsers JSON hacen dos cosas:

a) Toman una referencia a un objeto (normalmente JavaScript) y genera una representación JSON en forma de string
b) Toman un string JSON y devuelve el objeto original

A pesar que en el sitio JSON.org se pueden encontrar dos parsers JSON para VFP, decidi hacer mi propio parser usando solo código VFP y, de paso, incluyendo un par de mejoras al estilo fox.

La mejor de estas adiciones es lo que llame "schema". Un schema es basicamente una forma de definir uns estructura de datos reutilizable, al estilo de la construcción STRUCT en C# (pero sin la posibilidad de incluir metodos).

Por ejemplo, para definir el schema "User":

JSON.declareSchema("User","{loginName:string, fullName: string, profileId: numeric, active: boolean}")

Luego, cuando queremos trabajar con un objeto que represente un usuario, solo hacemos:

oUser = JSONObject("schema:User")
oUser.loginName = 'vespina'
oUser.fullName = 'Victor Espina'
oUser.profileId = 25
oUser.active = .T.


Supongamos ahora que queremos almacenar los datos del usuario que modifico un registro. Con JSON podriamos hacerlo asi:

SELECT clientes
REPLACE rowLastUpd WITH DATETIME(),;
        rowUpdBy   WITH oUser.ToJSON()

Luego, cuando queramos mostrar quien modifico el registro, hacemos:

oUser = JSONObject(clientes.rowUpdBy)
MESSAGEBOX("Este registro fue modificado por " + oUser.fullName)


Otro uso muy comun de JSON es crear objetos sobre la marcha de forma sencilla:

oPoint = JSONObject("{x:10, y:20}")
?oPoint.x --> 10


Como ven, las posibilidades son muchas. En la documentacion de la libreria hay multitud de ejemplos de todo lo que se puede hacer con ella.


Descargar qdfoxJSON (version 1.2 del 9 Feb de 2012).