LIBERAR SUB-PROGRAMA INSTANCIADO DO PRINCIPAL
Caros colegas,
Estou com dificuldades de liberar totalmente programas executáveis instanciados pelo programa principal através do Assembly e CreateInstance. As rotinas funcionam perfeitamente, entretanto, depois de encerrado o sub-programa que foi chamado pelo programa principal, para que eu possa atualizar a versão deste, ou seja, substituir o programa chamado, cujo usuários estejam utilizando o Sistema (executável Principal), é necessário que o programa principal seja encerrado também, ou seja, todos devem sair do sistema para a devida atualização do sub-programa. Existe alguma maneira de ser liberado totalmente o programa chamado da memória depois que foi encerrado para que possa ser feito a atualização deste programa sem ter que encerrar o sistema totalmente? Abaixo está descrito a chamada dos sub-programas. Esta chamada está em uma class library:
Dim extAssembly As System.Reflection.Assembly = System.Reflection.Assembly.UnsafeLoadFrom(Pub.pathsistema & [Ô]\[Ô] & Programa & [Ô].exe[Ô])
Dim FormType As Type = extAssembly.GetType(Programa & [Ô].[Ô] & Formulario, True)
Dim extForm As Object = Activator.CreateInstance(FormType, Nothing, Nothing, Param, Nothing, Nothing)
extForm.Show()
Se puder me ajudar nesta dúvida, fico extremamente agradecido. Aguardo breve retorno. Muito obrigado.
Atenciosamente
Luiz Ricardo
Estou com dificuldades de liberar totalmente programas executáveis instanciados pelo programa principal através do Assembly e CreateInstance. As rotinas funcionam perfeitamente, entretanto, depois de encerrado o sub-programa que foi chamado pelo programa principal, para que eu possa atualizar a versão deste, ou seja, substituir o programa chamado, cujo usuários estejam utilizando o Sistema (executável Principal), é necessário que o programa principal seja encerrado também, ou seja, todos devem sair do sistema para a devida atualização do sub-programa. Existe alguma maneira de ser liberado totalmente o programa chamado da memória depois que foi encerrado para que possa ser feito a atualização deste programa sem ter que encerrar o sistema totalmente? Abaixo está descrito a chamada dos sub-programas. Esta chamada está em uma class library:
Dim extAssembly As System.Reflection.Assembly = System.Reflection.Assembly.UnsafeLoadFrom(Pub.pathsistema & [Ô]\[Ô] & Programa & [Ô].exe[Ô])
Dim FormType As Type = extAssembly.GetType(Programa & [Ô].[Ô] & Formulario, True)
Dim extForm As Object = Activator.CreateInstance(FormType, Nothing, Nothing, Param, Nothing, Nothing)
extForm.Show()
Se puder me ajudar nesta dúvida, fico extremamente agradecido. Aguardo breve retorno. Muito obrigado.
Atenciosamente
Luiz Ricardo
Essa chamada pela Class Library é de um método static/shared ou está em um objeto? Se estiver em um objeto, acho que o mesmo está mantendo esses sub-programas referenciados não permitindo que vc faça a substituição na atualização. Veja se consegue dá um Dispose() nesse objeto hipotético.
O .Net não permite que assemblies sejam [Ô]descarregados[Ô] da memória sem que o AppDomain seja finalizado, quando você carrega um assembly da forma como fez ele é carregado no AppDomain padrão do seu programa então só quando o seu programa for finalizado é que ele vai ser descarregado e não tem o que fazer.
é possÃvel criar um AppDomain secundário, porém é mais complicado trabalhar com isso, tem algumas limitações do que pode ser feito e ainda assim é necessário finalizar esse AppDomain manualmente, então você precisaria saber quando ele não é mais necessário para poder fazer isso.
Outra coisa é que não recomendo fazer desta forma com executáveis, o melhor seria você usar DLLs para estes sub programas, fica basicamente a mesma coisa que já está no seu código, só que na DLL não é gerado algumas partes de código que são especÃficas para EXEs
é possÃvel criar um AppDomain secundário, porém é mais complicado trabalhar com isso, tem algumas limitações do que pode ser feito e ainda assim é necessário finalizar esse AppDomain manualmente, então você precisaria saber quando ele não é mais necessário para poder fazer isso.
Outra coisa é que não recomendo fazer desta forma com executáveis, o melhor seria você usar DLLs para estes sub programas, fica basicamente a mesma coisa que já está no seu código, só que na DLL não é gerado algumas partes de código que são especÃficas para EXEs
Bom dia a todos!
A estrutura está montada da seguinte forma:
Codigo no Programa Principal abaixo:
Imports MAIN
Public Class FormPrincipal
Dim Instancia As New ClasseInstanciar
Private Sub FormPrincipal_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Pub.pathsistema = Application.StartupPath
etc...
End Sub
Private Sub EventoMenu_Click(ByVal sender As Object, ByVal e As System.EventArgs) [ô]Click do Menu Dinâmico
If CType(sender, MenuItem).Name <> Nothing Then
Pub.Programa = CType(sender, MenuItem).Name
If Instancia.Instanciar(Pub.Programa, Pub.Param) = False Then
Me.Close()
Exit Sub
End If
End If
etc...
End Sub
Codigo no Programa Chamado:
Imports MAIN
Public Class FormChamado
Dim BancoDados As New ClasseBancoDados(Pub.conexao)
etc...
Private Sub FimProgramaChamado
Me.Close
End Sub
Código da Class Library chamado de MAIN ( única DLL que contém várias Classes como: ClasseInstanciar, Pub (contém variáveis shared apenas), ClasseBancoDados, ClasseMenu, ControleFormulario, etc...):
ClasseInstanciar contém o seguinte código:
Imports System.Reflection
Imports System.Windows.Forms
Public Function Instanciar(ByVal Programa As String, Optional ByVal Param() As Object = Nothing) As Boolean
Dim extAssembly As System.Reflection.Assembly = System.Reflection.Assembly.UnsafeLoadFrom(Pub.pathsistema & [Ô]\[Ô] & Programa & [Ô].exe[Ô])
Try
Dim FormType As Type = extAssembly.GetType(Programa & [Ô].[Ô] & Formulario, True)
Dim extForm As Object = Activator.CreateInstance(FormType, Nothing, Nothing, Param, Nothing, Nothing)
extForm.Show()
Catch ex As Exception
MessageBox.Show([Ô]Ocorreu um erro durante a chamada do programa: [Ô] & ex.Message, _
[Ô]Executa Rotina[Ô], MessageBoxButtons.OK, MessageBoxIcon.Error)
Return False
End Try
Return True
End Function
End Class
Obs: Na DLL MAIN cada classe no projeto foi criado separado (Adicionar/Novo Item/Classe)
Leandro, shared estão designados para as variáveis criadas na classe PUB na DLL. Postei melhor os códigos de acordo com o projeto.
OCELOT, estava com receio sobre AppDomain. Já li a respeito disso, porém é um tanto complicado, mas se for esta a solução, você poderia postar um exemplo de como utilizar isto?
Obrigado a todos!!
Que Deus abençoe!!!
Atc,
Luiz Ricardo
A estrutura está montada da seguinte forma:
Codigo no Programa Principal abaixo:
Imports MAIN
Public Class FormPrincipal
Dim Instancia As New ClasseInstanciar
Private Sub FormPrincipal_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Pub.pathsistema = Application.StartupPath
etc...
End Sub
Private Sub EventoMenu_Click(ByVal sender As Object, ByVal e As System.EventArgs) [ô]Click do Menu Dinâmico
If CType(sender, MenuItem).Name <> Nothing Then
Pub.Programa = CType(sender, MenuItem).Name
If Instancia.Instanciar(Pub.Programa, Pub.Param) = False Then
Me.Close()
Exit Sub
End If
End If
etc...
End Sub
Codigo no Programa Chamado:
Imports MAIN
Public Class FormChamado
Dim BancoDados As New ClasseBancoDados(Pub.conexao)
etc...
Private Sub FimProgramaChamado
Me.Close
End Sub
Código da Class Library chamado de MAIN ( única DLL que contém várias Classes como: ClasseInstanciar, Pub (contém variáveis shared apenas), ClasseBancoDados, ClasseMenu, ControleFormulario, etc...):
ClasseInstanciar contém o seguinte código:
Imports System.Reflection
Imports System.Windows.Forms
Public Function Instanciar(ByVal Programa As String, Optional ByVal Param() As Object = Nothing) As Boolean
Dim extAssembly As System.Reflection.Assembly = System.Reflection.Assembly.UnsafeLoadFrom(Pub.pathsistema & [Ô]\[Ô] & Programa & [Ô].exe[Ô])
Try
Dim FormType As Type = extAssembly.GetType(Programa & [Ô].[Ô] & Formulario, True)
Dim extForm As Object = Activator.CreateInstance(FormType, Nothing, Nothing, Param, Nothing, Nothing)
extForm.Show()
Catch ex As Exception
MessageBox.Show([Ô]Ocorreu um erro durante a chamada do programa: [Ô] & ex.Message, _
[Ô]Executa Rotina[Ô], MessageBoxButtons.OK, MessageBoxIcon.Error)
Return False
End Try
Return True
End Function
End Class
Obs: Na DLL MAIN cada classe no projeto foi criado separado (Adicionar/Novo Item/Classe)
Leandro, shared estão designados para as variáveis criadas na classe PUB na DLL. Postei melhor os códigos de acordo com o projeto.
OCELOT, estava com receio sobre AppDomain. Já li a respeito disso, porém é um tanto complicado, mas se for esta a solução, você poderia postar um exemplo de como utilizar isto?
Obrigado a todos!!
Que Deus abençoe!!!
Atc,
Luiz Ricardo
Faça seu login para responder