Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [VB.NET] Form MDI con finestre child integrate come plugin

    Salve a tutti, ho un annoso problema a cui non riesco a venire a capo:

    Premetto che il mio scopo è quello di creare un form PADRE di tipo MDI ed accogliere tanti MDI-Child quanti sono gli eseguibili che vengono trovati in una determinata directory, utilizzando la tecnica dei plug in applicata alle dll (http://vbnotebookfor.net/2007/10/09/...-ins-in-vbnet/) ma usando degli eseguibili EXE (generati sempre con VB).
    In pratica io andrei a creare una specie di "MasterPage" che viene integrata con nuovi programmi e funzionalità a seconda di quanti sono gli eseguibili disponibili.

    I passaggi effettuati sono:
    1. Creazione di un form 'PADRE' mdi che implementa un interfaccia che chiameremo IPadre
    2. Creazione della DLL con le interfacce IPadre e IFiglio
    3. Creazione di uno o piu eseguibili che implementano l'interfaccia IFiglio


    Fino a questo momento è tutto ok funziona tutto alla perfezione, nel form Padre per ottenere l'elenco delle form che implementano l'interfaccia IFiglio uso un ciclo e controllo con la reflection i tipi implementati dagli assemblyes, se trovo quello che mi interessa attivo un istanza del .exe e salvo tale istanza in un hashtable:

    codice:
     Dim Plugins As New Hashtable
     Private Sub CercaPlugIn()
            Plugins.Clear()
            Dim Cartella As String = Application.StartupPath
            'cerchiamo tutti file dll nella directory del programma
    
            Dim Files() As String = System.IO.Directory.GetFiles(Cartella, "*.exe")
            Dim File As String
            For Each File In Files
                Try
                    'carichiamo i file trovati
                    'notate che stiamo usando la reflection
    
                    Dim Assembly As Reflection.Assembly = Reflection.Assembly.LoadFile(File)
                    Dim tipo As Type
                    For Each tipo In Assembly.GetTypes
                        'cerchiamo le istanze del tipo IFiglio
    
                        Dim iface As Type = tipo.GetInterface("funzioniPadre.Interfaccia.IFiglio")
                        If Not (iface Is Nothing) Then
                            'creiamo l'istanza del plugin-
                            Dim plugin As IPlugIn = Activator.CreateInstance(tipo)
                            'salviamo l'istanza in hashtable
    
                            Plugins.Add(plugin.Name, plugin)
                        End If
                    Next
                Catch ex As Exception
                    MsgBox("Impossibile caricare un programma. Messaggio restituito: " & ex.Message, MsgBoxStyle.Exclamation)
                End Try
            Next
        End Sub
    Ora arriviamo al problema:

    Il programma FormPadre con tutti i vari PlugIn 'Figlio' risiedono in una cartella condivisa nella nostra rete, ogni client esegue il programma padre ed utilizza i vari sottoprogrammi visti come 'estensioni' del programma padre.
    Il problema nasce quando devo fare l'aggiornamento di un singolo programma figlio:
    il fatto che il padre crea una istanza di ogni figlio, di fatti, blocca il file EXE sottostante fino alla chiusura del form padre anche se il form figlio NON è in esecuzione.
    Come fare a distruggere l'istanza creata con Activator.Createistance dalla memoria una volta che detta istanza della form figlio viene chiusa senza chiedere a tutti gli utenti di chiudere anche il form PADRE??? Sto letteralmente impazzendo, so che non è un problema di facile soluzione, e Dio Google non ha prodotto una soluzione per il mio caso.
    Scrivo qui nel fortuito caso in cui un utente di questo forum abbia dovuto affrontare un problema simile...

    Grazie a tutti anche solo per la lettura del lungo testo.
    if $oggi = "Lunedi" {
    $coglioni = $coglioni * 500;
    }

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,480
    Dal codice che hai postato, se ho capito bene, tu scandisci tutte le librerie dei plugin e ne carichi una classe rappresentativa memorizzandone l'oggetto in una lista (variabile Plugins).

    In questo modo, non puoi sbloccare la libreria in quanto hai un oggetto attivo in memoria che appartiene ad una classe definita nel file che intendi restituire.

    A mio avviso, dovresti memorizzare solo delle "informazioni di riferimento" nella lista dei plugin, ossia dei dati che ti consentano di sapere quali plugin sono installati ed eventualmente cosa puoi farci, ma senza andare a creare oggetti definiti nella libreria esterna del plugin; quest'ultima operazione la fai solo nel momento in cui ti occorre necessariamente, usando le informazioni di riferimento per individuare la libreria, la classe e fare quello che stai facendo attualmente.

    Per ottenere delle "meta-informazioni", potresti opzionalmente ricorrere all'uso di attributi (discendenti di System.Attribute) con cui decorare i plugin.

    Penso sia più difficile rendere l'idea del concetto che descriverlo.
    Spero comunque che sia chiaro.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Quote Originariamente inviata da alka Visualizza il messaggio

    Penso sia più difficile rendere l'idea del concetto che descriverlo.
    Spero comunque che sia chiaro.

    Ciao!
    No, è chiarissimo, ma una volta che l'utente attiva l'AddIn dal menu devo per forza istanziare l'oggetto di tipo IFiglio nell'Heap viene generato il riferimento corrispondete allo stack ed a quel punto sono 'fregato', se si potesse buttare giu il riferimento allo stack come avviene nella gran parte degli oggetti con il comando Dispose sarebbe ideale...
    if $oggi = "Lunedi" {
    $coglioni = $coglioni * 500;
    }

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2015
    Messaggi
    2
    Quote Originariamente inviata da Frungillo Visualizza il messaggio
    Salve a tutti, ho un annoso problema a cui non riesco a venire a capo:

    Premetto che il mio scopo è quello di creare un form PADRE di tipo MDI ed accogliere tanti MDI-Child quanti sono gli eseguibili che vengono trovati in una determinata directory, utilizzando la tecnica dei plug in applicata alle dll (http://vbnotebookfor.net/2007/10/09/...-ins-in-vbnet/) ma usando degli eseguibili EXE (generati sempre con VB).
    In pratica io andrei a creare una specie di "MasterPage" che viene integrata con nuovi programmi e funzionalità a seconda di quanti sono gli eseguibili disponibili.

    I passaggi effettuati sono:
    1. Creazione di un form 'PADRE' mdi che implementa un interfaccia che chiameremo IPadre
    2. Creazione della DLL con le interfacce IPadre e IFiglio
    3. Creazione di uno o piu eseguibili che implementano l'interfaccia IFiglio


    Fino a questo momento è tutto ok funziona tutto alla perfezione, nel form Padre per ottenere l'elenco delle form che implementano l'interfaccia IFiglio uso un ciclo e controllo con la reflection i tipi implementati dagli assemblyes, se trovo quello che mi interessa attivo un istanza del .exe e salvo tale istanza in un hashtable:

    codice:
     Dim Plugins As New Hashtable
     Private Sub CercaPlugIn()
            Plugins.Clear()
            Dim Cartella As String = Application.StartupPath
            'cerchiamo tutti file dll nella directory del programma
    
            Dim Files() As String = System.IO.Directory.GetFiles(Cartella, "*.exe")
            Dim File As String
            For Each File In Files
                Try
                    'carichiamo i file trovati
                    'notate che stiamo usando la reflection
    
                    Dim Assembly As Reflection.Assembly = Reflection.Assembly.LoadFile(File)
                    Dim tipo As Type
                    For Each tipo In Assembly.GetTypes
                        'cerchiamo le istanze del tipo IFiglio
    
                        Dim iface As Type = tipo.GetInterface("funzioniPadre.Interfaccia.IFiglio")
                        If Not (iface Is Nothing) Then
                            'creiamo l'istanza del plugin-
                            Dim plugin As IPlugIn = Activator.CreateInstance(tipo)
                            'salviamo l'istanza in hashtable
    
                            Plugins.Add(plugin.Name, plugin)
                        End If
                    Next
                Catch ex As Exception
                    MsgBox("Impossibile caricare un programma. Messaggio restituito: " & ex.Message, MsgBoxStyle.Exclamation)
                End Try
            Next
        End Sub
    Ora arriviamo al problema:

    Il programma FormPadre con tutti i vari PlugIn 'Figlio' risiedono in una cartella condivisa nella nostra rete, ogni client esegue il programma padre ed utilizza i vari sottoprogrammi visti come 'estensioni' del programma padre.
    Il problema nasce quando devo fare l'aggiornamento di un singolo programma figlio:
    il fatto che il padre crea una istanza di ogni figlio, di fatti, blocca il file EXE sottostante fino alla chiusura del form padre anche se il form figlio NON è in esecuzione.
    Come fare a distruggere l'istanza creata con Activator.Createistance dalla memoria una volta che detta istanza della form figlio viene chiusa senza chiedere a tutti gli utenti di chiudere anche il form PADRE??? Sto letteralmente impazzendo, so che non è un problema di facile soluzione, e Dio Google non ha prodotto una soluzione per il mio caso.
    Scrivo qui nel fortuito caso in cui un utente di questo forum abbia dovuto affrontare un problema simile...

    Grazie a tutti anche solo per la lettura del lungo testo.

    Ciao,

    Navigando su internet alla ricerca di una soluzione al mio problema ho trovato questo topic e approfitto per chiedere/ti alcuni suggerimenti, visto che ti trovi già ad uno stadio più avanzato nell'affrontare il problema rispetto a me.

    Io ho sviluppato un applicazione in vb.net di tipo MDI ed ora mi trovo con la necessità di dover sviluppare dei child (form) custom. Non li voglio integrare nel progetto principale in quanto non vorrei trovarmi a dover ricompilare a causa del componente custom. Inoltre vorrei svilupparli come plug-in, in modo che utilizzando l'applicazione primaria non ci si accorge che la form sia derivante da un plug-in.

    Grazie per gli aiuti preziosi,

    Ciao

    Se non sbaglio è la stessa cosa che hai realizzato tu, giusto?

  5. #5
    Utente di HTML.it L'avatar di gibra
    Registrato dal
    Apr 2008
    residenza
    Italy
    Messaggi
    4,244
    Questo degli aggiornamenti 'on fly' è un problema abbastanza comune.
    Consideriamo anche il fatto che vi possono essere scenari anche più complessi oltre a quello classico che hai rappresentato di una rete LAN locale.

    Infatti, fino a che in azienda gli utenti erano pochi, potevo farli uscire dal programma per eseguire l'aggiornamento, ma poi le esigenze sono cambiate ed ora abbiamo utenti che si possono connettere da qualsiasi parte del mondo (ad un nostro server CITRIX), con diversi fusi orari (e quindi non sempre raggiungibili nell'orario di lavoro) per cui ho dovuto studiarmi qualcosa, perché sarebbe stato impossibile continuare su questa strada.
    Dovevo trovare il modo di aggiornare i programmi in modo trasparente all'utente.

    L'unica soluzione che ho trovato è non usare l'eseguibile sul server, ma creare un launcher che all'avvio copia l'eseguibile e altri file accessori in un percorso locale dell'utente.

    In tal modo, io posso aggiornare il programma quando voglio (non essendo mai in uso) e quando l'utente avvierà la prossima sessione, si trova tutto aggiornato, indipendentemente dal fatto che altri utenti stiano utilizzando il programma o meno.

    Se qualcuno ha soluzioni migliori, ben vengano.


    P.S. Segnalo anche un mio progetto di esempio sui plug-in(di diversi anni fa) che ha un approccio leggermente diverso. magari può interessare:
    VB2008 - Gestione moduli Plugin
    http://nuke.vbcorner.net/Projects/NE...T/Default.aspx


  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2015
    Messaggi
    2
    Grazie mille, ho capito l'approccio è l'ho adeguato al mio progetto, funziona perfettamente,
    Grazie

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.