Friday, December 22, 2006

Visual Studio 2005 SP1 para Windows Vista (Beta)

esta disponible, justo a tiempo para navidad

Wednesday, December 20, 2006

funcion para generar numeros aleatorios, con todos los digitos distintos

El codigo para este articulo aplica a C#

Leyendo blogs, me encontre con este post (en italiano), donde Marco quiere escribir una funcion que le genere numeros aleatorios de 5 digitos, el resultado se requiere en un string, donde todos los digitos son diferentes, es decir, cada numero (de 5 digitos) generado, no puede tener 2 digitos iguales, la funcion que el escribio es la siguiente:

private string GetRandom()
{
Random rn = new Random();
string resultnum=string.Empty;
do
{
string a = rn.Next(0, 9).ToString();
if (resultnum.Contains(a)!=true)
resultnum = resultnum + a;
}
while (resultnum.Length<5); style="color: rgb(0, 0, 255);">return resultnum;
}

Inmediatamente me dio curiosidad por ver que areas que podria mejorar, y me puse a escribir una funcion que obtuviera el mismo resultado, pero en forma mas optimizada

cosas que saltan a mi mente inmediatamente son:

  1. concatenacion de strings
  2. el loop y la comparacion para encontrar numeros que no tengamos previamente

Entonces lo que quise lograr en mi funcion es: evitar la concatenacion, y ejecutar el loop exactamente 5 veces, esto es el resultado:

static char[] allNumbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Random r = new Random();
public string GetRandom2() {

char[] result = new char[5];
int max = 9, pos=0;
for (int i=1; i<6; pos =" r.Next(0," style="color: rgb(0, 128, 0);">//*** swap positions
allNumbers[pos] ^= allNumbers[max];
allNumbers[max] ^= allNumbers[pos];
allNumbers[pos] ^= allNumbers[max--];
}
return new string(result);
}

La tecnica que use,

- fue tener un arreglo predefinido de caracteres con todos los digitos,

- luego tengo una variable max que uso para llamar el metodo Random.Next(0, max),

- en cada iteracion del loop decremento esta variable,

- y cambio el numero que resulto elegido a la ultima posicion, con esto lo dejo fuera de las posibilidades para la siguiente llamada

Estos cambios me dieron una ganancia realmente minima (3 milesimas por cada 1000 llamadas), luego se me ocurrio mover la declaracion de la variable Random afuera de la funcion, para que se reusara con cada llamada a este metodo, y eso si que me dio una ganancia tremenda, llamando la funcion 10,000 veces, el metodo original me da 114ms, y el metodo nuevo 6ms, asi que ahi era donde estaba realmente el problema, lo demas es casi insignificante =o(

Seguro alguien mas puede crear una funcion mas rapida, pero yo cumpli mi objetivo =o)

salu2

Signo de que estas blogueando mucho: blog Deja Vu

Antonio Ganci nos platica (blog en italiano) que algunas veces cuando va a postear algo, le da la sensacion de que ya escribio eso antes en su blog, algo asi como blog Deja Vu, luego se pone a checar sus posts viejos, para cerciorarse que no lo habia escrito realmente

Se me hizo chistoso, personalmente aun no me ha pasado algo asi, pero probablemente le pasa a bastante gente en estos dias; el efecto Deja Vu me parece un tema muy interesante... y hace algunos dias fui a ver la pelicula Deja Vu, que se me hizo bastante buena, aunque creo que le encontre unos errores en la secuencia, pero haber ustedes que piensan

salu2

Como borrar elementos de una lista generica

El codigo para este articulo aplica a C# 2.0

Una tarea mas o menos comun cuando usamos una lista generica, es borrar elementos de esta, vamos a ver que alternativas tenemos:

#1 La forma definitivamente equivocada de hacerlo:

List<Person> l1 = GetList();
//*** The wrong way
foreach (Person p in l1) {
if (p.Age > 30)
l1.Remove(p);
}

Este codigo nos dara una excepcion InvalidOperationException: "Collection was modified; enumeration operation may not execute."

#2 Funciona mas o menos (y nos permite ejecutar una accion en cada elemento que vamos a borrar)

List<int> ints = new List<int>();
ints.Add(1);
ints.Add(2);
ints.Add(3);
ints.Add(4);
ints.Add(5);
ints.Add(6);

ints.ForEach(delegate(int i) {
if ((i % 2) == 0) {
Console.WriteLine("removing"+i.ToString());
ints.Remove(i);
}
});

Si corres este codigo funcionara perfectamente, pero la verdad es que tiene un problema grande, si agregaras los numeros pares primero, verias que no los borra todos, y no te da una excepcion ni nada, simplemente se sale del foreach y continua; asi que este metodo funciona, pero solo en condiciones especiales, lo cual lo hace codigo peligroso

#3 La forma correcta: recorremos la coleccion hacia atras y borramos elementos cuando necesitamos
int x = ints2.Count;
while (--x>=0) {
if (ints2[x] < 4)
ints2.RemoveAt(x);
}

#4 Una mejor manera: La lista generica trae un metodo ya incluido que nos sirve para borrar multiples elementos

ints2.RemoveAll(delegate(int i) {
return i <4;
});

#5 Pero que pasa si quiero ejecutar una accion en cada elemento que se borre?

ints2.RemoveAll(delegate(int i) {
if (i < 4) {
//*** Perform action here
Console.WriteLine("removing :" + i.ToString());
return true;
}
else
return false;
});


Si el elemento fuera una clase, podrias mandar llamar uno de sus metodos antes de borrarlo (por ejemplo una llamada a la base de datos)

Mas adelante escribire en detalle porque exactamente las alternativas #1 y #2 no funcionan

salu2

Monday, December 18, 2006

poner el focus en el campo UserName de un control ChangePassword

Estaba intentando todo tipo de cosas para poner el focus en el control UserName del control ChangePassword, resulta que es tan simple como:

if (!Page.IsPostBack)
ChangePasswordControl.Focus();

Funciona para el control Login tambien

if (!Page.IsPostBack)
LoginControl.Focus();

macros en el buen amigo DOS

Acabo de leer este post (por Jeffery Hicks?): Make an old friend do your work Donde explica como puedes usar el buen "doskey" para facilitarte la vida (en la linea de comando), y me motivo a escribir este post por 2 razones:

- Le faltaron un par de cosas
- Quiero recordar estos comandos, ya que parece que comienzo a olvidar cosas =o(

Vamos a ver, primero el define una macro asi:
doskey xl="%programfiles%\Microsoft Office\Office11\Excel.exe" $1 $2 $3 $4 $5

y explica "Puedes usar variables como $1 y $2 (hasta $9)".
Pero porque limitarnos con solo 9 parametros? puedes escribir la macro asi:
doskey xl="%programfiles%\Microsoft Office\Office11\Excel.exe" $*

Y tomara cualquier numero de parametros que le pases. Para probar que tomaba mas de 10 parametros cree un archivo 1.xls y luego corri este comando (muchisima gente no sabe de esta capacidad del CMD):

for /l %e in (2,1,11) do copy 1.xls %e.xls

Esa linea quiere decir algo asi como: un loop del 2 al 11, incrementos de 1, copia el archivo 1.xls a [variable].xls;
Ahora tengo 11 archivos para jugar, ahora llamo la macro:
xl 1 2 3 4 5 6 7 8 9 10 11

Lo cual nos lleva a otro punto que le falto: "de la linea de comando puedo escribirxl file1.xls file2.xls file3.xls y Excel abrira los 3 archivos"
Pues no tienes que especificar la extension, puedes pasar el nombre del archivo sin extension y Excel lo abrira sin problemas

Esto tambien nos lleva a otro punto: Si solo quieres abrir un solo archivo, solo tienes que escribir el nombre del archivo:
1.xls
Y Windows lo abrira usando la aplicacion asignada a ese tipo de archivo (Excel en este caso), asi que para archivos simples, no necesitamos la macro

finalmente, esta macro no funciona para Notepad (o Notepad2), si ejecutas
np 1.txt 2.txt
trata de abrir el archivo "1.txt 2.txt"

Asi que solo puedes abrir un archivo a la vez =o(

un ultimo truco, para borrar una macro, simplemente ejecutas
doskey myMacro=

salu2

Sunday, December 17, 2006

Como obtener todos los campos privados de otra clase

Hace casi 2 meses escribi unos articulos acerca del uso de refleccion, especificamente sobre como ejecutar metodos privados, alguien dejo una pregunta sobre como podria obtener todos los campos privados de una clase, apenas hoy me di tiempo para contestar aqui mismo en el blog; primero vamos a crear una clase de prueba

class TestClass {
private int prop1;

public int Prop1 {
get { return prop1; }
set { prop1 = value; }
}

private string prop2;

public string Prop2 {
get { return prop2; }
set { prop2 = value; }
}

private bool prop3;

public bool Prop3 {
get { return prop3; }
set { prop3 = value; }
}

public bool field4;

public TestClass() {
prop1 = 10;
prop2 = "20";
prop3 = false;
field4 = true;
}
}



luego creamos una instancia de esta clase, y utilizamos el metodo GetFields para obtener la lista de campos, pasando como parametros que queremos los campos privados que pertenezcan a una instancia (que no sean estaticos), una vez que tenemos la lista podemos hacer lo que queramos, en este caso imprimo el tipo del campo y el valor de este

TestClass test = new TestClass();
FieldInfo[] fields = test.GetType().GetFields(BindingFlags.NonPublic BindingFlags.Instance);
foreach (FieldInfo f in fields)
Console.WriteLine(string.Format("type:{0} \t value:{1}", f.FieldType.ToString(), f.GetValue(test)));




listo, eso es todo. Ahora solo para hacerlo un poquito mas interesante me puse a crear una funcion generica para realizar esta tarea y puede reutilizarse con cualquier otra clase:

static void PrintPrivateFields<T>(T theInstance) where T:class {
Type t = theInstance.GetType();
FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic BindingFlags.Instance);
foreach (FieldInfo f in fields)
Console.WriteLine(string.Format("type:{0} \t value:{1}", f.FieldType.ToString(), f.GetValue(theInstance)));
}



para usarla simplemente creamos la instancia de la clase, y pasamos esta instancia a nuestra funcion:


TestClass test = new TestClass();


PrintPrivateFields(test);


noten que no necesito pasarle el tipo generico asi


PrintPrivateFields<TestClass>(test);


sino que el compilador es inteligente y puede derivar el tipo generico.


Espero les sea util, el codigo completo lo encuentran aqui, salu2

Termine de navegar "El Internet"

From tecblog

O dicho de otra manera, por fin termine de leer todos los blogs que tenia pendientes!, la cosa es que he estado enfermo y bastante ocupado este ultimo mes, lo cual tambien ha sido la razon de que no he escrito mucho en mi blog. Pero los escritores de los blogs que leo no me dan descanso, apenas si me paso 2 dias sin leer blogs y me atrazo bastante; aqui les dejo una lista de los posts que me han parecido mas interesantes (de los 266 blogs a los que estoy subscrito), tratare de incluir los links interesantes en español en algun lado en esta pagina, creo que en el link que les dejo todo es en ingles =o(
Posts interesantes

Friday, December 15, 2006

Como instalar Visual Studio SP1 en menos de una hora

La noticia de que el Service Pack 1 para Visual Studio esta listo anda por todos los blogs, pero hay un problemita, estan reportando que se tarda muchisimo para instalar (mas de 2 horas), yo lo que hice es que cerre todos los programas de windows y esta lista de servicios:

- Print Spooler
- Tu programa antivirus, ej. yo tengo: "Symantec Antivirus Client"
- Task Scheduler
- TCP/IP NetBIOS Helper Service
- VNC Server
- IIS Admin Service (junto con los otros servicios que dependen de este)
- MSSQL* (Puede haber varios de estos, yo los apagaria todos)
- cualquier otro servicio que reconozcan y que puedan apagar sabiendo que no va a afectar nada (sincronizador de PDA, etc)

y listo, la instalacion completa salio como en media hora, ojala que esto le sirva a alguien
salu2

Actualizacion: en mi maquina vieja (que le acabo de instalar Windows Vista) la actualizacion de Visual Studio me tomo solo 20 minutos =o) siguiendo mi simple recomendacion

Monday, December 11, 2006

Tour Juarez-Chihuahua 2006

Pues es esa temporada del año en la que tengo la oportunidad de regresar a visitar a la familia y amigos por alla en mi tierra, voy a estar en Juarez y Chihuahua (y Cuauhtemoc talvez 1 o 2 dias) entre el 23 de Diciembre y el 1 de Enero, si alguien esta interesado en tener una cena geek, platicar o lo que sea, dejenme un comentario y ahi nos arreglamos

salu2

Saturday, December 09, 2006

Windows is unable to find a system volume that meets its criteria for installation

Tuve algunos problemitas (bueno, realmente solo uno, el error mencionado en el titulo) instalando Windows Vista en mi maquina vieja ( hey, mi maquina ya tiene mas de un año... y hey!, ya tengo mas de un año en esto del blog!!)... en que estaba, ah si, lo del mensaje ese de error, pues por mas que trataba, seguia recibiendo ese mensaje al tratar de instalar Vista en cualquiera de las (3) particiones de mi disco SATA, borre particiones, las formatee, las recree, nada funcionaba. Por supuesto anduve buscando informacion acerca de este problema, y lo mejorcito que encontre fue una respuesta en un foro "Vista debe ser instalado en la particion activa", y eso que se supone que quiere decir???

En un ultimo y desesperado intento, desconecte el otro disco duro (que no mencione antes =o) ), dejando solo el disco SATA conectado, corri la instalacion y voila!, era todo lo que necesitaba, la instalacion corrio sin ningun problema despues de eso, y todo esta funcionando perfectamente hasta ahorita, creo que hasta Internet Explorer 7 me gusta mucho mas en Vista, y esto de los efectos Aero Glass esta chido chido chido!

Aqui esta una lista de teclas de rapido acceso para aquellos de ustedes que sean nuevos usando Vista (no halle un link en español =o(... tendre que poner una recopilacion aqui pues =o))

Y pues espero que mi experiencia le sea de ayuda a alguno, ahora si me disculpan tengo que ir a jugar, siguiente paso: Office 2007

Thursday, December 07, 2006

Wednesday, December 06, 2006

Comandos de Novell para recordar

Yo "creci" usando servidores Novell y DOS, recuerdo que era bastante bueno para administrar servidores Novell, pero hace un buen que no toco un servidor de estos; ayer unos colegas estaban teniendo problemas con uno de estos servidores y me hablaron para pedirme ayuda, y yo no me podia acordar de esos comandos, asi que este post es para guardar en mi memoria digital esos comandos para en caso de que se me ofrezca despues, y talvez tambien tu eres bien suertudo y los puedas usar algun dia

Comandos para el servidor

  • server - En un prompt de DOS, inicia el servidor
  • restart server - resetear el servidor pues
  • VRepair - Usalo para corregir problemas con los volumenes (no puedes usar vrepair en un volumen montado)
  • enable/disable login - para que los usuarios no nos molesten
  • mount/dismount - poner un volumen disponible a los usuarios (mount all para montar todos los volumenes)
  • volume - obtener una lista de volumenes montados, o la informacion acerca de un volumen en particular (parametro)
  • down - bajar el servidor (amablemente)
  • load/unload monitor - cargar/descargar el monitor (para administrar el servidor con un bonito UI)
  • tcpcon - un bonito monitor con bastante informacion sobre TCP y otros protocolos de red
  • display environment/processors/servers/networks / modified environments / interrupts -
  • list devices - obtener una lista de dispositivos de almacenamiento (discos duros, cd-rom, etc)
  • memory - muestra el total de memoria instalada a la cual el sistema operativo tiene acceso
  • mirror status - ver el estado de las particiones de disco espejeadas(???), ver el porcentaje de datos espejeados en cada particion
  • modules - obtener una lista de los modulos cargados

Commands para las maquinas de usuario

  • attach - connectar a otro servidor, pero mantenerse conectado al servidor actual
  • caston/castoff - habilita mensajes de la red de otras maquinas de usuario y del servidor si se usa la opcion ALL
  • chkvol - muestra informacion del volumen, espacio libre, uso, archivos borrados, etc
  • login/logout - pues eso mismo...
  • rights - muestra los derechos para archivos y directorios
  • rconsole - consola remota, para controlar el servidor desde un cliente; si el servidor no se especifica, nos muestra una lista
  • purge - remover archivos (previamente borrados) permanentemente, archivos purgados no pueden ser recuperados
  • slist - lista de servidores
  • syscon - administrar usuarios, grupos, derechos, etc
salu2

Tuesday, December 05, 2006

Haz estado usando patrones de diseño desde hace tiempo...

Por ejemplo aqui esta este, llamado Composed method:
Divide tu programa en metodos que realizan una tarea identificable. Manten todas las operaciones de un metodo al mismo nivel de abstraccion. Esto resultara naturalmente en programas con muchos metodos pequeños, cada uno con pocas lineas de codigo.
Es tan simple como extraer codigo de metodos grandes, y crear metodos mas pequeños, algo que haces todos los dias que programas algo, hay muchos patrones simples como este, lo unico que hacen es describir (con un nombre corto) las tareas que realizas diariamente.

La idea es que conociendo estos patrones por nombre, te puedes comunicar mucho mas rapido, facil y mejor, y usandolos te conviertes en un programador mas educado, un mejor desarrollador; recuerda que un gran desarrollador es aquel que no solo escribe codigo increiblemente eficiente, sino que ademas es capaz de comunicar ideas y trabajar en equipo.

"El mejor codigo en el mundo no tiene sentido si nadie sabe acerca de tu producto."

Asi que como ves, ya has estado usando patrones de diseño desde que estas programando, ahora aprendete los nombres de estos, aprende mas patrones, usalos y educa a tu equipo (tambien a compañeros, lectores de tu blog, etc) sobre estos.

Ademas de todo lo anterior, tambien aprendes mas tu al enseñar a los demas.

salu2

Monday, December 04, 2006

si eres talentoso, las herramientas no importan tanto

Este es el primer post usando blogger beta, haber que tal... mientras chequense este chavo, lo que puede hacer usando solamente Paint

Sunday, December 03, 2006

trucos css: encabezado, pie de pagina y area principal cubriendo 100% del documento

En los viejos tiempo (no hace ni tanto) yo empezaba una pagina con una table html con 3 rows, uno para el encabezado, uno para el area principal (al 100% de tamaño) y uno para el footer

En estos dias esto ya no funciona, y ademas nos dicen que debemos usar CSS puro, que nada de html y no se que... pero como logramos esto con puro CSS?

Vamos a necesitar algo de CSS y un poco de javascript, primero vamos a ver el CSS

html,body,form
{
margin:0;
padding:0;
}//prevent some default spacing on some browsers
.header
{
text-align:center;
background-color:Navy;
color:White;
width:100%;
}
.footer
{
background-color:Orange;
color:Navy;
position:absolute;
bottom:0;
border:0;
}
div.scrollable{
overflow:auto;
border-left-width:0px;
border-bottom-width:0px;
border-top-width:0px;
border-right-width:0px;
background-color:Gray;
color:White;
position:absolute;
}

Lo mas interesante es la clase div.scrollable; la propiedad overflow:auto hace que el DIV sea scrollable, y el resto es para eliminar los border y poner algo de color.

Ahora vamos a ver el html:

<html>
<head>
</head>
<link rel="stylesheet" type="text/css" href="test.css" />
<body>

<div>
<div id="header" class="header" height="20px">
This is the header
</div>

<div id="mainDiv" class="scrollable">
This is the main body<br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br>
<br><br><br>
This is the last line
</div>

<div id="footer" class="footer" height="20px">
<div style="float:left">This is a div on the left</div>
<div style="float:right">This is a div on the right</div>
</div>

</div>

</body>
</html>

A proposito he puesto muchas lineas en la seccion media, para que se pueda apreciar que el documento hace scrolling (solo en la parte de enmedio, el header y footer siempre se quedan en su lugar). Tambien como un "bono" puse 2 divs en el footer, uno alineado a la izquierda y otro a la derecha, ambos a la misma altura, ya que me he dado cuenta que esta es una de las cosas que mucha gente batalla para lograr. Ya mero terminamos, solo necesitamos un poco de Javascript:

var mainDivHeight;
var mainDivWidth;

function AdjustFullSize() {
var screenHeight = 450;
var screenWidth = 610;

if (window.innerHeight) {
screenHeight = window.innerHeight;
screenWidth = window.innerWidth;
}
else if (document.body) {
screenHeight = document.body.clientHeight;
screenWidth = document.body.clientWidth;
}

mainDivHeight = screenHeight - 20 - 20; //20+20 for header and footer
mainDivWidth = screenWidth - 0;

document.getElementById('mainDiv').style.height = mainDivHeight + 'px';
document.getElementById('mainDiv').style.width = mainDivWidth + 'px';
}

Diferentes browsers tienen diferentes propiedades para accesar el tamaño del documento, asi que nos encargamos de eso y luego asignamos el tamaño al maindiv que es nuestra area principal, mandamos llamar esta funcion en el "onload" (y tambien en el onresize!) y listo, el resultado final es este, puedes obtener el codigo completo de ahi, espero que les sea util.

salu2