Este artículo nació de una charla informal sobre «hasta dónde se puede llamar binario único a algo en Windows». La publicación que lo originó es la siguiente. Aunque se omita esta parte, el resto está escrito para poder leerse de forma independiente.
En Windows, «si es posible, nos gustaría distribuirlo en un solo archivo» es una petición bastante habitual. Para herramientas internas, herramientas de integración con equipos, terminales de monitorización, entornos sin conexión y sitios que quieren evitar en lo posible el uso de instaladores, convertir la app en un binario único resulta muy atractivo.
Sin embargo, si no se separa este tema desde el principio, la conversación suele dejar de tener sentido a mitad de camino. Esto se debe a que, en Windows, «queremos un binario único» tiende a mezclar en realidad cuatro cuestiones distintas.
- Queremos un único paquete de distribución
- Queremos no tener que preinstalar los runtimes de .NET o Visual C++
- Queremos que funcione con solo colocarlo, sin instalador ni permisos de administrador
- No queremos depender de las diferencias entre versiones del Windows de destino
Estas cuatro cosas no son lo mismo. En la práctica, la forma de pensarlo que menos se desvía es esta.
Reducir el paquete de distribución a un solo EXE es bastante posible. Pero eliminar por completo la dependencia del Windows de destino no lo es.
En este artículo organizamos esa línea divisoria pensando en el trabajo práctico con apps de Windows.
1. Conclusión inicial
Si resumimos solo la conclusión al principio, es esta.
- Con un EXE de escritorio normal, se puede llevar la conversión a binario único bastante lejos
- Sin embargo, poder reducirlo a 1 EXE y no depender del Windows de destino son cosas distintas
- En las extensiones de shell, los servicios de Windows, los controladores, WebView2 y una parte de WinUI 3, lo importante suele ser menos el número de archivos y más qué se registra en el SO y qué se da por sentado
- Lo más importante en la práctica es decidir por separado si lo que se busca es el binario único, prescindir del instalador o reducir la dependencia del SO
Dicho de otro modo, la línea divisoria en Windows queda así.
- Reducir el paquete de distribución a uno solo: bastante posible
- Incluir runtimes adicionales: bastante posible
- Acercarse a la distribución por xcopy: depende del tipo de app
- Eliminar la dependencia del lado del Windows de destino: imposible
1.1 Terminología usada en este artículo
Antes de continuar, organizamos aquí los términos que aparecerán repetidamente más adelante.
| Término | Lectura o expansión | Significado en este artículo |
|---|---|---|
| UCRT | Universal C Runtime | Parte de la biblioteca C estándar que resultó de dividir el runtime de C en Visual Studio 2015. Desde Windows 10 en adelante se incluye como componente del propio SO |
| Paquete redistribuible de VC++ | Visual C++ Redistributable | Instalador para incluir en el equipo de destino las DLL del runtime de Visual C++ distintas de UCRT |
| framework-dependent | Distribución que depende del .NET del entorno de destino | Forma de distribución que da por sentado que el equipo de destino ya tiene instalado el runtime de .NET |
| self-contained | Runtime de .NET incluido | Forma de distribución en la que la propia app incluye el conjunto completo del runtime de .NET |
| single-file | Publicación en archivo único | Opción de publicación de .NET que reúne el paquete de distribución en un solo EXE |
| Native AOT | Native Ahead-Of-Time | Forma de distribución que precompila el IL a código nativo en el momento de la publicación. No usa JIT en tiempo de ejecución |
| Distribución app-local | Distribución adyacente a la app | Forma de distribución en la que las DLL se colocan en la misma carpeta que el EXE y solo esa app las usa |
| Distribución xcopy | Distribución de solo copiar | Forma de distribución que funciona con solo colocar la carpeta, sin instalador ni permisos de administrador |
| SCM | Service Control Manager, administrador de control de servicios | Mecanismo del SO que gestiona el registro, inicio y detención de los servicios de Windows |
| UAC | User Account Control, control de cuentas de usuario | Mecanismo de seguridad de Windows que controla la elevación a permisos de administrador |
| Extensión de shell | Extensión de shell | Componente COM que se carga y se ejecuta dentro de procesos como el Explorador |
| Evergreen | Modo de actualización continua | Modo de distribución que deja el WebView2 Runtime a cargo de una única copia compartida que se actualiza automáticamente |
| Fixed Version | Modo de versión fija | Modo de distribución que incluye una versión específica del WebView2 Runtime junto con la propia app |
| arch | architecture, arquitectura de CPU | Se refiere a x86, x64 o Arm64 |
2. Cuatro niveles para pensar el binario único
Si primero representamos los niveles en un diagrama, queda así. La dificultad aumenta de abajo hacia arriba, y el nivel superior no se puede alcanzar en Windows.
flowchart BT
accTitle: Niveles de la conversión a binario único en Windows
accDescr: Muestra los cuatro niveles, desde tener un solo paquete de distribución hasta no depender del Windows de destino, indicando cuáles son alcanzables y cuál no
A["Nivel A: el paquete de distribución es uno solo<br/>Bastante posible"]
B["Nivel B: no hace falta preinstalar el runtime del lenguaje<br/>Bastante posible"]
C["Nivel C: no hace falta instalación ni registro<br/>Depende del tipo de app"]
D["Nivel D: no depende del Windows de destino<br/>Inalcanzable en Windows"]
A --> B
B --> C
C --> D
El trabajo necesario cambia por completo según a cuál de estos cuatro niveles se refiera realmente la frase «queremos un binario único».
2.1 Nivel A: el paquete de distribución es uno solo
Este es el aspecto más superficial.
- Se puede enviar por correo como un único archivo
- Basta con colocar un archivo en un USB
- En el destino de instalación solo queda
app.exe
Esto se refiere a la unidad de distribución tal como se ve. En la práctica, aunque se descomprima temporalmente al iniciarse o dependa de DLL del propio SO, esta condición por sí sola se puede cumplir.
2.2 Nivel B: no hace falta preinstalar el runtime del lenguaje
El siguiente nivel es el estado en el que la app funciona sin necesidad de instalar de antemano el runtime de .NET o el paquete redistribuible de VC++ en la máquina de destino.
- Enlace estático de C/C++
- self-contained de .NET
- single-file de .NET
- Native AOT de .NET
En este nivel, la sensación de «poder llevarlo de forma autónoma» se vuelve mucho más fuerte.
2.3 Nivel C: no hace falta instalación ni registro
A partir de aquí la dificultad aumenta de golpe.
Un EXE simple a veces funciona con solo colocarlo. Pero los siguientes casos son distintos.
- Extensiones de shell
- Servicios de Windows
- Esquemas de URL personalizados o asociaciones de archivos
- Controladores
- Componentes que se cargan en otros procesos, como el Explorador o Office
En este terreno no basta con colocar el archivo. Hace falta registro por parte del SO y conexión con el host.
2.4 Nivel D: no depender del Windows de destino
Esto es imposible en Windows.
Se debe a que una app de Windows termina ejecutándose sobre las API de Windows, el cargador, el modelo de seguridad y la pila de dispositivos. La conversión a binario único solo llega hasta el ámbito de responsabilidad de la propia app. No implica llevarse consigo el propio SO.
3. Áreas donde resulta bastante fácil reducirlo a un solo EXE
También en Windows hay apps relativamente fáciles de reducir a un solo EXE.
- Herramientas de escritorio que se ejecutan de forma independiente
- Apps de negocio en las que el propio EXE contiene la interfaz y el procesamiento
- Herramientas de comunicación, procesamiento de archivos, recopilación de registros, monitorización o control de equipos
- Apps que no necesitan integración con hosts como el Explorador o Office
- Interfaces que no dan por sentado un runtime web
En este tipo de apps hay muchos elementos fáciles de incluir en el propio cuerpo de la aplicación.
- Código propio
- Recursos
- El manifiesto
- La configuración predeterminada
- Datos de plantilla
- Algunas bibliotecas de terceros
- El propio runtime del lenguaje
Además, aunque no se incorporen por completo las DLL dentro del EXE, la distribución app-local, que coloca las DLL junto al EXE, es una opción habitual y sólida en Windows. En la práctica,
- Un único
app.exe - O
app.exemás varias DLL adyacentes - Pero sin necesidad de instalador ni de permisos de administrador, distribuible por xcopy
No es raro que esta forma resulte más fácil de mantener que comprimirlo todo a la fuerza en un solo EXE.
4. Dependencias de Windows que no desaparecen aunque sea un solo EXE
Si se piensa que «con un solo EXE ya no se depende del Windows de destino», aquí es donde se produce el error. En realidad, incluso reduciéndolo a 1 EXE quedan dependencias.
4.1 Dependencia de la versión del SO
Cada API de Windows tiene su propio SO mínimo compatible. También existen diferencias entre x64 y Arm64. Es decir, incluso con un único EXE,
- si debe funcionar hasta Windows 10
- si se da por sentado Windows 11
- si también debe funcionar en Windows Server
- a cuál de x86, x64 o Arm64 se dirige
son decisiones que hay que fijar desde el principio.
4.2 Dependencia de las DLL del sistema
Aunque uno crea haberlo reducido a 1 EXE, en tiempo de ejecución, como es natural, se siguen usando componentes proporcionados por el SO.
kernel32.dlluser32.dlladvapi32.dll- La infraestructura COM
- La infraestructura de control de servicios
Todo esto forma parte del ámbito de responsabilidad de Windows.
4.3 Dependencia del modelo de seguridad
- UAC
- Las ACL de archivos
- El administrador de control de servicios
- El registro
- La directiva de firma de controladores
La app no puede hacerse cargo de todo esto por sí sola.
4.4 Dependencia del host o del runtime
Si el diseño no consiste en un EXE independiente, sino que se apoya en algún host, las dependencias aumentan de golpe.
- Usar WebView2: hace falta el WebView2 Runtime
- Usar WinUI 3 / Windows App SDK: hace falta organizar el modo de distribución
- Crear una extensión de shell: hace falta registrarla en el Explorador
En definitiva, la elección de la interfaz o de la integración se traduce a menudo directamente en la dificultad de la distribución.
5. Puntos de equilibrio realistas según la tecnología
5.1 C/C++ nativo
El C/C++ nativo está del lado con mayor libertad para la conversión a binario único. Existe margen para elegir el enlace estático, y si se trata de un EXE independiente, resulta bastante fácil acercarse a ese objetivo.
Sin embargo, más que meterlo todo por la fuerza en un solo archivo,
- qué hacer con UCRT o con el runtime de VC++
- si colocar las DLL de terceros como app-local
- hasta qué punto limitar la CPU y el SO de destino
es lo que resulta más importante en la práctica.
Punto de partida: la diferencia entre /MT y /MD
En MSVC, lo que decide en la práctica si se incluye o no el runtime es esta opción del compilador.
| Opción | Qué se enlaza | Qué se necesita en el equipo de destino |
|---|---|---|
/MD |
Las bibliotecas de importación para DLL ucrt.lib y vcruntime.lib. En tiempo de ejecución se usan ucrtbase.dll y vcruntime<versión>.dll |
UCRT y el runtime de VC++ |
/MT |
Enlace estático de libucrt.lib, libvcruntime.lib y libcmt.lib |
Ningún runtime adicional |
La forma mínima de probarlo es esta, desde el Developer Command Prompt.
cl /std:c++17 /EHsc /O2 /MT app.cpp /Fe:app.exe
Aquí hay tres puntos que conviene tener en cuenta.
- UCRT pasó a ser un componente de Windows cuando el runtime de C se dividió en Visual Studio 2015, y desde Windows 10 en adelante se incluye como parte del SO. Si se apunta a versiones de Windows anteriores, hace falta redistribuirlo mediante
vcredist. - No se recomienda compilar el lado de la DLL con
/MT. Como el CRT enlazado estáticamente mantiene su estado confinado dentro de esa misma DLL, la reserva de memoria, la configuración regional y el comportamiento de_set_se_translatorquedan desalineados entre el EXE y la DLL. Si se uniforma sin más criterio «el EXE en/MT, la DLL incluida también en/MT», se producen errores al reservar y liberar memoria a través de ese límite. /clry/MTno se pueden usar juntos. Si se mezcla C++/CLI, hay que optar por/MD.
5.2 .NET
.NET cuenta con single-file, self-contained y Native AOT, por lo que la unidad de distribución visible se puede reducir bastante.
Sin embargo, es necesario distinguir entre ellos.
- framework-dependent: depende del .NET del entorno de destino
- self-contained: incluye el runtime de .NET
- single-file: reúne el paquete de distribución en uno solo
- Native AOT: reduce aún más las dependencias en el arranque, pero también impone restricciones de funcionalidad
No es que «al ser single-file, se reduzca la dependencia del SO». Lo que se reduce es, principalmente, la dispersión del paquete de distribución de la app.
Punto de partida: los 3 patrones de dotnet publish
Si primero se quiere ejecutar y ver las diferencias, estos tres comandos son suficientes.
rem 1. framework-dependent + single-file: se necesita el runtime de .NET en el equipo de destino
dotnet publish -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true
rem 2. self-contained + single-file: incluye el runtime de .NET
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true
rem 3. Native AOT: publicar después de escribir PublishAot en el csproj
dotnet publish -c Release -r win-x64
La recomendación oficial es escribir PublishSingleFile y PublishAot en el csproj en lugar de en la línea de comandos, porque así se activa el análisis de compatibilidad durante la compilación y se reducen los errores que solo se detectan después de publicar.
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<PublishAot>true</PublishAot>
</PropertyGroup>
Tenga en cuenta que, si especifica RuntimeIdentifier, SelfContained pasa a ser true de forma predeterminada. Si desea framework-dependent, especifique explícitamente --self-contained false. Para publicar Native AOT en Windows hace falta la carga de trabajo Desarrollo para el escritorio con C++ de Visual Studio.
La contrapartida: reducirlo a uno solo no sale gratis
Si aquí solo se escribiera lo que «se puede hacer», se correría el riesgo de un error, así que enumeramos también la contrapartida.
El despliegue en tiempo de arranque de single-file
- De forma predeterminada, solo se empaquetan las DLL administradas. Se cargan en memoria al iniciarse y no se extraen a una carpeta. Los binarios nativos del propio runtime permanecen como archivos separados.
- Si además desea incluir los binarios nativos en el único archivo, use
IncludeNativeLibrariesForSelfExtract; si desea extraer todo el contenido antes de ejecutarse, useIncludeAllContentForSelfExtract. En ambos casos el comportamiento pasa a ser «extraer y después iniciar», y en Windows se extrae bajo%TEMP%\.net. ConDOTNET_BUNDLE_EXTRACT_BASE_DIRse puede cambiar la ubicación, pero no la convierta en un lugar en el que puedan escribir usuarios o servicios con permisos distintos. - Si activa
EnableCompressionInSingleFile, el EXE se vuelve bastante más pequeño, pero el arranque se ralentiza porque el contenido se descomprime en memoria al iniciarse. La propia documentación oficial indica que hay que medir tanto el tamaño como el coste de arranque antes de usarlo. El impacto varía mucho según la app.
Incompatibilidades de API en single-file
Al reducir el paquete de distribución a uno solo, el código que da por sentada una ruta de archivo se rompe de forma silenciosa.
| API | Comportamiento en single-file |
|---|---|
Assembly.Location |
Devuelve una cadena vacía |
Assembly.CodeBase |
PlatformNotSupportedException |
Assembly.GetFile |
IOException |
Module.Name |
Devuelve la cadena <Unknown> |
Si necesita acceder a un archivo junto al EXE, recurra a AppContext.BaseDirectory; si necesita la ruta del ejecutable, use Environment.ProcessPath. Como algunas bibliotecas de terceros usan internamente estas API, tras convertir la app a single-file hace falta comprobar al menos una vez el arranque en una máquina real.
Restricciones de funcionalidad de Native AOT
A cambio de «arranque rápido y sin necesidad de runtime», deja de estar disponible lo siguiente.
- La carga dinámica, como
Assembly.LoadFile - La generación de código en tiempo de ejecución, como
System.Reflection.Emit - C++/CLI
- En Windows, el COM integrado (built-in COM interop)
- Como el trimming es obligatorio, también se heredan sus restricciones
- Al ser en esencia single-file, también se heredan las incompatibilidades de API mencionadas arriba
System.Linq.Expressionssiempre funciona en modo intérprete, por lo que resulta más lento que el código generado en tiempo de ejecución
La plataforma de destino también queda fijada de antemano. En .NET 8, Windows admite x64 y Arm64, y a partir de .NET 9 se añadió x86. La idea de «uno solo con AnyCPU» no es viable desde el principio.
5.3 WebView2
Al adoptar WebView2, la dificultad del binario único cambia por completo. Aquí el tema central no es el número de EXE, sino cómo tratar el WebView2 Runtime.
Antes de «¿se puede reducir a 1 EXE?», hay preguntas que conviene plantearse primero.
- Si se da por sentado que el runtime ya existe en el entorno
- Si se usa Evergreen
- Si se incluye una Fixed Version
- Hasta dónde asumir la responsabilidad en una distribución sin conexión
La diferencia entre Evergreen y Fixed Version es, a grandes rasgos, esta.
| Evergreen | Fixed Version | |
|---|---|---|
| Quién actualiza | Microsoft. Se actualiza automáticamente | Usted mismo. Se sustituye junto con las actualizaciones de la app |
| Instancia en el equipo | Una sola compartida por todas las apps | Incluida individualmente por cada app |
| Tamaño de distribución | Prácticamente no aumenta | Supera los 250 MB |
| Forma de instalación | El Bootstrapper pesa unos 2 MB y descarga lo necesario. Sin conexión, se incluye el Standalone Installer | Se distribuye el conjunto de binarios ya extraídos junto con la app |
| Restricciones existentes | Hay que comprobar antes del arranque si ya está instalado en el equipo | No se puede ejecutar desde una ruta de red ni desde una ruta UNC |
El Evergreen Runtime viene preinstalado como parte del SO en Windows 11. Sin embargo, todavía quedan equipos con Windows 10 que no lo tienen, por lo que la propia Microsoft recomienda que, aunque se elija Evergreen, conviene distribuir también el Runtime. Es decir, en cualquier caso hace falta un procedimiento en el que la app compruebe si está presente y lo instale si falta. Fixed Version, a cambio de «poder controlar uno mismo el momento de la actualización», añade varios cientos de MB al paquete de distribución. Al margen de la cuestión del EXE único, esto es algo que hay que decidir de antemano.
5.4 WinUI 3 / Windows App SDK
WinUI 3 también hace que los requisitos de distribución cambien en el momento en que se adopta. La elección de la tecnología de interfaz se convierte directamente en la elección del método de distribución.
En concreto, hay dos ejes que decidir.
- packaging: packaged (MSIX), packaged que apunta a una ubicación externa, o unpackaged
- runtime: framework-dependent o self-contained
Y, desde el punto de vista del binario único, lo que realmente importa es esta restricción de combinación.
PublishSingleFilesolo se puede usar en apps de WinUI 3 que sean unpackaged y self-contained a la vez, y requiere Windows App SDK 1.5 o posterior.- En las apps packaged, y en las packaged que apuntan a una ubicación externa, no se puede usar
PublishSingleFile. - Al pasar a unpackaged se pierde la package identity, por lo que dejan de estar disponibles las funciones de Windows que dan por sentada la package identity, como las notificaciones, las tareas en segundo plano, las asociaciones de archivos o las extensiones del menú contextual.
En definitiva, en WinUI 3, «reducirlo a 1 EXE» y «usar las funciones de extensión de Windows» chocan de frente. Si el binario único es la máxima prioridad, a menudo es más rápido revisar desde el principio la premisa de la tecnología de interfaz.
6. Áreas que por naturaleza requieren registro y dependencias
6.1 Extensiones de shell
Las extensiones de shell que se cargan en el Explorador son algo distinto de un simple «EXE que basta con colocar». Aquí lo importante no es el número de archivos, sino cómo se registran en el Explorador.
6.2 Servicios de Windows
Aunque el propio exe del servicio se pueda reducir a un solo archivo, la distribución es un problema distinto.
- El registro en el SCM
- Los permisos
- La cuenta de inicio
- La configuración de recuperación
son aspectos que hay que tener en cuenta. Es decir, en los servicios, el terreno que hay que trabajar a fondo es más «cómo instalarlo» que «reducirlo a 1 EXE».
6.3 Controladores (drivers)
En los controladores esto es todavía más claro. Solo se completan incluyendo el INF, la firma y el procedimiento de instalación, por lo que desde el principio les cuesta encajar en el terreno del binario único.
7. Tabla de decisión para uso práctico
Para hacerse una idea general, esta tabla resulta útil.
| Lo que se quiere crear | Grado de viabilidad de 1 EXE | Qué conviene decidir primero |
|---|---|---|
| Herramienta Win32/C++ independiente | Alto | Enlace estático, SO/arquitectura de destino |
| Herramienta WinForms/WPF independiente | Alto | Idoneidad de self-contained, single-file y Native AOT |
| App de WinUI 3 / Windows App SDK | Medio | Modo de distribución, dependencias adicionales |
| Interfaz de escritorio basada en WebView2 | Bajo a medio | Método de distribución del Runtime |
| Extensiones de clic derecho o vista previa del Explorador | Bajo | Registro de COM/registro del sistema |
| Servicio de Windows | Medio | Registro en el SCM, permisos, procedimiento de actualización |
| App con controlador incluido | Bajo | INF, firma, instalación |
Lo más importante de esta tabla es entender que el «número de binarios» y el «ámbito de responsabilidad de la distribución» son cosas distintas.
8. Qué decidir antes de diseñar la distribución
Si se quiere lograr con éxito la conversión a binario único, hay cosas que conviene decidir antes de la implementación.
8.1 Decidir qué es lo que se quiere reducir a uno solo
- Si se quiere un único paquete de distribución
- Si se quiere eliminar la preinstalación del runtime
- Si se quiere prescindir del instalador
- Si se quiere simplificar la actualización sin conexión
La tecnología que se elija depende de la respuesta a esto.
8.2 Fijar desde el principio la versión mínima de Windows y la arquitectura
Tanto single-file como Native AOT son, básicamente, específicos del SO y de la arquitectura. Si se avanza dejando esto ambiguo, con la idea de «en cualquier caso, un solo archivo», al final se atasca por falta de API o por incompatibilidades de runtime.
8.3 Documentar explícitamente qué se incluye y qué se deja a cargo de Windows
En la práctica, con solo redactar esta lista se reducen bastante los errores.
- Lo que se incluye en la app
- El exe principal
- Las DLL propias
- Las plantillas de configuración
- El runtime self-contained
- Lo que se deja a cargo de Windows
- Las DLL del sistema
- Las API del SO
- El SCM, el registro y el Explorador
- La infraestructura de controladores
- Lo que se da por sentado aparte
- WebView2 Runtime
- VC++ Redistributable
- Office/Excel
- Controladores específicos
8.4 Si el binario único es prioritario, reduzca la integración con el host
Esto tiene un efecto considerable.
- Prescindir de las extensiones de shell y usar un EXE normal
- No convertirlo en servicio, y recurrir al Programador de tareas o al inicio explícito
- Usar una interfaz nativa en lugar de WebView2
- Mantener COM confinado dentro del propio proceso
En definitiva, cuanto más se reduzca el diseño que hace que el SO «cargue» o «registre» algo, más cerca se estará del binario único.
9. Resumen
La conversión a binario único en Windows es posible hasta un punto considerable. Sin embargo, a lo que se llega al final es a esta frase.
Se puede reducir la app a un solo EXE. Pero no se puede reducir a un solo EXE el propio Windows del que esa app depende.
A continuación se enumeran cinco puntos que conviene recordar en especial.
- Con un EXE normal e independiente, se puede llevar bastante lejos la distribución en un solo archivo
- El enlace estático de C/C++, el single-file de .NET y Native AOT son opciones sólidas
- Sin embargo, la dependencia de la versión del SO, la arquitectura, las DLL del sistema y el modelo de seguridad no desaparece
- En las extensiones de shell, los servicios, los controladores, WebView2 y una parte de WinUI 3, lo central pasa a ser el registro en el SO o los runtimes adicionales
- El éxito del binario único depende de separar desde el principio «qué es lo que se quiere reducir a uno solo»
Si se da una prioridad muy alta al binario único, resulta muchísimo más fácil tener éxito si, ya desde la elección de la tecnología, se diseña reduciendo el grado de acoplamiento con el SO.
10. Referencias
- Microsoft Learn, Create a single file for application deployment
- Microsoft Learn, Native AOT deployment overview
- Microsoft Learn, C runtime (CRT) and C++ standard library (STL) lib files
- Microsoft Learn, Dynamic-link library search order
- Microsoft Learn, Targeting your application for Windows
- Microsoft Learn, Creating Registration-Free COM Objects
- Microsoft Learn, Registering Shell Extension Handlers
- Microsoft Learn, CreateServiceW function
- Microsoft Learn, Overview of INF Files
- Microsoft Learn, Windows driver signing tutorial
- Microsoft Learn, Distribute your app and the WebView2 Runtime
- Microsoft Learn, Windows App SDK deployment guide for self-contained apps
- Microsoft Learn, Package and deploy Windows apps overview
- Microsoft Learn, Packaging overview - Windows apps
- Microsoft Learn, Evergreen vs. fixed version of the WebView2 Runtime
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
Externalización y desarrollo por encargo de una app Windows: qué aclarar antes de solicitarlo
Antes de encargar la externalización o el desarrollo por encargo de una app Windows, estos son los puntos a aclarar: revisión de software...
¿Es WebView2 el siguiente paso tras el modo IE? — La restricción de que ActiveX no funciona y un diseño de migración realista
Explicamos la estructura básica de WebView2, la estrategia de distribución Evergreen y Fixed Version, la trampa de la carpeta de datos de...
¿Qué es ClickOnce? - Cómo funciona, actualizaciones y en qué casos conviene o no usarlo, desde la práctica
ClickOnce distribuye apps de escritorio Windows en .NET: manifiestos, actualizaciones, caché, firma y en qué casos conviene usarlo, con d...
Lista de verificación para manejar procesos secundarios de forma segura en aplicaciones de Windows
Para manejar procesos secundarios de forma segura en aplicaciones de Windows, la propiedad del árbol de procesos y el procedimiento de ci...
Proxy interno de la empresa y aplicaciones de Windows — cómo se resuelve el proxy en WinINET, WinHTTP y .NET
El navegador conecta, pero la app empresarial no atraviesa el proxy interno. La causa suele ser una discrepancia sobre qué configuración ...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Servicios relacionados con este tema
El artículo está directamente relacionado con los siguientes servicios.
Desarrollo de aplicaciones para Windows
En la distribución de apps de Windows conviene diseñar desde el principio la conversión a single-file, la inclusión del runtime, la decisión de adoptar WebView2 o WinUI y la conveniencia de convertir la app en servicio, para reducir los retrocesos posteriores.
Consultoría técnica y revisión de diseño
La petición de «queremos que quede en un solo EXE» resulta más fácil de decidir si se separan la unidad de distribución, la dependencia del SO, la necesidad de registro y la responsabilidad de las actualizaciones.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Se puede distribuir una app de Windows con un solo archivo EXE?
- Si se trata de una herramienta de escritorio que se ejecuta de forma independiente, es posible llegar bastante lejos. Con el enlace estático de C/C++, el self-contained o single-file de .NET, o Native AOT, se puede reducir el paquete de distribución a un único EXE. Sin embargo, poder empaquetarlo en un EXE y no depender del Windows de destino son cosas distintas: la dependencia de la versión del SO, la arquitectura, las DLL del sistema y el modelo de seguridad no desaparece.
- ¿El single-file de .NET elimina la dependencia del SO?
- No. Lo que reduce principalmente el single-file es la dispersión del paquete de distribución de la app, no la dependencia del SO. El framework-dependent depende del .NET instalado en el entorno de destino, el self-contained incluye el runtime de .NET, y Native AOT reduce aún más las dependencias en el arranque, aunque también impone restricciones de funcionalidad. Tanto single-file como Native AOT son, en esencia, específicos del SO y de la arquitectura, así que hay que fijar desde el principio la versión mínima de Windows compatible y la arquitectura.
- ¿Qué tipo de apps son difíciles de reducir a un solo EXE?
- Las extensiones de shell, los servicios de Windows, los controladores, las interfaces basadas en WebView2 y una parte de WinUI 3. En estos casos, lo importante no es el número de archivos, sino qué se registra en el SO y qué runtimes adicionales se necesitan. Por ejemplo, una extensión de shell necesita registrarse en el Explorador, un servicio requiere diseñar el registro en el SCM, los permisos y la cuenta de inicio, y un controlador solo se completa incluyendo el INF y la firma, por lo que no basta con distribuirlo simplemente colocando el archivo. Con WebView2 hay que decidir primero cómo se va a distribuir el WebView2 Runtime.
- ¿Hay una forma mejor de distribuir la app que forzarla dentro de un solo EXE?
- La distribución app-local, en la que las DLL se colocan junto al EXE, es una alternativa sólida. Aunque sea app.exe más varias DLL adyacentes, si se puede distribuir por xcopy sin necesidad de instalador ni de permisos de administrador, no es raro que resulte más fácil de mantener que comprimirlo todo a la fuerza en un solo EXE. Lo importante es separar desde el principio si lo que se quiere es un único paquete de distribución, eliminar la preinstalación del runtime, o prescindir del instalador.
Perfil del autor
Página de presentación del autor del artículo.
Go Komura
Representante de KomuraSoft LLC
Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.