a nil value

Blog sobre programación e informática en general (Por Guillermo Zafra)

Browsing Posts in miniguías

Puedes necesitarla por varias razones; si quieres programar para Mac, para el iPhone, o si simplemente quieres echarle un vistazo al sistema. Ahora bien, no recomiendo usarlo como sistema para el “día a día” ya que es bastante inestable y tiene muchos problemas, pero para salir del paso sirve.

NOTA: Antes de comenzar hay que matizar que los pasos que aquí explicaré pueden no ser los mismos para todos los sistemas. VMWare virtualiza un equipo en funcion del hardware donde se instale, por lo que tendréis que usar un poco de lógica e intuición si no os funciona.

Lo primero que necesitamos es un VMWare versión 6.5 o posterior y una imagen de Leopard. Recomiendo encarecidamente una que se llama iatkos v7 (podeis buscar por Google que seguro que la encontrais). Esta imagen tiene la virtud de poseer una versión de Leopard 10.5.7, lo cual es muy bueno para instalar SDK relativamente modernos. (Podremos instalar hasta cualquier SDK 3.1.x del iPhone)

PASO 1 “Creando la máquina virtual”

1.- Creamos una nueva máquina virtual desde el VMWare.
2.- Seleccionamos Custom.
3.- Elegimos el sistema operativo, en nuestro caso tenemos dos opciones; o Windows NT u Otros > FreeBSD64. Recomiendo comenzar con Windows NT y probar FreeBSD64 cómo segunda opción.
4.- Cuando nos pida el disco de instalación seleccionamos la imágen .iso de iatkos que ya deberíamos tener.
5.- Elegimos 1 PROCESADOR y un mínimo de 512RAM.
6.- En red elegimos host-only ya que le meteremos un parche después para que funcione.
7.- En SCSI Adapter elegimos LSI Logic, creamos un nuevo disco virtual tipo IDE y ponemos mínimo 16GB (Si queremos instalar el SDK para programar recomiendo al menos 20GB)
8.- Finalizamos la creación de la máquina virtual.

PASO 2 “Instalación”

1.- Llegamos a la parte de la instalación. Arrancamos la máquina y cuando nos indique que presionemos F8 durante el arranque para entrar en el modo consola.
2.- Escribimos: “-v busratio=7 cpus=1″ y pulsamos Enter.
3.- La instalación comienza y nos aparece la primera pantalla, que aceptaremos dandole al boton de la flecha.
4.- Antes de continuar vamos a Utilities y de ahí a Disk Utility.
5.- Seleccionamos la partición de 20GB que hemos creado y le damos a Erase. (Ponemos el nombre que queramos y dejamos el formato por defecto)
6.- Le damos a salir pulsando la X roja y continuamos la instalación, eligiendo la nueva partición que hemos creado.
7.- Antes de terminar, le daremos al boton de customize que nos habrá aparecido y añadimos los siguientes add-ons:
– x86patches -> kernel -> voodoo 9.7.0
– drivers->system-> sata-ide -> intel sata/ide (o amd si tenemos un amd)
– [OPCIONAL] drivers -> USB (Si tienes pensado usar algun disco USB o realmente lo necesitas. Aunque suele pegarse con los demás dispositivos USB)
[Ahora tendrás que echarle imaginación]
Si usas ratón o teclado USB deberías seleccionar:
– x86patches -> ACPI -> x86 ACPI
– ps2-> apple ps2 mouse & keyboard
Si usas ratón y teclado PS2:
– ps2 -> voodoo ps2 mouse & keyboard
8.- Aceptamos y comenzamos la instalación. (podemos darle a skip en la comprobación)

PASO 3 “Primer arranque”

1.- Una vez termina la instalación se reiniciará el sistema y pueden ocurrir dos cosas. Que te arranque a la primera sin tocar nada (tienes una flor en el culo) o que empiece a entrar en un maravilloso bucle de reinicios infinito. (Si tienes activadas las alertas te dara un petardazo del kernel y al aceptar se reiniciará).

2.- Lo que tenemos que hacer es darle a F8 (aunque creo que cualquier tecla sirve), durante el arranque y escribir nuestro maravilloso: “-v busratio=7 cpus=1″ y darle a ENTER. (Estoy convencido de que se podría configurar para no tener que escribirlo cada arranque, pero no he conseguido hacerlo, así que en cada reinicio tendremos que hacer lo mismo para que reinicie)

El parámetro -v activa el modo VERBOSE, que nos dirá paso por paso lo que está haciendo el sistema. Es bastante útil si no conseguimos arrancar para saber qué está causando el problema. Si es un driver problemático, la última linea antes del petardazo nos indicará cual es. En cualquier caso, hay que tener paciencia con el arranque; si no arranca, probad varias veces antes de descartar que la máquina no funcione.

3.- Si dios quiere arrancaremos el sistema y todo funcionará correctamente (más o menos, el sonido es un coñazo configurarlo)
4.- Nos pedirá que configuremos nuestro equipo y fiesta. Tendremos nuestra máquina virtual de Leopard 10.5.7.

PASO 4 “Configurando la red”

El último paso que nos queda es configurar la red. Es opcional ya que podemos no necesitarla.

1.- Para ello tendremos que bajarnos el siguiente archivo: http://rapidshare.com/files/353866969/Maxxuss-AMDPCNET-v1.0.iso
2.- Una vez lo tengamos, lo descomprimimos y nos aparecerá una ISO. Con la VM apagada seleccionamos este ISO en la unidad de CD/DVD.
3.- Antes de arrancar la máquina, vamos al directorio donde la tengamos en nuestro equipo y editamos el archivo .vmx con el Notepad.
4.- Agregamos la siguiente linea: ethernet0.virtualDev = “e1000? Guardamos y arrancamos el sistema.
5.- Una vez dentro de Leopard de nuevo, copiamos el contenido del ISO que hemos cargado en cualquier lugar localizable.
6.- Iniciamos el Terminal y escribimos lo siguiente:
$ sudo ./install.sh
$ sudo reboot

(NOTA: Debemos estar localizados en la ruta donde hayamos copiado el contenido del ISO, y dentro de la carpeta. Nos pedirá la contraseña del sistema y reiniciará la máquina)

7.- Al reiniciar, iremos a Ajustes -> Network y nos indicará que hay un nuevo dispositivo. Aceptamos y seleccionamos DHCP. Cerramos y voila! Deberíamos tener acceso por red a nuestro equipo y a internet.

Eso es todo amigos! Espero que haya sido de utilidad.

Un saludo

Cuando creamos un instalador para alguno de nuestros proyectos de Visual Studio podemos necesitar incluir como requisito tener instalada algun paquete o complemento e incluso podermos querer añadirlo al instalador para que, si no está instalado, lo haga.

A esto se le conoce como Bootstrapping y es bastante sencillo.

Para ello lo primero que tenemos que hacer es crear un paquete personalizado para cada complemente que queramos añadir como prerrequisito a nuestro instalador. Por ejemplo, si queremos hacer un instalador para nuestra aplicacion y nos damos cuenta de que requiere el Adobe Reader, podemos hacer un paquete llamado AdobeReader con el redistribuible del Adobe Reader.

Antes de nada saber que estos paquetes se añaden desde Visual Studio a la hora de crear un instalador. Dentr del proyecto de instalación, si vamos a Propiedades del proyecto y ahí a Requisitos Previos obtendremos una lista de los paquetes por defecto que se incluyen en el SDK de Visual Studio, que será similar a la siguiente imagen:

Cada uno de estos requisitos equivale a una carpeta con un ejecutable, unos manifiestos (XML) y otros archivos opcionales de configuración.
Todos estos paquetes se encuentran en una ruta del disco que dependerá de la versión de Visual Studio que estemos utilizando:

Visual Studio 2005: C:\Archivos de programa\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages
Visual Studio 2008: C:\Archivos de programa\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages

Por lo que lo primero que debemos hacer es ir a la ruta que nos corresponda y crearnos una carpeta con el nombre de nuestro paquete, en nuestro caso “AdobeReader”.

El siguiente paso será meter en dicha carpeta el ejecutable que nos instala el AdobeReader. (Hay que tener en cuenta que existen dos versiones de este instalable, al igual que en muchos otros. Una completa que se instala completamente offline y otra online que descarga contenido desde Internet. La primera hara más pesado el contenido de la instalación pero no requerirá acceso a Internet, y la segunda pues obviamente lo contrario)

El tercer paso es crear el manifiesto “Product.xml”. Vamos, crear un XML con este nombre al que añadiremos lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<Product ProductCode="AdobeReader" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
  <PackageFiles CopyAllPackageFiles="false">
    <PackageFile Name="AdobeReader-setup.exe" Hash="F774D8891793C46BDDC1F9418D8E427B6CBAE26D" />
  </PackageFiles>
  <InstallChecks>
    <FileCheck Property="" SpecialFolder="ProgramFilesFolder" SearchPath="C:\Archivos de programa\Adobe\Reader 8.0\Reader" FileName="AcroRd32.exe" />
  </InstallChecks>
  <Commands Reboot="Defer">
    <Command PackageFile="AdobeReader-setup.exe">
      <ExitCodes>
        <DefaultExitCode Result="Success" String="Anunexpectedexitcodewasr" FormatMessageFromSystem="true" />
      </ExitCodes>
    </Command>
  </Commands>
</Product>

Este es el manifiesto obligatorio para que el paquete sea reconocido por el Visual Studio. Pero también tenemos el manifiesto “Package.xml” que añadirá información adicional a nuestro paquete tal como un EULA, o el idioma de la instalación:

<?xml version="1.0" encoding="utf-8" ?>
<Package
  xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"
  Name="AdobeReader"
  Culture="Culture"
  LicenseAgreement="eula.txt">
 
  <PackageFiles>
    <PackageFile Name="eula.txt"/>
  </PackageFiles>
 
  <Strings>
    <String Name="DisplayName">AdobeReader</String>
    <String Name="Culture">es</String>
    <String Name="NotAnAdmin">Debes tener permisos de administrador para poder ejecutar este paquete.</String>
    <String Name="GeneralFailure">A ocurrido un error al intentar instalar el paquete.</String>
  </Strings>
</Package>

En este caso, si añadimos una referencia a “eula.txt” tendremos que añadir el correspondiente fichero con el texto que se deberá mostrar en el EULA.

El cuarto paso es importante, y es que si tenemos el Visual Studio instalado en la lengua de Shakespeare, tendremos que añadir un manifiesto por defecto para dicho idioma. Bastará con crear una carpeta llamada “es” dentro de nuestro paquete y poner una copia del fichero “Product.xml” dentro.

Y ya está! Si volvemos a la ventana del Visual Studio donde se mostraban los prerrequisitos por defecto veremos que aparece nuestro paquete “AdobeReader”. Molto facile e divertente.

Y ahora viene la parte buena, que la he puesto al final para joder un poco, que hay que saber cómo funcionan las cosas y hacerlas a lo Clint Eastwood antes de recurrir a lo fácil. Y es que existe una maravillosa herramienta de Microsoft que nos hace todo el trabajo en unos cuantos clicks. Se llama Bootstrapper Manifest Generator y se puede obtener gratuitamente desde la siguiente URL:

http://code.msdn.microsoft.com/bmg

La aplicación es bastante sencilla y nos da la posibilidad de crear manifiestos mas complejos añadiendo condiciones y otros parámetros de configuración.

Espero que fuera de ayuda para alguien que lo necesite.

Un saludo

Cuando se trabaja de forma asíncrona con AJAX y UpdatePanels resulta imprescindible implementar procesos para informar al usuario de que se están efectuando actualizaciones en el servidor.

Por defecto, ASP.NET AJAX nos proporcionar el complemento UpdateProgress, que unido a un ScriptManager y un UpdatePanel permiten mostrar cualquier indicador mientras el UpdatePanel esta trabajando asíncronamente.

No obstante el UpdateProgress es limitado si queremos realizar tareas o efectos mas complicados. Por ejemplo posicionar el loader dinamicamente en la pantalla segun lo que se actualice, realizar alguna accion de Jscript antes de comenzar la actualización, o permitir al usuario cancelar el proceso.

Para ello existe un maravilloso y muy simple javascript que controla dos eventos importantísimos de la página; el comienzo y el fin del httprequest.

<script language="javascript" type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(
  function(sender, e)
  {
        $get('cargador').style.display="block";
   });
 Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
  function(sender, e)
  {
        $get('cargador').style.display="none";
   });
 
</script>

Donde “cargador” podría ser, por ejemplo:

<div id="cargador" runat="Server" style="display:none">
        <table width="200">
            <tr>
                <td height="50" valign="bottom" align="center">Cargando...</td>
            </tr>
            <tr>
            <td height="50" valign="top" align="center"><img alt="cargando..." src="../img/ajax-loader.gif" /></td>
            </tr>
        </table>
    </div>

add_beginRequest se lanzaría antes de comenzar el evento de solicitar información al servidor y add_endRequest justo despues de terminar todo el proceso.

Para cancelar el Request bastaría con mostrar un boton en el beginRequest que lanzara el siguiente script:

function CancelarPostback() {
    var man= Sys.WebForms.PageRequestManager.getInstance();
    if (man.get_isInAsyncPostBack())
        man.abortPostBack();
    }

Aunque ojo! con este “Cancelar” ya que, si bien cancelara el request y forzando el endRequest, el proceso en el servidor es muy probable que se haya ejecutado ya. Mi consejo es que se utilice unicamente para procesos de lectura y no de escritura.

Un saludo

Cómo continuación del truquillo que puse para guardar las lineas de los errores en el servidor voy a añadir un tutoríal para guardar un log de errores en ficheros, de esta manera cada vez que ocurra un error, sea contrlado mediante un bloque try-catch o sin controlar, tendremos constancia de él y sabremos donde ha ocurrido, incluido el origen y la linea.

Lo primero que hay que tener en cuenta es que la mayoría de los errores que ocurren en nuestra página web deben estar controlados, pero puede suceder que ocurran excepciones en lugares que no habiamos previsto. Incluso aunque sepamos que tenemos todo controlado creo que siempre es recomendable establecer un proceso para los errores globales de nuestra aplicación, aunque nunca se utilice.

Para ello implementaremos dos versiones de la misma función, a la que llamaremos, por ejemplo, “lanzarError”; la primera recibirá la excepción que hemos controlado desde nuestra página web, la tratará y la almacenará en una ruta específica.

public static int lanzarError(Exception ex)
        {
 
            StringBuilder errorInfo = new StringBuilder();
 
            //obtenemos la traza del error
            System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(ex, true);
 
            //creamos un contenido que incluiremos en el log del error
            errorInfo.Append("Método: " + ex.TargetSite.ToString() + "\n");
            errorInfo.Append("Código: " + ex.Source + "\n");
            errorInfo.Append("Mensaje de Error: " + ex.Message + "\n");
            errorInfo.Append("Traza de la Pila: " + ex.StackTrace + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("Excepción:" + ex.ToString());
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
 
            //añadimos información adicional (Es necesario cargar el .pbd de la aplicación)
            errorInfo.Append("Método:" + trace.GetFrame(0).GetMethod().Name + "\n");
            errorInfo.Append("Linea:" + trace.GetFrame(0).GetFileLineNumber().ToString() + "\n");
            errorInfo.Append("Columna:" + trace.GetFrame(0).GetFileColumnNumber().ToString() + "\n");
 
            //obtenemos el nombre del fichero añadiendo un sufijo
            string nombreFichero = obtenerNombreFichero("CAUGH_EX");
 
            //escribimos en el fichero del log
            if (escribirFichero(errorInfo.ToString(), nombreFichero) == -1)
            {
                return -1;
            }
            else
            {
                return 1;
            }
 
        }

Cómo podemos ver no tiene ningún secreto, crearemos un StringBuilder con lo que queramos guardar en nuestro fichero de log, elegimos un nombre para el fichero y escribimos.

Esta función hace uso de dos funciones adicionales; una para establecer el nombre del fichero y otra para escribir en él.

protected static string obtenerNombreFichero(string sufijo)
        {
            string fecError = "";
            string codError = "";
            DateTime Now = System.DateTime.Now;
            //DateTimeFormatInfo dfi = new DateTimeFormatInfo();
 
            //establecemos el formato que tendrá la fecha incluida en el nombre
            //dfi.FullDateTimePattern = "dd-MM-yyyy_HHmmss";
 
            fecError = String.Format("{0:dd-MM-yyyy_hh.mm.ss}", Now);
 
            codError = fecError + "_" + sufijo;
 
            string nombreFichero = "Error_" + codError + ".txt";
 
            return nombreFichero;
 
        }

Podemos elegir el nombre del fichero que queramos. En este caso he pensado que establecer la fecha completa sería una buena idea, pero ojo!, tenemos que tener en cuenta que si no añadimos un nombre único podemos encontrarnos con ficheros duplicados. Tenemos dos opciones. O comprobamos que si existe un fichero con ese nombre añadimos un sufijo adicional, o añadimos más parámetros a la hora (¿milisegundos?).

protected static int escribirFichero(string texto, string nombreFichero)
        {
 
            //obtenemos la ruta donde crearemos el log. Podemos enviarla desde nuestra aplicación
            string ruta = ConfigurationSettings.AppSettings.Get("errorPath") + "\\errores\\";
 
            //controlamos que existe la ruta y si no la creamos
            if (!System.IO.Directory.Exists(ruta))
            {
                System.IO.Directory.CreateDirectory(ruta);
            }
 
            //creamos el flujo de salida para escribir
            System.IO.StreamWriter sw = new System.IO.StreamWriter(ruta + nombreFichero, false);
 
            try
            {
                //intentamos escribir en el fichero
                sw.Write(texto);
                sw.Flush();
                return 1;
            }
            catch (Exception ex)
            {
                return -1;
            }
            finally
            {
                sw.Close();
            }
 
        }

Esta segunda función nos servirá para escribir en el fichero, enviándole previamente una ruta en donde almacenar los ficheros del log. En este ejemplo la ruta se obtiene desde un fichero de configuración de la aplicación, pero si queremos encapsular totalmente el registro de errores deberemos enviar esta ruta desde nuestra aplicación web y habrá que añadirlo como parámetro en la cabecera de la función.

Finalmente tenemos la segunda versión de lanzarError que sobrecarga a la primera:

public static int lanzarError(HttpContext ctx)
        {
            //Deberemos pasar información de la sesión desde nuestra aplicación
            //HttpContext ctx = HttpContext.Current;
 
            //obtenemos le ultimo error ocurrido
            Exception exception = ctx.Server.GetLastError();
            StringBuilder errorInfo = new StringBuilder();
 
            //obtenemos la traza del error
            System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(exception, true);
 
            //creamos un contenido que incluiremos en el log del error
            errorInfo.Append("Página del Error: " + ctx.Request.Url.ToString() + "\n");
            errorInfo.Append("Código: " + exception.Source + "\n");
            errorInfo.Append("Mensaje de Error: " + exception.Message + "\n");
            errorInfo.Append("Traza de la Pila: " + exception.StackTrace + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("Excepción:" + exception.ToString());
            errorInfo.Append("*******************************************************************" + "\n");
            errorInfo.Append("*******************************************************************" + "\n");
 
            //añadimos información adicional (Es necesario cargar el .pbd de la aplicación)
            errorInfo.Append("Método:" + trace.GetFrame(0).GetMethod().Name + "\n");
            errorInfo.Append("Linea:" + trace.GetFrame(0).GetFileLineNumber().ToString() + "\n");
            errorInfo.Append("Columna:" + trace.GetFrame(0).GetFileColumnNumber().ToString() + "\n");
 
            //obtenemos el nombre del fichero añadiendo un sufijo
            string nombreFichero = obtenerNombreFichero("UNCAUGH_EX");
 
            //escribimos en el fichero del log
            if (escribirFichero(errorInfo.ToString(), nombreFichero) == -1)
            {
                return -1;
            }
            else
            {
                return 1;
            }
 
        }

Cómo podemos ver es similar a la primera salvo que en este caso se envía la información sobre el contexto de la aplicación y de ahí obtendremos el último error ocurrido. Esta función nos permitirá registrar excepciones no controladas, pero para ello primero deberemos añadir un par de cosas en el fichero “Global.asax” de nuestra aplicación web:

protected void Application_Error(object sender, EventArgs e)
        {
            HttpContext ctx = HttpContext.Current;
            exCatcher.lanzarError(ctx);
            ctx.Response.Redirect("Error.aspx");
        }

El evento Application_Error ya existe por defecto en el Global.asax, así que solo tendremos que añadir el contenido. Esto unicamente obtendra el estado de la aplicación y lo enviará a nuestra función lanzarError. Finalmente redirigiremos a una página de Error que nos habremos creado previamente y en la que informaremos al usuario de lo que creamos conveniente.

Y eso es todo. Esto podemos complicarlo todo lo que queramos para añadirle más posibilidades.

Espero que haya servido de ayuda.

Un saludo

Powered by WordPress Web Design by SRS Solutions © 2010 a nil value Design by SRS Solutions