|
VB dotNET & more...
-
En vista a que bastante gente me ha pedido si puedo publicar ya el código del proyecto de ejemplo, he decidido publicarlo ahora en lugar de esperar al último post de la serie. En caso que se realicen variaciones en el código, las publicaré posteriormente. Aquí lo teneis, publicado en skydrive (*): (*) En ocasiones, al realizar cross-posting a otros blogs desde el original de geeks.ms, tal vez no aparezca correctamente el enlace a skydrive. Si es así, os recomiendo que visitéis el post original en geeks.ms y realicéis la descarga desde éste. En el post anterior, os dije que en el siguiente (este post) mostraríamos cómo realizar la suplantación (Impersonate) de usuario de Windows para ejecutar nuestra aplicación con otras credenciales. Sin embargo, como ésto ya lo mostré en otro post de una serie anterior, lo doy por explicado y así avanzamos un poco más. System.Net.NetworkInformation Antes de entrar al trapo, un pequeño apunte. Apuntaros este espacio de nombres, que hemos utilizado para obtener algunos datos básicos para el proyecto, y que contiene un montón de métodos que devuelven información muy interesante sobre el tráfico y estadísticas de red. LDAPServices Vamos a ir comentando algunas de los métodos que proporciona esta clase. Como os comenté son todos estáticos, por lo que no es necesario instanciar un objeto para invocarlos. Empecemos: sIDtoString - Trabajando con el AD constantemente vamos a encontrarnos con los llamados SID (identificadores de seguridad). Este método se encarga de transformar un SID (array de bytes) en una cadena de texto que pueda ser mostrada al usuario. public static string sIDtoString(byte[] sidBinary) { SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0); return sid.ToString(); }
getNTAccountName - Devuelve el nombre del objeto dentro del AD a partir de su SID. Por ejemplo, a partir de un identificador de seguridad como {S-1-5-12-7623811015-3361044348-030300820-1013} retorna un string con formato: 'DOMINIO\NombreObjeto'.
public static string getNTAccountName(string wksid) { SecurityIdentifier sid = new SecurityIdentifier(wksid); NTAccount account = (NTAccount)sid.Translate(typeof(NTAccount)); return account.Value; }
getADUserMemberOf - Devuelve un diccionario con los grupos a los que pertenece un usuario. Espera un argumento de tipo token de seguridad (habitualmente utilizaremos el WindowsIdentity.GetCurrent().Token) y el diccionario genérico devuelto es de tipo <string, IdentityReference>.
public static Dictionary<string, IdentityReference> getADUserMemberOf(IntPtr logonToken) { Dictionary<string, IdentityReference> groups = new Dictionary<string, IdentityReference>(); WindowsIdentity user = new WindowsIdentity(logonToken); IdentityReferenceCollection irc = user.Groups; foreach (IdentityReference ir in irc) { groups.Add(getNTAccountName(ir.Value), ir); } return groups; }
(*) Al ir escribiendo el artículo me he dado cuenta de que esta función podría ser optimizada, aprovechando algunas de las nuevas características de C# 3.0, incorporadas en Visual Studio 2008. De modo que podría ser re-escrita del siguiente modo ¡en tan sólo 3 líneas!
public static Dictionary<string, IdentityReference> getADUserMemberOf2(IntPtr logonToken) { WindowsIdentity user = new WindowsIdentity(logonToken); var groups = from g in user.Groups select g; return groups.ToDictionary(p => getNTAccountName(p.Value)); }
¿Menudo cambio, verdad? Observar el uso de:
- Inferencia de tipos (var)
- Palabras clave de consulta (from, in, select)
- Expresiones lambda en la llamada al método extensor ToDictionary (p => getNTAccountName(p.Value))
La verdad es que en cuanto empiezas a usar estas mejoras te 'enganchan'. No sabeis la cara de bobo que se me queda cuando a veces abro el editor de VB6.0 (si, habéis oído bien) para realizar alguna modificación en aplicaciones que todavía no se han migrado a .NET (y lo que les queda... :-P).
Hasta aquí algunos de los métodos que contiene la clase LDAPServices. En el próximo post veremos cómo obtener la lista de propiedades de un objeto user dentro del directorio activo, así cómo realizar búsquedas de objetos dentro del directorio.
No vemos pronto,
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
:-) Hoy he visto en el foro de VB una duda que planteaba Tito, acerca de la posibilidad de usar un entorno de formularios hijos dentro de un TabPanel (al estilo del editor de Visual Studio). No es la primera vez que veo esta duda, así que le he dedicado un ratillo y aquí publico una posible solución. De este modo podemos tener un formulario que actúa como contenedor de otros, pero sin utilizar MDI (que por otra parte me parece ya bastante pasado de moda :-P). La técnica a usar muy sencilla y lo único que hacemos es cada vez que creamos un form, creamos también un objeto TabPage e insertamos el formulario dentro de la nueva pestaña. La única cosa que tenemos que tener en cuenta es establecer la propiedad TopLevel del nuevo formulario 'hijo' a False, ya que de otro modo recibiremos un error. Una muestra: Private Sub ShowForm() Dim r As New Random() Static i As Integer i += 1 Dim key As String = "f" + i.ToString() 'Crea el nuevo form (copia de form2) Dim f As New Form2 f.BackColor = Color.FromArgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255)) f.Text = String.Format("Nuevo form {0}", i) 'Crea el tab que lo contiene Me.Tabs.TabPages.Add(key, f.Text) f.TopLevel = False f.FormBorderStyle = Windows.Forms.FormBorderStyle.None f.Dock = DockStyle.Fill Me.Tabs.TabPages(key).Controls.Add(f) Me.Tabs.SelectedTab = Me.Tabs.TabPages(key) 'Asigna el nuevo form al tag del tabpage Me.Tabs.TabPages(key).Tag = f 'Por si desde el propio form quieres cerrar y eliminar el tab f.Tag = Me.Tabs.TabPages(key) f.Show() End Sub
Podeis descargar el proyecto de ejemplo desde:
Y para los que siempre me tiráis los puntosycoma en cara, lo he realizado en VB (eh Jorge? :-D). Un saludo desde Andorra!
** Modificación (02/07/2008) para agregar un menú contextual a las pestañas **
A petición de Carlos. De este modo es puede cerrar la pestaña actual o todas las pestañas menos la que estamos viendo ahora. El menú es un objeto ContextMenuStrip, de modo que es totalmente extensible para agregar vuestra propia funcionalidad.
La nueva versión está disponible en:
Saludos,
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
En el post anterior vimos que en ocasiones nuestra aplicación deberá acceder a los datos que contiene el directorio activo de nuestra organización, ya sea para buscar elementos, validar credenciales, etc. Hoy nos centraremos en los objetos del framework que nos permiten realizar esto, empezando por el objeto WindowsIdentity, que nos acompaña desde la versión 1.0 del framework, y que representa un usuario de Windows. WindowsIdentity Representa un usuario de Windows. Dispone de un método GetCurrent() que devuelve una referencia al usuario de Windows que está ejecutando la aplicación y que por defecto será el usuario actual de Windows. En nuestro ejercicio vamos a utilizar este objeto para mostrar en la barra de estado algo de información sobre el usuario actual. El nombre y token, así como el contexto de suplantación y diversa información cómo si está autenticado, es de sistema, etc. El código es muy sencillo y para usarlo sólo debemos tener en cuenta haber importado el espacio de nombres System.Security.Principal: private void RefreshUserInformation() { WindowsIdentity user = WindowsIdentity.GetCurrent(); lblUser.Text = string.Format("User: {0}", user.Name); lblToken.Text = string.Format("Token: {0}", user.Token.ToString()); lblImpersonating.Text = string.Format("Impersonating: {0}", user.ImpersonationLevel.ToString()); lblIsAnonymous.Text = string.Format("Is Anonymous: {0}", user.IsAnonymous.ToString()); lblIsAuthenticated.Text = string.Format("Is Authenticated: {0}", user.IsAuthenticated.ToString()); lblIsGuest.Text = string.Format("Is Guest: {0}", user.IsGuest.ToString()); lblIsSystem.Text = string.Format("Is System: {0}", user.IsSystem.ToString()); if (sec.ImpersonationContext == null) { cmdImpersonateApplicationAsUser.Enabled = true; lblUser.ForeColor = Color.Black; lblImpersonating.ForeColor = Color.Black; } else { cmdImpersonateApplicationAsUser.Enabled = false; lblUser.ForeColor = Color.Red; lblImpersonating.ForeColor = Color.Red; } cmdUndoImpersonation.Enabled = !cmdImpersonateApplicationAsUser.Enabled; }
Lo único a destacar es que en caso de que exista suplantación (ImpersonationContext distinto de nulo), mostraremos algunos campos en color rojo, para destacar que este usuario es distinto del que inició sesión en Windows.
LDAPServices
En este proyecto he creado una clase que proporciona una serie de funcionalidades comunes, su nombre es LDAPServices y encapsula una serie de métodos estáticos, para facilitar el trabajo con LDAP. En los próximos posts detallaremos el uso de estos métodos:
SecurityContext
También aparece la clase llamada SecurityContext que ya hemos visto en la serie de posts sobre acceder a la caché de IE, que encapsula toda la lógica necesaria para impersonar nuestra aplicación y que se ejecute con otras credenciales de usuario de Windows.
Esta clase expone una propiedad de tipo WindowsImpersonationContext que devuelve información sobre si está realizando suplantación, y que en caso afirmativo permite terminarla mediante el método Undo(). También expone dos métodos LogonUser y ImpersonateUser, que permiten respectivamente validar unas credenciales de usuario contra un dominio y empezar un contexto de suplantación.
En el próximo post veremos cómo realizar esta suplantación y cómo recabar más información del usuario actual (por ejemplo a que grupos de Windows pertenece el usuario actual).
Hasta entonces!
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
Hemos vuelto a liarla! El pasado 7 de Junio se celebró otro evento en AndorraDotNet en las instalaciones de FIMARGE (gracias de nuevo por la sala). En él tratamos de mostrar las novedades de Visual Studio 2008, en un evento al más puro estilo de la serie Heroes happen {here}. La agenda estaba bastante apretada y de hecho aunque la sesión pasó de las tres horas nos dejamos por ver algunas cosillas, pero de este modo las guardaremos para futuros eventos... que ya tenemos alguno en mente, verdad pilluelos? La sesión transcurrió como a mí me gusta, con mucha participación por parte de la gente (incluso en una ocasión tuve que aclarar que una pregunta no había estado preparada de antemano, jeje...), y tuve la gran suerte que todas las demos salieron bien. Incluso una que se realizó íntegramente picando código 'al vuelo', cosa que ya sabéis que no siempre sale bien :-D, pero en esta ocasión todo salió a pedir de boca. La parte del sorteo estuvo muy divertida, ya que improvisamos un sistema en el que cada asistente tenía 3 números y podía tocarle más de un regalo, pero para evitarlo establecimos como norma que si a uno le tocaba otro premio tenía la posibilidad de escoger entre el nuevo o el que ya tenía, y esto animó bastante la cosa, hasta el punto que aquello parecía más un bingo que un sorteo de goodies y licencias. Como ya os anuncié, os dejo los materiales para su descarga (son libres para usarlos como queráis, bajo licencia jabugoware). La presentación PPTX:
El código fuente con las demos (*):
(*) Incluye el código del sorteo. Para que podáis comprobar que se efectuó limpiamente :-P Al terminar unos cuantos nos fuimos a cenar y continuamos con la charla pero en un ambiente más distendido, y como siempre terminamos hablando los más viejos contando batallitas de cuando la informática era algo nuevo, y cada uno se tenía que documentar como buenamente podía... que tiempos aquellos. En fin, muchas gracias a los que asististeis, y a todos los que no pudisteis venir os invito a hacerlo a la próxima. Un saludo desde Andorra, PD - Os pido disculpas por haber tardado un tiempo en publicarlo, pero me he tomado unos días para reflexionar.
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
Acabo de regresar. He desaparecido por 10 días, y no me he acercado a menos de 2 metros de un ordenador, ni he visto la TV (debo ser uno de los pocos que no ha seguido la Eurocopa), y apenas he leído los periódicos.
Y no ha sido fácil porque lo he dejado todo sin apenas avisar, de modo que ahora tengo muchas llamadas que contestar, una lista de correos y feeds por leer que llega de aquí hasta la calle y muchas tareas que retomar... Pero ha valido la pena.
Hace un par de semanas con mi mujer decidimos pasar unos días de vacaciones en Menorca, y por aquel entonces (Dios, si parece que haga meses!) mi intención era llevarme el ordenador portátil para poder trabajar un poco en alguno de los varios proyectos que tengo en marcha. Sin embargo, mi mujer que es más sabia que yo me prohibió tajantemente (del modo que sólo saben hacer las mujeres) que me llevara el portátil.
Al principio pensé "Bien! Fantástico! con la de trabajo que tengo encima, sólo me falta pasarme una semana sin hacer nada", y sinceramente estuve a punto de enzarzarme en una discusión, pero luego me lo pensé mejor y me dije a mí mismo "mira chico, tampoco se va a terminar el mundo, sabes?" y "bueno, que pasaría si enfermases repentinamente? pues nada, el mundo seguiría girando". Y como estaba en uno de ésos momentos en los que el estrés y la presión hace que pienses que todo da lo mismo accedí, y debo reconocer que ha sido una decisión estupenda.
Esta semana me ha permitido tomarme las cosas con perspectiva, esa perspectiva que el día a día no te permite. Y es que no deja de ser curioso que en la época de la información, en éste mundo cada vez más conectado, en el que los estímulos llegan en tropel a nuestro cerebro, debas tomarte unos días offline para ver las cosas como realmente son, y lo que realmente es importante en tu vida.
Así que cargado de buenas intenciones dejé pasar los primeros dos o tres días para cambiar los hábitos de cuerpo y mente y un buen día me hice la gran pregunta: Vamos a ver chico, ¿tú querías vivir tu vida actual cuando eras pequeño? Y la respuesta me llegó sola al instante: En casi todos los aspectos SI (si dejamos aparte lo de ser astronauta o viajar por el espacio, claro :-P).
-
-
Formo parte de una familia fantástica, con los que sé que puedo contar siempre y que tiene la inmensa suerte de no tener problemas graves.
-
Mis amigos son los mismos de toda la vida y otros más que se han ido incorporando durante el viaje.
-
Vivo en un pueblecito encantador, pequeñito y que no tiene nada que ver con una gran ciudad.
-
Trabajo en algo que me encanta, ya que he hecho de mi hobby mi oficio. Cuánta gente desearía lo mismo...
-
Colaboro en las comunidades online ayudando a la gente en la medida que puedo, y también escribo en varios blogs y alguna publicación. Eso me permite transmitir la pasión que siento por el desarrollo de software y hace que me sienta muy bien, o como gritaba el bueno de Sean 'el jefe' "I feel goooooood!".
- He fundado el primer grupo de usuarios de .NET en el país, y la iniciativa funciona muy bien. De hecho es posible que muy pronto tengamos que buscar una sala con más capacidad.
Soy en esencia feliz, de modo que ¿cuál es el problema?, ¿por que demonios nos pasamos la vida intentando que las cosas vayan cómo queramos, y no nos sentamos a disfrutar de ello?
Creo que el problema es el tiempo, o más bien la falta de él (¡vaya, acabo de descubrir la sopa de ajo!). Hoy en día no tenemos tiempo para nada. Ni para pasar con los seres queridos, ni para dedicarlo a nuestras aficiones ni para muchas otras cosas ¡solamente pensar en la cantidad de cosas que tenéis apartadas, a la espera de tener más tiempo!
Y hasta ahora, paradójicamente mi forma de conseguir más tiempo ha sido trabajar más para intentar en un futuro cercano no tener que trabajar tanto. O dicho de otro modo, trabajar como un burro ahora con la esperanza no tener que hacerlo en el futuro y poder vivir la vida. Magnífica filosofía de mierda, verdad? Pues creo que hoy en día la seguimos unos cuantos...
¡Pues ya me he cansado! A partir de ahora renuncio a dedicar más tiempo al trabajo que a las cosas que más me importan. De modo que he decidido cancelar algunos proyectos que tenía en marcha, y a partir de ahora dedicarme a pasar más tiempo con mi familia y no embarcarme en más proyectos de esta envergadura. Eso no significa que deje de hacer la mayoría de las cosas que hacía hasta ahora (como contribuir con las comunidades, porque para mí son muy importantes), pero sí que he tomado la decisión de no comprometerme con más proyectos faraónicos. De esos que minan la salud física y mental, y que prometen toda clase de recompensas en un futuro, pero hacen que te olvides del presente.
También he decidido cambiar algunas otras cosillas, cómo por ejemplo volver a hacer algo de ejercicio, algo que últimamente tenía bastante olvidado y alguna más que no contaré aquí por que no es el sitio adecuado, jejeje...
Así que si tenéis la suerte de disponer de algunos días libres, haceros la gran pregunta y tratad de ser honrados con vosotros mismos. Tal vez os sirva de algo como a mi...
Ahora seguiré con la serie de acceder al directorio activo desde .NET, pero sin prisas. Tal vez mañana...
this.Close();
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
 Creo que me estoy aficionando a las series de posts no de la tele, ya que acabo de terminar la serie de artículos acerca de cómo acceder a la caché de Internet Explorer y ya estoy planteándome una nueva, sobre acceder al directorio activo mediante una aplicación realizada con C#. Esta serie, al igual que la anterior intentará ser lo más directa y práctica posible, y del mismo modo al final de la serie publicaré el código completo del ejemplo para su descarga. El motivo... ...de esta serie es porque tanto en los foros como en los grupos de notícias, es muy común encontrar preguntas muy variadas acerca de cómo acceder a LDAP desde una aplicación .NET. Así que me he planteado empezar una serie de posts en los que mostraremos varios ejemplos: Mostrar información del usuario actual de Windows, averiguar los grupos a los que pertenece, validar credenciales contra un dominio para saber si son correctas, impersonar nuestra aplicación para que se ejecute con las credenciales de otro usuario, buscar usuarios o grupos en LDAP, extraer la lista de propiedades del objeto usuario, etc. ¿LDAP o Directorio Activo? Antes de empezar quiero hacer una aclaración: ¿Es lo mismo LDAP que Directorio Activo? No, no es lo mismo. LDAP es el acrónimo de (Lightweight Directory Access Protocol) que es es un protocolo a nivel de aplicación que permite el acceso a un servicio de directorio ordenado y distribuido para buscar diversa información en un entorno de red. Habitualmente se utiliza para acceder a la información almacenada de usuarios, grupos y equipos de una organizació y existen muchas implementaciones de este protocolo, desde Microsoft hasta Novell pasando por Red Hat, iPlanet u OpenLDAP. El directorio Activo o AD es la implementación de LDAP realizada por Microsoft en su família Windows Server. Al igual que LDAP permite acceder a distintos tipos de objetos almacenados que representan los elementos de la organización. Cada uno de estos objetos tendrá atributos que permiten identificarlos en modo unívoco (por ejemplo, los usuarios tendrán campo "nombre", campo "email", etc..., las impresoras de red tendrán campo "nombre", campo "fabricante", campo "modelo", campo "usuarios que pueden acceder", etc). Toda esta información queda almacenada en Active Directory replicándose de forma automática entre todos los servidores que controlan el acceso al dominio. Situaciones cotidianas Nosotros los desarrolladores, como creadores de aplicaciones que deben coexistir en un entorno corporativo, cada vez nos encontramos en más ocasiones en las que nuestra aplicación debe utilizar los usuarios y grupos del AD de la empresa, en lugar de almacenar una base de datos propia de usuarios y grupos. Incluso me atrevería a decir que la frontera entre una aplicación madura, de uso corporativo, y que se integre con otras aplicaciones y servicios, a veces estriba en detalles como éste. Hoy en día cada vez más empresas disponen de la figura del administrador del AD, que gestiona todos los datos de los empleados de la misma, de modo que ¿para que van a mantener otra base de datos con los usuarios de una aplicación, si éstos ya existen en el AD? Incluso puede ser peor ¿os imagináis cuántas aplicaciones funcionan de este modo? ¿Debemos mantener X bases de datos de usuarios por X aplicaciones? Esto puede ser el caos... ¡imaginaos la de datos duplicados que existen y lo difícil que resulta mantenerlos! Gracias al .NET framework, hoy en día podemos integrar nuestras aplicaciones con el AD de la empresa, de forma que podamos aprovechar la ventaja de contar con un repositorio centralizado. De este modo podremos dejar en manos del administrador del AD la creación de usuarios, grupos y cómo se relacionan entre ellos, y nosotros encargarnos de lo que realimente nos importa: La aplicación. En el próximo post empezaremos a construir nuestra aplicación de ejemplo, y para ello contaremos con la ayuda del namespace System.Security.Principal y de System.DirectoryServices... hasta entonces!
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
Éste es el último post de esta serie, en la cual se ha desarrollado un proyecto de ejemplo de cómo acceder a la caché de archivos temporales de Internet Explorer. De hecho, he aprovechado la excusa para montar un pequeño proyecto de ejemplo en el que poder enseñar varias cosas que tenía en mente y por falta de tiempo no podía postear. ASí pues en éste ejercicio hemos mostrado entre otras cosas cómo: - Utilizar el API para acceder a los archivos temporales de Internet (post 1)
- Persistir objetos .NET en ficheros XML mediante serialización (post 2)
- Impersonar, para ejecutar temporalmente muestra aplicación con las credenciales de otro usuario (post 3)
- Crear y distribuir nuestra aplicación como un servicio de Windows (post 4)
Y aquí os dejo el código completo del ejemplo: Espero que os guste,
** crossposting desde el blog de Lluís Franco en geeks.ms **
|
-
 En los dos primeros artículos pudimos ver los objetos del API de Windows que íbamos a usar para poder acceder a la caché de los archivos temporales de Internet, cómo persistir estos datos en formato XML, y finalmente cómo permitir que temporalmente nuestra aplicacación se ejecute con las credenciales de otro usuario, para poder realizar una serie de acciones que de otro modo no podría efectuar por falta de privilegios. Siguiendo con el objetivo de este ejercicio hoy vamos a encapsular la lógica de negocio de nuestra aplicación en forma de servicio de Windows, y éste va a encargarse de realizar una consulta a la caché de Internet de nuestro ordenador cada X tiempo (configurable mediante un fichero XML). Lo primero de todo va a ser construir la base de nuestro servicio mediante un proyecto de tipo Windows Service. Esta plantilla nos genera un proyecto con un componente de tipo ServiceBase, que servirá para ir construyendo nuestro pequeño juguetito. A continuación vamos a cambiar el nombre al servicio, en nuestro caso lo llamaremos "IECacheQueryService". Y posteriormente estableceremos a True los valores de las propiedades CanPauseAndContinue y CanShutdown, para poder pausar y detener nuestro servicio en tiempo de ejecución. Importante: Comprobar que el nombre sel servicio se ha cambiado correctamente en el punto de entrada de la aplicación (si no fuese así tendremos que modificarlo manualmente): static class Program { static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new IECacheQueryService() }; ServiceBase.Run(ServicesToRun); } }
Implementando funcionalidad al servicio:
De momento el servicio será capaz de iniciarse, pero no realizará nada. Ahora debemos dotarlo de funcionalidad, y para ello vamos a crear un temporizador que se encargue de realizar una tarea cada X tiempo (por defecto una hora). Éste lo crearemos como un miembro dentro de nuestra clase:
public partial class IECacheQueryService : ServiceBase { private Timer clock = new Timer();
Y lo usaremos desde el constructor de la misma, así como en los eventos OnStart y OnStop. Observar que en el constructor lo inicializamos con un valor que proviene del fichero de configuración del proyecto (propiedades del proyecto/settings) llamado TimerInterval y se ha establecido a un valor de 3.600.000 (1 hora en milisegundos).
public IECacheQueryService() { InitializeComponent(); clock = new Timer(Properties.Settings.Default.TimerInterval); clock.Elapsed += new ElapsedEventHandler(clock_Elapsed); clock.Enabled = true; //... } protected override void OnStart(string[] args) { ExecuteQuery(); clock.Start(); //... } protected override void OnStop() { clock.Stop(); }
Del mismo modo también especificamos el manejador de evento asociado que se ejecutará cada vez que se cumpla este intervalo de tiempo (clock_Elapsed). Éste será el corazón de nuestro servicio y será el encargado de invocar la consulta a la caché de IE:
void clock_Elapsed(object sender, ElapsedEventArgs e) { try { ExecuteQuery(); } catch (Exception ex) { appEventLog.WriteEntry("Exception: " + ex.Message, EventLogEntryType.Error); } }
Simple verdad? Ahora vamos a construir este método ExecuteQuery a apartir de las piezas que vimos en anteriores entradas de la misma serie. No os preocupeis que en el último post estará un enlace al código completo del ejemplo (incluido el instalable).
Que hace exactamente este método?
- Primero de todo crea un objeto de tipo StopWatch para medir con precisión el tiempo que transcurre en la ejecución del mismo.
- Llama al método getResults que se encarga de efectuar la consulta y devolver un objeto que es una lista genérica de entradas de la caché.
- Construye el nombre de fichero en el que guardaremos los resultados y llama al método saveResults, encargado de realizar la suplantación de identidad y serializar los resultados en el fichero antes mencionado.
private void ExecuteQuery() { try { Stopwatch watch = new Stopwatch(); watch.Start(); List<IECacheEntry> results = getResults( Properties.Settings.Default.SearchPattern); string filename = string.Format("{0}{1}_{2}.xml", Properties.Settings.Default.TargetPathLocation, Environment.MachineName, DateTime.Now.ToString("ddMMyyyy_hhmm")); watch.Stop(); TimeSpan ts = watch.Elapsed; saveResults(results, filename); appEventLog.WriteEntry(string.Format( "Query executed successfully at {0} in '{1}' by user '{2}'. Elapsed time (ms): {3}", DateTime.Now.ToString(), Environment.MachineName, WindowsIdentity.GetCurrent().Name,ts.Milliseconds)); } catch (Exception ex) | |
|