Convertir una DLL de nuevo en un proyecto compilable con Glass.NET
Leer C# decompilado en una ventana es una cosa; obtener un .csproj que puedes abrir, grepear, refactorizar y compilar es otra. Aquí está cómo la exportación de proyecto de Glass.NET reconstruye un ensamblado entero —fuente, referencias, recursos—, qué maneja limpiamente, dónde el código generado por el compilador necesita una mano, y cómo scriptarlo desde la CLI.
Un decompilador que solo te muestra código en un panel te mantiene de turista. Puedes mirar, puedes desplazarte, pero no puedes trabajar. En el momento en que quieres grepear un ensamblado por cada llamada a File.Delete, correr un analizador estático sobre él, poner un punto de ruptura en una reproducción local, o refactorizar una biblioteca perdida para devolverla a su forma, necesitas la cosa en disco como un proyecto real: un .csproj que tu cadena de herramientas entienda. Ese salto, de «una ventana llena de C#» a «una solución que puedo abrir», es para lo que sirve la exportación de proyecto de Glass.NET.
Este artículo es una inmersión práctica en esa exportación: qué reconstruye Glass, cómo manejarla tanto desde la GUI como la CLI, qué compila limpiamente, dónde aparecen los límites honestos de la decompilación, y cómo cerrar la brecha.
De un panel de solo lectura a un proyecto en disco
Abre un ensamblado en Glass y obtienes C# decompilado, navegación, y una vista de información de ensamblado: todo lo que necesitas para leerlo. La exportación convierte esa reconstrucción en archivos:
Un proyecto, no un volcado: el .csproj lleva el framework de destino y las referencias de ensamblado que Glass leyó de los metadatos, los espacios de nombres se vuelven una disposición sensata de archivos/carpetas, y los recursos embebidos se extraen junto a ellos. Abre la carpeta en cualquier IDE y tus herramientas normales —búsqueda, ir-a-definición, analizadores, el compilador— vuelven a estar sobre la mesa.
Las dos formas de exportar
Desde la GUI, carga el ensamblado y elige File ▸ Export to Project. Glass escribe el .csproj y los archivos .cs reconstruidos (más los recursos extraídos) a la carpeta que elijas. Este es el camino correcto cuando estás explorando: has navegado el ensamblado, sabes que es el que quieres, y te gustaría tenerlo en tu editor.
Desde la CLI, el subcomando glass export hace lo mismo sin interfaz, que es lo que quieres en un script, un lote sobre muchos archivos, o un pipeline de análisis:
glass export MyLibrary.dll --output ./MyLibrary.Source
Eso escribe un proyecto compilable bajo ./MyLibrary.Source. Y como es un comando simple, puedes distribuirlo en abanico: recupera una carpeta de ensamblados huérfanos en una sola pasada:
for dll in ./legacy-bin/*.dll; do
name=$(basename "$dll" .dll)
glass export "$dll" --output "./recovered/$name"
done
Y como Glass nunca ejecuta el ensamblado —es estrictamente análisis estático sobre metadatos e IL— exportar un binario no confiable o sospechoso es seguro. Obtienes la fuente en disco para grepear sin que el binario se ejecute jamás, que es precisamente la situación en la que más la quieres: auditar algo en lo que no confías lo suficiente como para ejecutarlo.
Qué vuelve limpiamente
Para una amplia clase de ensamblados reales, la exportación compila con poco o ningún problema, porque el motor de decompilación moderno maneja las construcciones que solían producir basura:
- La lógica de negocio ordinaria —clases, interfaces, genéricos, propiedades, eventos, LINQ— se reconstruye fielmente.
- El C# moderno que el motor entiende —máquinas de estado
async/await, bloques iteradores (yield), coincidencia de patrones y expresiones switch, records, lambdas y clausuras— vuelve como la construcción de alto nivel, no como la fontanería generada en bruto. El motor reconoce la rebaja del compilador y la revierte. - Las referencias y el targeting de framework se llevan al
.csproj, así que el proyecto sabe contra qué está compilando. - Los recursos embebidos se escriben fuera y se conectan, así que una biblioteca que distribuye cadenas respaldadas por
.resxo blobs binarios las conserva.
Para una pequeña biblioteca de utilidad o un único ensamblado cuya fuente perdiste, «exportar, abrir, compilar» frecuentemente simplemente funciona.
Dónde aparecen los límites honestos de la decompilación
La exportación es reconstrucción, no viaje en el tiempo, y vale la pena ser franco sobre qué preserva el IL y qué no. El IL codifica el comportamiento exactamente; no codifica cada detalle a nivel de fuente, así que algunas cosas se reconstruyen en lugar de recuperarse:
- Los nombres de variables locales suelen desaparecer (el IL identifica los locales por ranura, no por nombre), así que verás nombres reconstruidos. Los campos, métodos, tipos y parámetros conservan sus nombres a menos que el ensamblado fuera ofuscado.
- Algunas construcciones generadas por el compilador se reconstruyen como C# válido-pero-feo, y el patrón exótico ocasional no volverá a fuente compilable sin un empujón.
- El código
unsafe, las firmas P/Invoke, y cierta interoperación pueden necesitar que elAllowUnsafeBlocksdel proyecto se active o un retoque manual. - Las referencias faltantes: si el ensamblado depende de algo que no tienes, la exportación puede reconstruir los sitios de llamada pero no puede conjurar la dependencia; la suministras antes de que la compilación se ponga verde.
- La entrada ofuscada es el caso más difícil: si los nombres fueron mutilados por un ofuscador, Glass reproduce fielmente los nombres mutilados: decompila lo que hay, no des-ofusca.
Así que la expectativa realista para un ensamblado grande o inusual es: Glass te consigue un proyecto y la vasta mayoría de la fuente; cerrar el último puñado de errores de compilación es una breve pasada manual dirigida. Eso sigue siendo una transformación: de «solo puedo mirar esto en un visor» a «tengo un proyecto con el que toda mi cadena de herramientas puede trabajar».
Por qué un proyecto le gana a un panel
Una vez que el ensamblado es un .csproj, todo lo que ya sabes hacer vuelve:
- Grep y análisis estático. Busca en la fuente reconstruida las API que importan —cada
Process.Start, cada llamada de reflexión, cada sumidero de red— y apunta analizadores de Roslyn o tus propias reglas a ella. Esta es la columna vertebral de auditar una dependencia de la que no estás seguro: exporta, luego lee sistemáticamente las partes que pueden hacer daño. - Una reproducción local. ¿Recuperaste una biblioteca cuya fuente se perdió? El proyecto exportado te deja compilarla, referenciarla y —donde las referencias resuelven— depurar una reproducción en lugar de adivinar desde una traza de pila.
- Comparar entre versiones. Exporta dos compilaciones del mismo ensamblado y compara los árboles para ver exactamente qué cambió entre versiones: útil cuando una subida de dependencia te rompió y el changelog no lo explicó. (Glass también ofrece una comparación de ensamblados en la app con un diff de líneas para la versión rápida.)
- Refactorizar de vuelta a un estado mantenible. Para código genuinamente perdido, un proyecto exportado es el punto de partida para renombrar los locales reconstruidos, re-añadir docs XML, y devolver a la vida una biblioteca muerta.
Dónde encaja
La exportación de proyecto es el paso que convierte Glass.NET de un visor en un banco de trabajo. Lee un ensamblado con el modelo de navegación, confirma que es el que quieres con la vista de información de ensamblado, luego File ▸ Export to Project —o scriptea glass export MyLibrary.dll --output ./src— para obtener un .csproj que tu cadena de herramientas entienda. Espera una compilación limpia para ensamblados directos y una breve pasada manual para grandes o inusuales; espera la fuente en disco de cualquier modo, sin ejecutar jamás el binario. Consulta las guías de primeros pasos y navegación para el flujo de lectura que lleva a una exportación, o la página de producto de Glass.NET para el conjunto completo de herramientas. Es gratis: sin licencia, sin puestos, sin registro.
Prueba Nebula.NET
Endurece tu código .NET en minutos — empieza con la edición gratuita.