Evitar multiples instancias de nuestra Aplicación

Hola a todos.
Espero que hayáis tenido unas buenas vacaciones LifeIfSoft.
Ya veo que se ha animado algo el foro y por eso quiero aportar algo en este comienzo de curso.

Seguro que alguna vez habéis tenido la necesidad de evitar que el Usuario arranque más de una vez la Aplicación Velneo y como no he encontrado nada en el foro, os cuento mi experiencia (solo válido para Windows).

El problema a resolver es el siguiente:

  • El Usuario dispone en el escritorio de un acceso directo (.lnk) apuntando a vClient.exe y con el parámetro de la ruta VATP correspondiente.
  • El Usuario arranca el acceso directo y minimiza la aplicación en la barra de Tareas.
  • El Usuario arranca de nuevo el acceso directo y en este caso la ventana de la Aplicación debe mostrarse en pantalla restaurando su posición y tamaño anteriores.

He contemplado 3 formas de controlar la Multi Instanciación de una Aplicación en la misma máquina.

1º - Tenemos una variable global en 3º plano APP_INSTANCIAS en la que en el PRE del Autoexec iremos guardando las máquinas que van haciendo conexión en el vServer. La información a guardar puede ser APP_SIGLAS + getClientIP(). En el PRE del autoexec comprobamos si existe APP_SIGLAS + getClientIP() en APP_INSTANCIAS y en caso afirmativo devolvemos 0 para salir de la Aplicación. En el OnClose de la Aplicación elimino la información en APP_INSTANCIAS.
Para activar la ventana de la Aplicación que está minimizada he recurrido a las DLL’s del API Win32 pero con Velneo y su pésima gestión de DLL’s he sido incapaz.

2º - La 1º opción tiene el problema de que si vClient se cierra anormalmente la variable global APP_INSTANCIAS en 3P quedaría con un valor inconsistente. Así que visto mi fracaso con la gestión de DLL’s de Velneo recurrí a una herramienta de Script que contemplara funciones de acceso al API de Windows. Dicha herramienta se llama AutoIt3 (https://www.autoitscript.com/site/autoit/). Solo tenemos que adjuntar el Runtime Autoit3.exe a nuestra aplicación y podremos ejecutar macros con mucha mayor potencia que con VBScript.

Para comprobar si la Aplicación ya está instanciada y activar la ventana, creamos un fichero activarventana.au3 con el siguiente código:


; Comprueba que existe la ventana y la Activa
if WinExists ( TITULO ) then
WinActivate ( TITULO )
else
; Devuelve 1 para indicar error
exit (1)
endif

TITULO es el título de la Ventana principal de nuestra Aplicación.

Usamos en el PRE del autoexec un proceso PRO_MULTI_SETUP que preguntará si nuestra Aplicación admite Multiinstanciación. Si la respuesta es negativa ejecutará la macro (sysCacheClientPath/AutoIt3.exe activarventana.au3) para probar si puede activar una ventana de la Aplicación instanciada. Si la macro tiene éxito cerramos la instancia actual (PRO_MULTI_SETUP retorna 0). Si la macro devuelve Error la ejecución del autoexec sigue normalmente.

3º - La 2º opción tiene una pequeña pega. Para comprobar la multi instanciación el usuario debe pasar siempre por el proceso de Login. Así que recurrimos a la 3º opción que consiste en comprobar si la Aplicación está activa antes de ejecutar vClient.exe.
Usamos también AutoIt3 (en este caso un exe con la macro compilada). Disponemos en una carpeta de lo siguiente:
1- El Script lanzador_velneo.au3 que compilamos como _lanzador_velneo.exe
2- Los accesos directos .LNK de nuestras Aplicaciones que ejecutan vClient.exe con el VATP de conexión
El ejecutable lanzador_velneo.exe recibe como parámetro el nombre del acceso directo .lnk (ejem: lanzador_velneo.exe 0PS_APP_2). Comprueba si la Aplicación está en ejecución. Si es así activa la ventana de la Aplicación y en caso contrario usa la función SHELLEXECUTE() para ejecutar el fichero .lnk pasado como parámetro.
Adjunto un ejemplo de lanzador_velneo.au3 que muestra esta técnica.
Este sistema es el que mejor resultados ha obtenido: disponemos de los accesos directos lnk originales y además las aplicaciones se instancian en la Barra de Tareas de forma independiente sin combinar los botones cuando esta opción está activada en Win7 o Win8.

Me imagino que esta cuestión de la Multi Instanciación la habréis resuelto de diversas formas y me gustaría conocer vuestras opciones.

Saludos
Paco Satué

1 me gusta

Como siempre el adjunto va después.

lanzador_velneo.zip (1.36 KB)

1 me gusta

Muchas gracias por tu aporte @seh , siempre dandonos cosas interesantes y útiles que probar y aplicar.

Buenos dias, Paco

Bienvenido a casa. Se te echaba de menos…

Saludos. Ramiro

Gracias por compartir, la verdad siempre he sido fan de autoit te saca de muchos apuros

Gracias por el aporte.

Y por qué no usar un vClien personalizado mediante QML?

De esta forma, al hacer click en el icono compruebas antes de nada si ya hay una instancia abierta. Si lo está la maximiza y sino ejecutas login

Hola mdelgado.

Sí, por supuesto, ya había pensado en esa posibilidad. Incluso estuve mirando la raquítica documentación que hay al respecto y obtuve algunas conclusiones positivas, véase http://velneo.es/foros/topic/cliente-offline-qml.

La verdad es que sin un buen editor/depurador de QML y mis nulos conocimientso de Qt/C++ prefiero esperar a que Velneo se ponga las pilas en este y otros temas. De momento soy más productivo con AutoIt3.

¡¡ Qué más quisiera yo que hubiera ya cientos de componentes QML en el mercado compatibles con Velneo !!

Para un experto en QML seguro que resolver este problema es muy sencillo. A ver si alguien se anima.

Saludos
Paco Satué

Hola Paco.

Me he encontrado este hilo, tratando de buscar una solución a la disponibilidad de conexiones al servidor en una red, para que un solo equipo solo consuma una, me he declinado por la opción 3 sugerida en tu ejemplo, pero Windows me dice que no encuentra el archivo .lnk, pero autoit si valida su existencia.

Espero ser claro, muchas gracias por tu ayuda.

Saludos.
Carlos Jaime

Hola Carlos.

El archivo .lnk es el acceso directo que usarías para ejecutar la aplicación normalmente desde el Escritorio de Windows.

Por ejemplo:

  • Ahora tienes un acceso directo llamado MiERP en el escritorio

  • Mueve ese acceso directo a una carpeta del disco, por ejemplo d:\MisApps

  • Tendrás entonces un archivo d:\MisApps\MiERP.lnk

  • Copia a esta carpeta el ejecutable AutoIt compilado _lanzador_velneo.exe después de haber añadido la aplicación en la sección correspondiente:

    Switch $CmdLine[1]
      	case "MiERP"
      		$cAccesoDirecto = "MiERP.lnk"
      		$cTitulo = "Mi Aplicación ERP"
      	case "0PS_APP_2"
             .....
    EndSwitch
    
    
  • El Título debe ser el mismo que has asignado al AUTOEXEC de la aplicación.

  • Crea un nuevo Acceso directo al lanzador de aplicaciones (Lanzador_MiERP) con el parámetro MiERP >>>> d:\MisApps\_lanzador_velneo.exe MiERP

  • Este nuevo Acceso directo Lanzador_MiERP es el que usará a partir de ahora el Usuario para prevenir ejecuciones simultáneas desde un mismo PC.

El lanzador _lanzador_velneo.exe buscará el Acceso directo MiERP.lnk en la misma carpeta y lo ejecutará en el caso de que la aplicación no esté ejecutándose.

Saludos
Paco Satué

1 me gusta

Hola Paco.

Hice todo lo que me dices, pero me sale el mismo mensaje que cuando lo hago con los parámetros de prueba:

image

Como si no existiera el acceso directo pero ahí esta.

Quedo atento a cualquier otra recomendación.

Saludos.
Carlos A. Jaime

Hola Carlos.

Seguramente la función shellexecute del API de Windows ya no ejecute la extensión LNK.

Lo que vas a hacer es indicar en el script de AutoIt la ruta VATP de acceso a la Instancia en lugar del archivo LNK y usas la función Run.

Switch $CmdLine[1]
  	case "MiERP"
  		$cAccesoDirecto = "C:\Program Files\Velneo\vClient.exe vatp://USUARIO:*@<SERVIDOR>/INSTANCIA_ERP")
  		$cTitulo = "Mi Aplicación ERP"
  	case "0PS_APP_2"
         .....
EndSwitch

Y comentas las últimas líneas del script añadiendo Run($cAccesoDirecto).

;~ If FileExists($cAccesoDirecto) = 0 Then
;~ 	MsgBox($MB_ICONWARNING,"Aplicación - " & $cTitulo,"No existe el acceso directo " & $cAccesoDirecto, 5)
;~ 	Exit
;~ EndIf
; MsgBox(0,$cTitulo,"Acceso directo a ejecutar -> " & $cAccesoDirecto)
; ShellExecute($cAccesoDirecto)
Run($cAccesoDirecto)

Con esto ejecutas directamente el ejecutable vClient.exe y prescindes del LNK original.

Pruébalo
Saludos
Paco Satué

1 me gusta

Excelente paco, muchas gracias.

Saludos.

Carlos Andres Jaime.