Programma già aperto da MSAccess

di il
6 risposte

Programma già aperto da MSAccess

Può capitare che un utente lanci due volte sulla stessa macchina il programma, vorrei impedirlo.

Ovviamente la prima soluzione che viene in mente è mettere un semaforo, magari un file che all'ingresso viene creato e alla fine rimosso e testato al rientro.
Oppure meglio in una tabella dove viene inserito posto di lavoro, dataora di entrata e di uscita all'uscita.
Se uno chiede di rientrare e non è uscito blocca.

Il problema di questi sistemi è l'errore, ad esempio se la macchina si spegne e se rientro risulti ancora dentro.
Delle volte questo si ovvia con una domanda anzichè sbattere fuori 'sei sicuro di non aver lanciato il programma rimasto attivo?', se si risponde sì chiude la sessione precedente d'ufficio ecc. ecc.
Altra strada potrebbe essere controllare la presenza del DB ldb con i lock (ma anche quello in caso di crash resta).

Vorrei quindi fare qualcosa di meglio, in pratica interrogare quello che vedresti nel task manager per vedere se access con il DB che fa da programma è già attivo.
Sempre ammesso che questo si fattibile dallo user senza privilegi amministrativi.
Ovviamente essendo fatto dallo stesso programma al rientro vedrei due sessioni e quindi dovrei essere in grado di distinguere la più recente da chiudere.

Qualche idea?

6 Risposte

  • Re: Programma già aperto da MSAccess

    Ti dico come ho fatto io, in breve ho creato un EXE con uno script che verifica la presenza del file laccdb e se presente apre un popup di avvertimento.
    Volendo dettagliare in realtà, avendo a che fare con un cliente i cui dipendenti lavorano un pò da locale (in rete sotto dominio, classico) ed un pò in rdp su server (quello di win) ho creato l'exe in cui riconosco la tipologia di utilizzo (rdp/net), e l'utente di dominio. A quel punto verifica se esiste la copia del programma per quella combinazione, se esiste verifica la presenza dell'laccdb e segue quanto sopra diversamente crea la copia e la apre. All'apertura la copia del programma verifica se il programma "base" è + aggiornato e nel caso lo indica con popup e parte l'aggiornamento. in questo modo io ho una posizione in cui posiziono il file accde ed i vari client rimangono automaticamente aggiornati ad ogni apertura.
    Chiaramente sui desktop piuttosto che nelle applicazioni c'è solo il link all'exe (che per sicurezza richiama la versione corretta di runtime, ... 'n si sa mai)
  • Re: Programma già aperto da MSAccess

    Ci sono vari accrocchi fattibili... ma a mio avviso l'unico giusto è sfruttare il S.O. ed i Mutex.
    Non è semplice richiede le API, ma qui trovi un esempio completo...

    https://www.experts-exchange.com/articles/2104/Avoiding-running-multiple-instances-of-an-application.html
  • Re: Programma già aperto da MSAccess

    L'utilizzo delle API messe a disposizone dal SO (nel caso di Windows

    https://learn.microsoft.com/en-us/windows/win32/sync/synchronization-objects

    )

    e' il modo CORRETTO di fare il lavoro.

    Un'altro e' quello di controllare SE ESISTE gia' in processo attivo che sta' usando l'eseguibile corrente.
    ANCHE in questo caso si deve passare per le API di WIndows, ovviamente.

    L'alternativa il file, va ancora bene MA con un po' di controlli in piu'.

    NON BASTA la sola presenza del file.

    Come minimo bisogna modificare il timestamp del file ogni T secondi minuti.

    Quindi il secondo processo puo' controllare se il file e' presente e SE NON E' STATO AGGIORNATO PER TEMPO MAGGIORE di K*T
    (con K almeno 2)

    E' ovvio che se il file e' presente, ma non e' stato aggiornato, allora il processo che lo gestiva e' ""morto prematuramente"".

    Perche' K*T?
    Per evitare falsi negativi.

    Tutta questa logica va applicata ANCHE nel caso del record salvato sul DB.
  • Re: Programma già aperto da MSAccess

    migliorabile ha scritto:


    L'utilizzo delle API messe a disposizone dal SO (nel caso di Windows

    https://learn.microsoft.com/en-us/windows/win32/sync/synchronization-objects

    )

    e' il modo CORRETTO di fare il lavoro.

    Un'altro e' quello di controllare SE ESISTE gia' in processo attivo che sta' usando l'eseguibile corrente.
    Non ho fatto prove, quindi vado a memoria e mi sorge un dubbio.
    Ma access, non apre il processo solo per access e non per lo specifico database?
    Quindi, nella remota casistica che occorresse aprire un database diverso in contemporanea, a quello esclusivo, non si genererebbe un falso positivo anche con l uso delle api che impedirebbero l apertura di access?

    Una strada che premetto non è percorribile, perché trattasi di accrocco grosso come una casa, potrebbe essere quello di intercettare la doppia assegnazione di nome ad un menu o gruppo personalizzato di una ribbon personalizzata.
    Se non sbaglio anche se si aprono database completamente diversi, se in tutte e due c e una dichiarazione identica di nome nel codice xml, genera l errore di dichiarazione già esistente.
    Intercettando l errore si potrebbe impedire il caricamento della seconda istanza.
  • Re: Programma già aperto da MSAccess

    FORSE RISOLTO!
    Devo ancora 'testarlo sul campo', ma penso di aver trovato una soluzione banale ma dai primi test sembra perfetta.
    Se qualcuno ci trova delle controindicazioni me lo segnali.

    Sono partito dal presupposto che quando entro viene creato il file laccdb con il lock che non cambia come data di creazione fino alla sua cancellazione. Dato che si tratta di un file a sola lettura il lancio di una nuova sessione sullo stesso DB non pò cambiare la data ed ora di creazione di tale file, quindi se la distanza dalla data ora di creazione supera i 3 secondi è un rientro.

    Quindi alla partenza del programma lancio la funzione:
    
    Private Function TestRientro()
    ' Test rientro, by Holzl Paolo
    Dim DataOraLock
        DataOraLock = FileDateTime(Left(Application.CurrentDb.Name, Len(Application.CurrentDb.Name) - 5) & "laccdb")
        If DateDiff("s", DataOraLock, Now) > 3 Then
            Call MsgBox("Attenzione, programma già aperto in precedenza.")
            DoCmd.Quit
            End If
    End Function
    
  • Re: Programma già aperto da MSAccess

    Versione 2.0.
    Quando entriamo in sviluppo spesso chiudiamo le schermate per poi ripartire senza chiusere il DB.
    In quel caso ad ogni ripartenza ci sbatterebbe fuori considerandolo un rientro.
    Qui la versione riveduta e corretta che fa si che il controllo sia solo per accde o accdr.
    
    Function TestRientro()
    Dim DataOraLock
        If Right(Application.CurrentDb.Name, 1) <> "b" Then
            DataOraLock = FileDateTime(Left(Application.CurrentDb.Name, Len(Application.CurrentDb.Name) - 5) & "laccdb")
            If DateDiff("s", DataOraLock, Now) > 3 Then
                Call MsgBox("Attenzione, programma già aperto in precedenza.")
                DoCmd.Quit
                End If
            End If
    End Function
    
Devi accedere o registrarti per scrivere nel forum
6 risposte