[VS2005] Sandcastle – October 2007 Community Technology Preview (CTP)

 

Buenas

SandCastle sigue evolucionando, y este mes tenemos un nuevo CTP que no arregla todos los bugs que posee presenta las siguientes novedades:

  • Reflection data files
    The reflection files (generated from .net framework 3.5, vs2005 style) are included in the installer. After installation, they can be found under “%DxRoot%Datareflection”. In build_sandcastle.bat and build.proj, we have commented out the call to fxReflection.proj.
  • Conceptual example
    A conceptual example is located at “DxRootExamplesconceptual”. To build it, please run the following command line commands.
    Cd c:program filessandcastleexamplesconceptual
    Build_conceptual.bat
  • Conceptual configs
    conceptual.config is added for conceptual build in each presentation style. The path is “Vs2005(/hana/prototype)configurationconceptual.config”.
  • VS 2005 style sheet
    The old Whidbey style sheet is now available at “DxRootpresentationvs2005stylewhidbypresentation.css”. To use it, please copy it to “DxRootpresentationvs2005style” and overwrite the existing css. Before doing this, you may want to backup that css file first.
  • Conceptual Authoring schemas
    The schema files under “DxRootschemasAuthoring” are schemas for conceptual authoring. The root schema is developer.xsd. The conceptual sample xml can be found at “DxRootExamplesconceptualdduexml”.
  • Reflection schema
    The MrefBuilder reflection schema file is available under “DxRootschemasReflection” folder.
  • Firefox support
    we fixed many bugs to make the produced html files compatible with  the latest firefox browser.

 

Descarga: http://www.microsoft.com/downloads/details.aspx?FamilyId=E82EA71D-DA89-42EE-A715-696E3A4873B2&displaylang=en

Update: si quieres una interfaz gráfica para la generación y configuracion de SandCastle, puedes echarle un vistazo a http://www.codeproject.com/dotnet/SandcastleBuilder.asp

 

Saludos @ La Finca

El Bruno

Crossposting from ElBruno.com

[TFS] Team System Web Access y el error TF10128

Buenas

si trabajas mucho con Team Foundation Server seguramente el error TF10128 será familiar.

TF10128: The path {0} contains more than the allowed 260 characters. Type or select a shorter path.

La primera vez que me encontré con este error, fué en la configuración de unos builds automáticos que tenían un path extremadamente complejo. Después de esto aprendí la lección y comencé a guiarme por la regla del <= 260.

Nota: en Microsoft Visual Studio 2008 y el nuevo Build Server las cosas han mejorado mucho, con los diferentes Workspaces que podemos configurar para cada proyecto de Build. Mas información aquí.

 

Hace unos días me volví a encontrar con el mismo error pero esta vez utilizando Team System Web Access cuando trataba de acceder a un documento almacenado en un Team Project.

 

Team System Web Access utiliza un path temporal para almacenar en un caché el contenido de los documentos. La ubicación de este path se puede modificar desde el archivo de configuración de Team System Web Access, usualmente ubicado en:

..Program FilesMicrosoft Visual Studio 2005 Team System Web AccessWebweb.config

Dentro del mismo la configuración por defecto para el directorio de cache suele ser dentro del mismo path de instalacion de Team System Web Access:

<webAccessSettings> <!-- Directory path where cache is stored. --> <localCache path="C:Program FilesMicrosoft Visual Studio 2005 Team System Web AccessCache" /> ... </webAccessSettings>

Por lo que si queremos “ganar” un poco de espacio lo podemos cambiar por un path más corto:

<webAccessSettings> <!-- Directory path where cache is stored. --> <localCache path="D:TSWACache" /> ... </webAccessSettings>

asignamos los permisos necesarios sobre la nueva ubicación, reiniciamos el IIS y listo !!!

 

 

Saludos

El Bruno

Crossposting from ElBruno.com

[VS2008] Workaround para las VPCs de VS2008 con expiracion

Microsoft Visual Studio 2008 Beta 2

 

Buenas

hace un par de días comenté que las máquinas virtuales de Microsoft Visual Studio 2008 disponibles para descargar desde MSDN expiran el 1ro de Noviembre y para los que estamos probando con las mismas esto puede suponer un problema.

Nuevamente Jeff en su blog, nos comenta la solución para este “problema” (http://blogs.msdn.com/jeffbe/archive/2007/10/27/update-on-expiring-vs2008-beta2-vpcs.aspx)

Básicamente consiste en actualizar la licencia de Windows 2003 Server que posee la máquina virtual con una licencia válida. Si tienes una suscripción MSDN, y dispones de licencias disponibles puedes solucionar este problema rápidamente 😀

Otra opción es esperar durante la semana, ya que nuestros amigos de MSDN tienen pensado liberar nuevas versiones de las VPCs con Microsoft Visual Studio 2008.

Fuente: http://blogs.msdn.com/jeffbe/archive/2007/10/27/update-on-expiring-vs2008-beta2-vpcs.aspx

 

Saludos

El Bruno

Crossposting from ElBruno.com

El Bruno vs Status Reports

Buenas

¿cuantas veces has tenido que invertir tiempo, en generar informes para justificar el tiempo que has invertido en un proyecto?; en mi caso, esta situación se repite constantemente; y yo estoy en contra de la generación de status reports (aka: informes de estado)

Más de uno se preguntará ¿porqué?; pues porque creo que si para gestionar un proyecto utilizamos las herramientas adecuadas, no es necesario invertir tiempo en crear informes de estado, éstos se deben crear “automáticamente”.

 

Si utilizas Visual Studio Team System y Team Foundation Server, puedes aprovechar las diferentes herramientas que posee internamente para agilizar la gestión del proyecto:

Además si instalas Team System Web Access Power Tool, le explicas a los usuarios como utilizarlo; todos los usuarios (que posean los permisos necesarios) podrán conocer en todo momento el estado de cada una de las tareas del proyecto y además podrán tener una visión general del mismo.

 

Asi que, si tu jefe te obliga a invertir eternas horas en cerrar estados de situación para un proyecto; tomate una hora y explícale que existen herramientas que además de permitir generar automáticamente los Status Reports, le ayudarán a poder controlar el ciclo de vida de un proyecto.

Nota: explícale además que como a los informes los puede exportar a Microsoft Excel, luego los puede modificar y pintar como mejor le parezca. Ya sé que esto no es lo mas aconsejable, ya que miente un poco con respecto a la realidad; pero parece que es un requisito INDISPENSABLE para que los jefes de proyecto se animen con Team System … cosas de la relacion cliente – consultor que no apoyo para nada.

 

 

Saludos cerrando el finde @ Madrid

El Bruno

Crossposting from ElBruno.com

[VS2008] Demo VPC rest in peace (a partir del 01/11)

Microsoft Visual Studio 2008 Beta 2

 

Buenas

si como yo, utilizas las VPC con Microsoft Visual Studio 2008 Beta 2 que están disponibles para su descarga en el MSDN, debes tener cuidado. Las mismas quedarán INHABILITADAS A PARTIR DEL 1 DE NOVIEMBRE.

Esto nos comenta Jeff en su blog y obviamente la recomendación es comenzar a sacar de las mismas toda la información que necesitemos resguardar.

Una vez más: fecha de desactivación 1ro Noviembre.

Fuente: http://blogs.msdn.com/jeffbe/archive/2007/10/25/vs2008-beta2-vpcs-expiring-prematurely.aspx

 

Saludos @ Madrid

El Bruno

Crossposting from ElBruno.com

[TFS] WareHouseControllerRun Console Application (refresca el DataWareHouse de TFS desde una aplicacion de Consola)

Buenas

hace un tiempo comenté como forzar la actualización de los datos de la base de datos de DataWareHouse de Team Foundation Server a través de uno de los WebServices que expone TFS. Si bien el proceso de actualización puede ser configurado para que sea manejado por uno de los servicios de Team Foundation Server, existen ocasiones donde es necesario forzar la actualización de estos datos.

Si like me estás cansado de invocar manualmente este WebService, puedes crear una pequeña aplicación de Consola que se encargue de este trabajo. He aquí el código de la misma:

Module1.vb

1 Module Module1 2 3 Sub Main() 4 5 Try 6 7 ' define TFS webservice url 8 DefineTfsWebServiceUrl() 9 10 Dim svc As New TFS01.ControllerService 11 12 ' use current credential for webservice calls 13 svc.UseDefaultCredentials = True 14 15 ' start update process 16 Console.WriteLine(String.Empty) : Console.WriteLine(String.Empty) 17 Console.WriteLine("{0} Start Datawarehouse update Process", Now.ToString()) 18 If svc.Run() Then 19 ' get tfs warehouse status until datawarehouse is processed 20 GetWareHouseStatus(svc) 21 Console.WriteLine(String.Empty) : Console.WriteLine(String.Empty) 22 Console.WriteLine("{0} Datawarehouse updated !!!", Now.ToString()) 23 End If 24 25 Catch ex As Exception 26 Console.WriteLine(ex.ToString) 27 End Try 28 29 ' close program 30 Console.WriteLine("Press RETURN to close this program") 31 Console.ReadLine() 32 33 End Sub 34 35 36 ''' <summary> 37 ''' Defines the TFS web service URL. 38 ''' </summary> 39 Private Sub DefineTfsWebServiceUrl() 40 Dim url As String = My.MySettings.Default.TFS01_WareHouseControllerRun_tfs01_ControllerService 41 42 ' define TFS Url 43 Dim msg As String = String.Format("Use the following Url: {0} [Y/N]?", url) 44 Console.WriteLine(msg) 45 46 Dim k As ConsoleKeyInfo = Console.ReadKey() 47 If k.Key = ConsoleKey.N Then 48 Console.WriteLine("Enter TFS App Webservices Url:") 49 url = Console.ReadLine() 50 My.Settings.TFS01_WareHouseControllerRun_tfs01_ControllerService = url 51 My.Settings.Save() 52 End If 53 End Sub 54 55 ''' <summary> 56 ''' Gets the ware house status. 57 ''' </summary> 58 ''' <param name="svc">The SVC.</param> 59 Private Sub GetWareHouseStatus(ByVal svc As TFS01.ControllerService) ' DO NOT DO THIS !!! 60 System.Threading.Thread.Sleep(1000) 61 62 Dim res As TFS01.WarehouseStatus 63 res = svc.GetWarehouseStatus() 64 Do Until res = TFS01.WarehouseStatus.Idle 65 Console.WriteLine("{0} status: {1}", Now.ToString(), res) 66 ' DO NOT DO THIS !!!! 67 System.Threading.Thread.Sleep(1000) 68 res = svc.GetWarehouseStatus() 69 Loop 70 End Sub 71 72 End Module 73

Esta app posee una pequeña función para configurar la url del servidor (línea 39) y otra función para refrescar el estado del proceso de actualización (línea 59) y de esta manera conocer cuando se ha terminado de actualizar los datos en el servidor de Team Foundation Server. Un ejemplo de la salida de la consola es el siguiente:

 

y entre refresco y refresco, podremos ver la evolución de nuestros productos como en la siguiente imagen:

 

 

 

Proyecto de ejemplo: http://geeks.ms/files/folders/elbruno/entry45030.aspx

 

Saludos @ La Finca

El Bruno

Crossposting from ElBruno.com

[DSL] IsolatedStorageException: "Unable to determine the identity of domain."

 

Buenas

un post un post un poco espeso sobre un error más espeso aún con el que tuve que lidiar durante un par de semanas.

Introducción

Resulta que cuando realizas operaciones dentro del IDE de Visual Studio 2005 que necesiten trabajar con un IsolatedStorage te encuentras con una excepción del tipo IsolatedStorageException:

System.IO.IsolatedStorage.IsolatedStorageException occurred Message="Unable to determine the identity of domain." Source="mscorlib" StackTrace: at System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, Object& oNormalized) at System.IO.IsolatedStorage.IsolatedStorage.GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, String& typeName, String& instanceName) at System.IO.IsolatedStorage.IsolatedStorage._InitStore(IsolatedStorageScope scope, Evidence domainEv, Type domainEvidenceType, Evidence assemEv, Type assemblyEvidenceType, Evidence appEv, Type appEvidenceType) at System.IO.IsolatedStorage.IsolatedStorage.InitStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType) at System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType) at System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain() at ElBruno.Dsl20.IsolatedStorageHelper.GetIsolatedStorageMaxiumSixe()

Y seguramente, más de uno se preguntará ¿para que quiero trabajar con un IsolatedStorage?; pues un ejemplo puede ser el tratamiento de strings con un StreamWriter, porque cuando el tamaño del mismo en memoria sobrepasa cierto tamaño comienza a “bajar a disco” para realizar algunas operaciones. Es en este momento, cuando internamente el Framework solicita permisos para la creación de un IsolatedStorageFile y las operaciones se realizan en el ámbito del mismo.

 

Problema

Pero desde el IDE de Visual Studio, el escenario se complica un poco. Porque, por ejemplo, cuando ejecutas tu aplicacion en el Visual Studio Experimental Hive, el System.AppDomain principal del IDE no tiene identidad. Ya se que esto parece imposible, pero la siguiente imagen vale mas que mil cervezas lo muestra clarito:

 

Es por esto que frente a cualquier tipo de acción utilizando un IsolatedStorage, la exception “Unable to determine the identity of domain.” es lanzada.

 

Solución

Hace un tiempo, posteé este problema en los foros de Extensibilidad ed Visual Studio, pero después de verlo con la gente de Microsoft, no tuve respuesta. Así que me puse a estudiar un poco y encontré un workaround más que obvio para solucionar este problema:

¡¡¡ Ejecuta tus acciones en otro AppDomain con los permisos y evidencias necesarios !!!

He aquí un ejemplo para demostrar como solucionarlo. El siguiente DSL posee una validación en la clase ExampleModel.partial.cs; que cuando es invocada, muestra el tamaño por defecto para un IsolatedStorage para el usuario actual. Para esto se vale de una clase IsolatedStorageHelper con el siguiente código dentro de la misma.

Nota: sobre las validaciones y las Domain Specific Language Tools pueden leer mi anterior post aquí

IsolatedStorageHelper.cs

1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.IO.IsolatedStorage; 5 using System.IO; 6 7 namespace ElBruno.Dsl20 8 { 9 public class IsolatedStorageHelper : MarshalByRefObject 10 { 11 /// <summary> 12 /// Gets the isolated storage maxium sixe. 13 /// </summary> 14 /// <returns></returns> 15 public double GetIsolatedStorageMaxiumSixe() 16 { 17 IsolatedStorageFile isoFile; 18 isoFile = IsolatedStorageFile.GetUserStoreForDomain(); 19 20 // Open or create a writable file. 21 IsolatedStorageFileStream isoStream = 22 new IsolatedStorageFileStream(GetTemporalFileName(), 23 FileMode.OpenOrCreate, 24 FileAccess.Write, 25 isoFile); 26 27 StreamWriter writer = new StreamWriter(isoStream); 28 writer.WriteLine(Guid.NewGuid().ToString()); 29 30 // Calculate the amount of space used to record the user's preferences. 31 double d = isoFile.CurrentSize / isoFile.MaximumSize; 32 Console.WriteLine("CurrentSize = " + isoFile.CurrentSize.ToString()); 33 Console.WriteLine("MaximumSize = " + isoFile.MaximumSize.ToString()); 34 35 // StreamWriter.Close implicitly closes isoStream. 36 writer.Close(); 37 isoFile.Dispose(); 38 isoFile.Close(); 39 return d; 40 } 41 42 /// <summary> 43 /// Gets the name of the temporal file. 44 /// </summary> 45 /// <returns></returns> 46 private static string GetTemporalFileName() 47 { 48 string tempFile = string.Format("temp{0}.xml", Guid.NewGuid().ToString()); 49 RemoveFileIfExists(tempFile); 50 return tempFile; 51 } 52 53 /// <summary> 54 /// Removes the file if exists. 55 /// </summary> 56 /// <param name="outputFile">The output file.</param> 57 private static void RemoveFileIfExists(string outputFile) 58 { 59 if (System.IO.File.Exists(outputFile)) 60 { 61 System.IO.File.Delete(outputFile); 62 } 63 } 64 } 65 } 66

Dentro de una clase personalizada que he agregado a mi proyecto DSL, ejecuto la función GetIsolatedStorageMaxiumSixe() y muestro el resultado al usuario. Sin embargo si creo la clase IsolatedStorageHelper  de manera convencional, obtengo la excepcion mencionada.

helper = new IsolatedStorageHelper(); isolatedStorageMaxiumSixe = helper.GetIsolatedStorageMaxiumSixe();

Es por esto que he implementado la creación de la clase en un nuevo System.AppDomain como muestran las líneas 43 a 74 en el código de la clase que implementa la validación para el diagrama creado con las Domain Specific Language Tools:

ExampleModel.partial.cs

1 using Microsoft.VisualStudio.Modeling.Validation; 2 using System.IO.IsolatedStorage; 3 using System.IO; 4 using System; 5 using System.Threading; 6 using System.Security.Principal; 7 using System.Security.Permissions; 8 using System.Runtime.InteropServices; 9 using System.Reflection; 10 using System.Security.Policy; 11 using System.Security; 12 using System.Windows.Forms; 13 14 namespace ElBruno.Dsl20 15 { 16 17 [ValidationState(ValidationState.Enabled)] 18 public partial class ExampleModel 19 { 20 21 /// <summary> 22 /// Validates the duplicated users E mail. 23 /// </summary> 24 /// <param name="context">The context.</param> 25 [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)] 26 [System.Security.SecurityTreatAsSafe()] 27 [System.Security.SuppressUnmanagedCodeSecurity()] 28 private void ValidateDuplicatedUsersEMail(ValidationContext context) 29 { 30 try 31 { 32 // defines the name and type for the assembly creation 33 string assemblyName = Assembly.GetExecutingAssembly().FullName; 34 string typeName = "ElBruno.Dsl20.IsolatedStorageHelper"; 35 36 // validate user preferences 37 DialogResult res = System.Windows.Forms.MessageBox.Show("Execute IsolatedStorage in new AppDomain ??", "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); 38 IsolatedStorageHelper helper = null; 39 double isolatedStorageMaxiumSixe = 0; 40 41 if (res == DialogResult.Yes) 42 { 43 // --------------------------------------------------------------- 44 // Create and execute assembly in new AppDomain 45 // --------------------------------------------------------------- 46 47 // Set up the AppDomainSetup 48 AppDomainSetup setup = new AppDomainSetup(); 49 setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory.ToString(); 50 SecurityZone zone = SecurityZone.MyComputer; 51 52 // Set up the Evidence 53 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 54 Evidence evidence = new Evidence(baseEvidence); 55 evidence.AddAssembly(assemblyName); 56 evidence.AddHost(new Zone(zone)); 57 58 AppDomain app = AppDomain.CreateDomain("Processor AppDomain", evidence, setup); 59 60 try 61 { 62 63 helper = (IsolatedStorageHelper)app.CreateInstanceAndUnwrap(assemblyName, typeName); 64 isolatedStorageMaxiumSixe = helper.GetIsolatedStorageMaxiumSixe(); 65 66 } 67 catch 68 { 69 throw; 70 } 71 finally 72 { 73 AppDomain.Unload(app); 74 } 75 } 76 else 77 { 78 // --------------------------------------------------------------- 79 // Create and execute assembly in Visual Studio IDE AppDomain 80 // --------------------------------------------------------------- 81 helper = new IsolatedStorageHelper(); 82 isolatedStorageMaxiumSixe = helper.GetIsolatedStorageMaxiumSixe(); 83 } 84 85 // display result 86 MessageBox.Show(string.Format("Isolated Storage Maxium Sixe: {0}", isolatedStorageMaxiumSixe.ToString())); 87 88 } 89 catch (Exception ex) 90 { 91 System.Windows.Forms.MessageBox.Show(ex.ToString()); 92 } 93 } 94 } 95 }

Cuando ejecutamos el DSL y presionamos la opción Validate sobre el menú contextual en nuestro diagrama, veremos el siguiente diálogo de confirmación:

 

Si seleccionamos NO y nuestra clase se instancia dentro del mismo System.AppDomain que el que esta utilizando Visual Studio, veremos que se dispara la excepción IsolatedStorageException:

 

Si en cambio, instanciamos nuestra clase dentro de un nuevo System.AppDomain con los privilegios necesarios, la ejecución irá de maravillas y podremos festejar con unas cañas:

 

Si alguien está interesado en adentrarse un poco más en el tema, puede bajar el proyecto de ejemplo desde aquí (gracias Geeks.ms) y si encuentra algun otro workaround o más información al respecto y quiere compartirla, me avisa 😀

Descarga: http://geeks.ms/files/folders/elbruno/entry44654.aspx

 

Saludos @ La Finca

El Bruno

Crossposting from ElBruno.com

[TFS] MsBuild Profiler (para buils fast and furious …)

Buenas,

MsBuild Profiler es una herramienta que permite medir el rendimiento para las secuencias de comandos de un proyecto MSBuild. El analizador de MSBuild muestra un resultado en forma gráfica de rendimiento para todas las secuencias de comandos de MSBuild, esto permite optimizar y ajustar los tiempos de las secuencias internas para un proyecto de Build.

Página Principal: http://www.codeplex.com/msbuildprofiler

Descarga: http://www.codeplex.com/msbuildprofiler/Release/ProjectReleases.aspx?ReleaseId=7848

 

Saludos @ Home

El Bruno

Crossposting from ElBruno.com

[Off-Topic] Gracias PUMAS !!!

Buenas,

mi país es un territorio donde la principal pasión es el futbol. Sin embargo cada tanto, surge un grupo de personas que se destacan en otro deporte, y nos brindan una alegría que es muy díficil de explicar.

La selección Argentina de Rugby (Los Pumas) es un claro ejemplo de trabajo como un equipo ha trabajado y madurado durante casi 8 años, y ha cerrado este ciclo con un resultado impresionante; un 3er puesto en el mundial de Rugby; algo que hace sólo un par de años hubiese sido un insulto para las grandes potencias mundiales de Rugby.

No muchos pueden decir, que han quedado en un escalafon superior a los All Blacks, o a los Wallabys, o que han ganado 2 veces a la selección “de casa”. Pero lo que más valoro (como rescató el amigo Martín) es que este equipo siempre fue fiel a sus principios, siempre se mantuvo unido y destacó por la garra y por el corazon con el que jugaron cada partido.

Para muchos argentinos, ayer terminó el mundial de Rugby (aunque hoy se juegue la final Sudáfrica-Inglaterra); pero al igual que paso hace unos años con la selección de basquet, fue el comienzo de una nueva generación y una nueva pasión para disfrutar.

Gracias Pumas por un mes INOLVIDABLE 😀

 

Saludos @ Paris

El Bruno

Crossposting from ElBruno.com

[TFS] Como consultar la cantidad de lineas de codigo por developer ??? (sirve para competencias internas)

Buenas

siguiendo con la linea de posts para analizar datos almacenados en Team Foundation Server, hoy como es viernes crearé un Excel con el que puedes competir con tus compañeros para verificar quien:

  • es el que más líneas de código ha agregado
  • es el que más líneas de código ha modificado
  • es el que más líneas de código ha eliminado

Este informe es muy simple, y tomando de base los pasos iniciales para conectarse desde Excel 2007 a nuestro servidor de datos Team Foundation Server DataWarehouse (como comenté aquí), agregaremos los siguientes fields:

  • Seccion Values
    • Code Churn // Lines Added
    • Code Churn // Lines Deleted
    • Code Churn // Lines Modified
  • Row Labels
    • Checked In By // Person
  • Column Labels
    • Team Project // Team Project

como muestra la siguiente imagen

 

A partir de este momento podremos ver, la cantidad de líneas de código agregadas, eliminadas y modificadas por developer y por Team Project; además de los totales generales (que son los que valen para el concurso por un par de cañas).

 

Si además deseas agregar un filtro por fecha, simplemente debemos agregar el field Date // Date a la seccion Column Labels y ya tendremos un gráfico por día o por período para controlar estos valores.

 

 

Saludos @ La Finca

El Bruno

 

PD: la diferencia de cantidad de líneas de código a “mi nombre” se debe a que este servidor de Team Foundation Server ha sido alimentado a partir de una base de datos de Visual Source Safe y todos los items e históricos se han agregado a mi nombre.

Crossposting from ElBruno.com