Código fuente completo en C# (C Sharp) de .Net que comprueba si existe una versión concreta de UltraVNC instalada en un equipo. Si no existe la instala, si existe comprueba si es diferente, si lo es desinstala la actual e instala la nueva. Todo ello de forma silenciosa y transparente para el usuario. Sirve para automatizar la instalación/actualización de UltraVNC en equipos Windows. Permite también establecer los valores de configuración de UltraVNC: contraseña de acceso, mensaje de petición de acceso, etc.
- Requisitos e información para desarrollar aplicación de consola C# que instala/actualiza software automáticamente.
- Código fuente completo de la aplicación de consola en C# para instalar/actualizar UltraVNC.
- Ejecución y funcionamiento de aplicación C# de consola que instala/actualiza una aplicación automáticamente.
Requisitos e información para desarrollar aplicación de consola C# que instala/actualiza software automáticamente
Aunque la aplicación que describimos a continuación está diseñada específicamente para instalar/actualizar el software UltraVNC, también puede ser adaptada (con pequeñas modificaciones) para instalar cualquier otro software en un entorno Windows de forma automática y transparente para el usuario (silenciosa).
Necesitaremos disponer del IDE de desarrollo Microsoft Visual Studio .NET, en nuestro caso usamos la versión Community 2022. En el siguiente artículo explicamos cómo instalarla:
Esta aplicación de consola funcionará en sistemas operativos Windows. Por lo que dispondremos en nuestra organización de equipos Windows, al menos desde Windows XP en adelante, hasta Windows 10 y Windows 11. Y en equipo servidores Windows Server, desde Windows Server 2003 en adelante, hasta Windows Server 2019 y Windows Server 2022. Estos equipos necesitarán tener instalada la versión .NET Framework mínima que se use en el desarrollo de la aplicación de consola.
Para el caso de este script/ejecutable, dado que necesitará conocer de antemano la ruta donde se encuentre el instalador de UltraVNC (tanto en versión de 32bits como en versión de 64bits), así como los ficheros de configuración, contraseña y demás, necesitará tener estos ficheros en una carpeta compartida de un servidor de la red, que sea accesible (al menos de lectura), para todos los usuarios. En el ejemplo este servidor se llamará «servidorred» y la carpeta compartida donde se encuentran los instaladores y los ficheros de configuración será:
\\servidorred\infor\adm\VNC
Por otro lado, la aplicación almacenará en un fichero de log el resultado de su ejecución en cada equipo. Por ello, también se necesitará una carpeta compartida, con permisos de lectura/escritura, ubicada en algún servidor de la red. En este caso se coloca esta carpeta en:
\\servidorred\infor\adm\eventos\vnc\UltraVNC.csv
Los ficheros necesarios para que la aplicación de consola funcione serán:
- \\servidorred\infor\adm\VNC\UltraVNC_1_3_81_X64_Setup.exe: la aplicación comprobará si el equipo es de 32 bits o de 64 bits. Si es de 64 bits instalará su versión correspondiente, indicada en esta ruta.
- \\servidorred\infor\adm\VNC\UltraVNC_1_3_81_X86_Setup.exe: la aplicación comprobará si el equipo es de 32 bits o de 64 bits. Si es de 32 bits instalará su versión correspondiente, indicada en esta ruta.
- \\servidorred\infor\adm\VNC\UltraVNC.ini: fichero de configuración base de UltraVNC. La aplicación copiará este fichero de su carpeta origen (esta), a la destino donde se encuentre instalado UltraVNC, para dejar la misma configuración en todos los equipos.
- C:\Program Files\uvnc bvba\UltraVnc\UltraVNC.ini: ruta donde se encuentra el fichero de configuración de UltraVNC instalado en todos los equipos.
- \\servidorred\infor\adm\eventos\vnc\UltraVNC.csv: carpeta y fichero donde se guardarán los resultados de la ejecución de la aplicación en cada equipo.
- \\servidorred\infor\adm\VNC\filenameTIC: la aplicación permite identificar si un equipo es del departamento de Informática (TIC), en cuyo caso instalará tanto el server como el client de UltraVNC, copiando el fichero de configuración indicado aquí sólo para estos equipos.
- \\servidorred\infor\adm\VNC\filename: la aplicación permite identificar si un equipo es del departamento de Informática (TIC), este fichero lo copiará a los equipos que NO sean de Informática (TIC).
- EquiposTIC: variable donde se introduce el nombre de red (nombre DNS, hostname) de los equipos del departamento de Informática (TIC) en los que queramos que se intale tanto el server como el client de UltraVNC.
Código fuente completo de la aplicación de consola en C# para instalar/actualizar UltraVNC
Crearemos un proyecto de aplicación de consola con .Net Framework 4.8 (funciona con versiones inferiores de .NET Framework). Llamaremos al proyecto «InstalarUltraVNC». En primer lugar, crearemos una clase llamada EscribirLog.cs, nos servirá para guardar en fichero de log el resultado de la ejecución de cada comando, para depurar. Tendrá el siguiente código C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using System; using System.IO; namespace InstalarUltraVNC { class EscribirLog { public string mensajeLog { get; set; } public Boolean mostrarConsola { get; set; } //Constructor si se pasa el mensaje por parámetro en la creación de la clase public EscribirLog(string mensajeEnviar, Boolean mostrarConsola) { mensajeLog = mensajeEnviar; if (mostrarConsola) monstrarMensajeConsola(); escribirLineaFichero(); } //Constructor si se pasa el mensaje por setter tras la creación de la clase public EscribirLog() { if (mostrarConsola) monstrarMensajeConsola(); escribirLineaFichero(); } public void monstrarMensajeConsola() { //Quitar posibles saltos de línea del mensaje if ((mensajeLog != null) && (mensajeLog != "")) { mensajeLog = mensajeLog.Replace(Environment.NewLine, " | "); mensajeLog = mensajeLog.Replace("\r\n", " | ").Replace("\n", " | ").Replace("\r", " | "); Console.WriteLine(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss") + " " + mensajeLog); } } //Escribe el mensaje de la propiedad mensajeLog en un fichero en la carpeta del ejecutable public void escribirLineaFichero() { try { if ((mensajeLog != null) && (mensajeLog != "")) { FileStream fs = new FileStream(@AppDomain.CurrentDomain.BaseDirectory + "estado.log", FileMode.OpenOrCreate, FileAccess.Write); StreamWriter m_streamWriter = new StreamWriter(fs); m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); //Quitar posibles saltos de línea del mensaje mensajeLog = mensajeLog.Replace(Environment.NewLine, " | "); mensajeLog = mensajeLog.Replace("\r\n", " | ").Replace("\n", " | ").Replace("\r", " | "); m_streamWriter.WriteLine(DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss") + " " + mensajeLog); m_streamWriter.Flush(); m_streamWriter.Close(); } } catch { //Silenciosa } } } } |
En el fichero Program.cs añadiremos el siguiente código C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
using InstalarUltraVNC; using Microsoft.Win32; using System; using System.Diagnostics; using System.IO; using System.Net; using System.Text; namespace InstalarUltraVNCProyectoA { internal class Program { static void Main(string[] args) { // Mantiene actualizada UltraVNC a la última versión // Despliega el fichero de configuración por si se hace algún cambio UltraVNC.ini //Equipos de Informática para instalar Viewer y Server de VNC string[] EquiposTIC = { "PC1", "PC2", "PC3", "PC4", "PC5", "PC6" }; //Nueva versión a actualizar/Instalar de VNC string versionNueva = "1.3.8.1"; string versionInstalada = ""; //Ruta del instalador de VNC string rutaInstalador64Bits = @"\\servidorred\infor\adm\VNC\UltraVNC_1_3_81_X64_Setup.exe"; string rutaInstalador32Bits = @"\\servidorred\infor\adm\VNC\UltraVNC_1_3_81_X86_Setup.exe"; //Ruta del fichero de configuración INI de VNC string ficheroConfVNCOrigen = @"\\servidorred\infor\adm\VNC\UltraVNC.ini"; //Ruta destino del fichero de configuración (se copiará del origen al destino) string ficheroConfVNCDestino = @"C:\Program Files\uvnc bvba\UltraVnc\UltraVNC.ini"; //Ruta y fichero CSV con log de resultado string ficheroLogCSV = @"\\servidorred\infor\adm\eventos\vnc\UltraVNC.csv"; string configIntaladorTIC = @"\\servidorred\infor\adm\VNC\filenameTIC"; string configInstaladorCliente = @"\\servidorred\infor\adm\VNC\filename"; // Para instalar UltraVNC si ya existían versiones diferentes a $version o bien si no está instalado int instalar = 1; //Parámetros que se pasarán al instalador/desinstalador para hacerlo silencioso y otros menesteres string cmdArgumentos = ""; //Obtenemos arquitectura de equipo para instalar UltraVNC de 32 bits o de 64 bits bool es64bits= Environment.Is64BitOperatingSystem; bool depurar = true; bool depurarMostrarConsola = true; if (depurar) new EscribirLog("Se inicia InstalarUltraVNC.exe", depurarMostrarConsola); //Si el equipo es de 32 bits if (!es64bits) { if (depurar) new EscribirLog("Equipo de 32 bits", depurarMostrarConsola); // Desinstalar versión de 32 bits de UltraVNC si está instalada y es diferente a la nueva string strRegistro = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Ultravnc2_is1"; //Comprobamos si existe la versión, en caso de existir //una versión diferente a la nueva versión la desinstalamos RegistryKey claveRegistro = Registry.LocalMachine.OpenSubKey(strRegistro); RegistryKey aa = RegistryKey.OpenBaseKey(Registry.LocalMachine, RegistryView.Registry32()) string rutaDesinstalacion; if (claveRegistro != null) { Object valorRegistro = claveRegistro.GetValue("DisplayVersion"); if (valorRegistro != null) versionInstalada = valorRegistro.ToString(); else versionInstalada = ""; if (depurar) new EscribirLog("Versión instalada de 32 bits: " + versionInstalada, depurarMostrarConsola); valorRegistro = claveRegistro.GetValue("UninstallString"); if (valorRegistro != null) rutaDesinstalacion = valorRegistro.ToString(); else rutaDesinstalacion = ""; cmdArgumentos = "/verysilent /norestart"; //Desinstalamos si la versión instalada es diferente de la nueva if (File.Exists(rutaDesinstalacion) && versionInstalada != versionNueva) { if (depurar) new EscribirLog("Existe desinstalador y versión instalada diferente " + "de versión nueva, se ejecuta desinstalador", depurarMostrarConsola); try { ProcessStartInfo procesoLanzado = new ProcessStartInfo(); procesoLanzado.FileName = rutaDesinstalacion; procesoLanzado.Arguments = cmdArgumentos; procesoLanzado.ErrorDialog = false; procesoLanzado.WindowStyle = ProcessWindowStyle.Hidden; Process resultadoProceso = Process.Start(procesoLanzado); resultadoProceso.WaitForInputIdle(); resultadoProceso.WaitForExit(); //Para depurar Console.WriteLine("Ejecutado desinstalador con resultado: " + resultadoProceso.ExitCode.ToString()); } catch (Exception ex) { if (depurar) new EscribirLog("Error al ejecutar desinstalador: " + ex.Message, depurarMostrarConsola); } } if (versionInstalada == versionNueva) instalar = 0; } else instalar = 1; } else { if (depurar) new EscribirLog("Equipo de 64 bits", depurarMostrarConsola); // Desinstalar versión de 32 bits de UltraVNC si está instalada en equipo 64 bits string strRegistro = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Ultravnc2_is1"; RegistryKey claveRegistro = Registry.LocalMachine.OpenSubKey(strRegistro); string rutaDesinstalacion; if (claveRegistro != null) { if (depurar) new EscribirLog("Existe una versión de UltraVNC de " + "32 bits, se desinstalará", depurarMostrarConsola); Object valorRegistro = claveRegistro.GetValue("UninstallString"); if (valorRegistro != null) rutaDesinstalacion = valorRegistro.ToString(); else rutaDesinstalacion = ""; cmdArgumentos = "/verysilent /norestart"; if (File.Exists(rutaDesinstalacion)) { if (depurar) new EscribirLog("Desinstalando versión de 32 bits", depurarMostrarConsola); try { ProcessStartInfo procesoLanzado = new ProcessStartInfo(); procesoLanzado.FileName = rutaDesinstalacion; procesoLanzado.Arguments = cmdArgumentos; procesoLanzado.ErrorDialog = false; procesoLanzado.WindowStyle = ProcessWindowStyle.Hidden; Process resultadoProceso = Process.Start(procesoLanzado); resultadoProceso.WaitForInputIdle(); resultadoProceso.WaitForExit(); if (depurar) new EscribirLog("Ejecutado desinstalador de 32 bits con resultado: " + resultadoProceso.ExitCode.ToString(), depurarMostrarConsola); } catch (Exception ex) { if (depurar) new EscribirLog("Error al ejecutar desinstalador: " + ex.Message, depurarMostrarConsola); } } } // Desinstalar versión de 64 bits de UltraVNC si la versión no coincide con la nueva versión strRegistro = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Ultravnc2_is1"; claveRegistro = Registry.LocalMachine.OpenSubKey(strRegistro, false); if (claveRegistro != null) { Object valorRegistro = claveRegistro.GetValue("DisplayVersion"); if (valorRegistro != null) versionInstalada = valorRegistro.ToString(); else versionInstalada = ""; if (depurar) new EscribirLog("Versión instalada de 64 bits: " + versionInstalada, depurarMostrarConsola); valorRegistro = claveRegistro.GetValue("UninstallString"); if (valorRegistro != null) rutaDesinstalacion = valorRegistro.ToString(); else rutaDesinstalacion = ""; cmdArgumentos = "/verysilent /norestart"; if (versionInstalada == versionNueva) instalar = 0; //Si la versión instalada es diferente a la nueva, se desinstala if (File.Exists(rutaDesinstalacion) && (versionInstalada != versionNueva)) { if (depurar) new EscribirLog("Desinstalando versión de 64 bits", depurarMostrarConsola); try { ProcessStartInfo procesoLanzado = new ProcessStartInfo(); procesoLanzado.FileName = rutaDesinstalacion; procesoLanzado.Arguments = cmdArgumentos; procesoLanzado.ErrorDialog = false; procesoLanzado.WindowStyle = ProcessWindowStyle.Hidden; Process resultadoProceso = Process.Start(procesoLanzado); resultadoProceso.WaitForInputIdle(); resultadoProceso.WaitForExit(); if (depurar) new EscribirLog("Ejecutado desinstalador de 64 bits con resultado: " + resultadoProceso.ExitCode.ToString(), depurarMostrarConsola); } catch (Exception ex) { if (depurar) new EscribirLog("Error al ejecutar desinstalador: " + ex.Message, depurarMostrarConsola); } } } else instalar = 1; } //Copiar fichero de configuración UltraVNC.ini si el origen es más reciente if (File.Exists(ficheroConfVNCOrigen)) { bool reemplazarFichero = true; FileInfo fiOrigen = new FileInfo(ficheroConfVNCOrigen); var ultimaModificacionO = fiOrigen.LastWriteTime; //Si existe el fichero destino, comprobamos la fecha de modificación if (File.Exists(ficheroConfVNCDestino)) { FileInfo fiDestino = new FileInfo(ficheroConfVNCDestino); var ultimaModificacionD = fiDestino.LastWriteTime; if (ultimaModificacionO == ultimaModificacionD) reemplazarFichero = false; } if (reemplazarFichero) { //Si no existe la carpeta destino, se crea, dado que aún no se ha instalado VNC try { string carpetaDestino = Path.GetDirectoryName(ficheroConfVNCDestino); if (!Directory.Exists(carpetaDestino)) Directory.CreateDirectory(carpetaDestino); if (Directory.Exists(carpetaDestino)) { if (depurar) new EscribirLog("Copiando fichero de configuración " + "INI al ser de fecha diferente origen/destino", depurarMostrarConsola); File.Copy(ficheroConfVNCOrigen, ficheroConfVNCDestino, true); if (depurar) new EscribirLog("Copiado fichero de configuración INI", depurarMostrarConsola); } } catch (Exception ex) { if (depurar) new EscribirLog("Error al copiar fichero INI: " + ex.Message, depurarMostrarConsola); } } } //Instalar versión de UltraVNC if (instalar == 1) { if (depurar) new EscribirLog("Instalando UltraVNC", depurarMostrarConsola); //Obtenemos el nombre del equipo string nombrePC = Environment.MachineName; //En caso de no obtener el nombre del PC, se intenta con otros métodos if (nombrePC == "") { nombrePC = Dns.GetHostName(); if (nombrePC == "") nombrePC = Environment.GetEnvironmentVariable("COMPUTERNAME"); } //Si se ha podido obtener el nombre del PC continuamos if (nombrePC != "") { // Establecemos el fichero de configuración del instalador, // dependiendo de si se instala en equipos de TIC o en equipos normales //Comprobamos si el equipo está en el grupo de TIC if (Array.IndexOf(EquiposTIC, nombrePC) > -1) { cmdArgumentos = "/verysilent /norestart /loadinf=\"" + configIntaladorTIC + "\""; if (depurar) new EscribirLog("Equipo en grupo de TIC", depurarMostrarConsola); } else { cmdArgumentos = "/verysilent /norestart /loadinf=\"" + configInstaladorCliente + "\""; if (depurar) new EscribirLog("Equipo cliente normal (no en grupo de TIC)", depurarMostrarConsola); } //Instalamos UltraVNC con fichero de //configuración (para instalar Viewer y Server en TIC y Server en resto if (File.Exists(rutaInstalador64Bits)) { try { ProcessStartInfo procesoLanzado = new ProcessStartInfo(); if (es64bits) procesoLanzado.FileName = rutaInstalador64Bits; else procesoLanzado.FileName = rutaInstalador32Bits; procesoLanzado.Arguments = cmdArgumentos; procesoLanzado.ErrorDialog = false; procesoLanzado.WindowStyle = ProcessWindowStyle.Hidden; Process resultadoProceso = Process.Start(procesoLanzado); resultadoProceso.WaitForInputIdle(); resultadoProceso.WaitForExit(); if (depurar) new EscribirLog("Ejecutado instalador con resultado: " + resultadoProceso.ExitCode.ToString(), depurarMostrarConsola); //Guardamos el resultado en fichero CSV try { //Obtenemos la IP IPHostEntry ipsEquipo = Dns.GetHostEntry(nombrePC); string ipPC = ""; foreach (IPAddress ip in ipsEquipo.AddressList) { ipPC = ip.ToString(); } //Obtenemos el usuario string usuario = System.Security.Principal.WindowsIdentity.GetCurrent().Name; StringBuilder stringCSV = new StringBuilder(); string[] valoresCSV = new string[] {"\"" + DateTime.Now.ToString() + "\"", "\"" + nombrePC + "\"", "\"" + ipPC + "\"", "\"" + usuario + "\"", "\"" + versionNueva + "\"", "\"" + versionInstalada + "\"", "\"" + es64bits.ToString() + "\"", "\"" + resultadoProceso.ExitCode + "\""}; stringCSV.AppendLine(string.Join(";", valoresCSV)); if (!File.Exists(ficheroLogCSV)) File.WriteAllText(ficheroLogCSV, stringCSV.ToString()); else File.AppendAllText(ficheroLogCSV, stringCSV.ToString()); } catch (Exception ex) { if (depurar) new EscribirLog("Error al obtener IP, usuario y guardar en CSV: " + ex.Message, depurarMostrarConsola); } } catch (Exception ex) { if (depurar) new EscribirLog("Error al ejecutar instalador: " + ex.Message, depurarMostrarConsola); } } } else if (depurar) new EscribirLog("Nombre de equipo NO obtenido, no se instala UltraVNC", depurarMostrarConsola); } else if (depurar) new EscribirLog("No se instala porque ya hay una " + "versión igual a la nueva", depurarMostrarConsola); //Pausamos la aplicación para depurar y comprobar mensajes de consola //Console.WriteLine("Pulse cualquier tecla para salir..."); //Console.ReadKey(); } } } |
Ejecución y funcionamiento de aplicación C# de consola que instala/actualiza una aplicación automáticamente
Si queremos ejecutar la aplicación mediante directiva GPO, una vez compilada la aplicación C# y generado el .exe (InstalarUltraVNC.exe), lo copiaremos a alguna carpeta de algún servidor accesible por todos los usuarios. Habitualmente, los script de inicio de sesión de las directivas se suelen copiar a la carpeta:
\\dominio\SysVol\dominio\Policies{7497-42F-4B8F-8F9-71AA}\Machine\Scripts\Startup
Pero puede copiarse a la ubicación que se quiera, siempre y cuando los usuarios tengan, al menos, permisos de lectura.
Crearemos una directiva de grupo y agregaremos la ruta del ejecutable .exe de nuestra aplicación, para que se ejecute o bien en el inicio o bien incluso en el cierre de sesión:
Una vez creada la directiva, la asignaremos a un grupo de equipos (computers), dado que la hemos establecido en la rama «Configuración del equipo», para que se ejecute cuando el equipo se inicie.
La aplicación realizará lo siguiente en su inicio:
- Comprobará si el equipo es de 32 o de 64 bits. En función del resultado ejecutará el instalador de la versión de 32 bits o de 64 bits.
- En todos los casos, sea equipo de 32 o 64 bits, si existe una versión diferente a la indicada en versionNueva, la herramienta la desinstalará.
- Instalará la versión de 32 o 64 bits de UltraVNC que haya en la carpeta origen.
- Reemplazará el fichero de configuración del UltraVNC instalado por el de la carpeta origen.
- En el caso de que el nombre del equipo coincida con alguno de la variable EquiposTIC, además de instalar el Server, también instalará el Viewer. Para que los técnicos de Informática (TIC) puedan hacer control remoto al resto de equipos. Para este caso la aplicación reemplazará un fichero de configuración diferente del resto de equipos.
De esta forma siempre tendremos todos los equipos de la organización con la última versión de UltraVNC y todos tendrán la misma configuración.