Hallo Gemeinde,
ich erstelle gerade eine VB.NET-Applikation und bin nun an einem Punkt angelangt, bei dem ich alleine leider nicht mehr weiter komme.
Vielleicht kann mir ja jemand von Euch weiterhelfen ?
Es geht um folgendes:
Es gibt eine Hauptapplikation, die dem User nur als EXE vorliegen soll. Das Programm soll einen Waferprober steuern, der der Reihe
nach alle Chips auf einem Siliziumwafer durchstept und dabei jeden Chip mit Nadeln kontaktiert, um an ihm Funktionstests durchzuführen.
Da unterschiedliche Arten von Chips aber unterschiedliche Funktionstests benötigen, sollen diese Tests in eine Subroutine ausgelagert
werden, die der User nach seinen Anforderungen jeweils editieren kann.
Die Subroutine soll sich in einer separaten Datei befinden, die zur Laufzeit dann von der Hauptapplikation eingelesen wird und deren
Quellcode dann mit dem VBCodeProvider zu einer Assembly wird, auf die dann von der Applikation zugegriffen wird.
Dies funktioniert soweit auch schon; ich kann auch aus der dynamisch kompillierten Subroutine heraus auf Objekte und Public Shared
Variablen der Hauptapplikation zugreifen.
Allerdings wird die dynamsich erstellte Assembly zur selben AppDomain hinzugefügt, wie die Hauptapplikation. D. h. sie läßt sich leider
nur entladen, indem die gesamte Applikation geschlossen wird, was aber nicht in meinem Sinne ist. Ohne Entlademöglichkeit der
Assembly wächst aber leider der Speicherverbrauch ziemlich stark an, da in der dynamischen Subroutine viel mit mehrdimensionalen
Arrays gearbeitet wird.
Ich habe gelesen, daß es eine Möglichkeit gibt, Assemblies wieder zu entladen, wenn sie zu einer anderen AppDomain hinzugefügt
werden, als der AppDomain der Hauptapplikation. Der Begriff Marshalling ist mir dabei außerdem noch über den Weg gelaufen,
aber leider kann ich damit nichts anfangen.
Alles, was ich zu der Thematik gefunden habe, bezog sich nur auf C# und nicht auf VB.NET.
Ich könnte eines der C#-Beispiele ev. sogar zu VB.NET konvertieren, aber ich bekomme es leider nicht hin, das Thema "separate
AppDomain" mit "durch VBCodeProvider dynamisch generierte Assembly" zu verheiraten.
Hier ist eine eingedampfte Beispielapplikation, die aus einer Datei namens "Code.txt" eine Subroutine lädt und mit VBCodeProvider
eine dynamische Assembly erstellt. Könnte mir vielleicht jemand dieses Beispiel so umschreiben, daß mir daraus ersichtlich wird,
wie ich die dynamsiche Assembly in eine separate AppDomain bekomme (und weiterhin daraus auf die Hauptapplikation zugreifen
kann) ?
Hier ist noch der Inhalt der Datei "Code.txt":
Ich bedanke mich schon einmal herzlich für jede hilfreiche Antwort !
ich erstelle gerade eine VB.NET-Applikation und bin nun an einem Punkt angelangt, bei dem ich alleine leider nicht mehr weiter komme.
Vielleicht kann mir ja jemand von Euch weiterhelfen ?
Es geht um folgendes:
Es gibt eine Hauptapplikation, die dem User nur als EXE vorliegen soll. Das Programm soll einen Waferprober steuern, der der Reihe
nach alle Chips auf einem Siliziumwafer durchstept und dabei jeden Chip mit Nadeln kontaktiert, um an ihm Funktionstests durchzuführen.
Da unterschiedliche Arten von Chips aber unterschiedliche Funktionstests benötigen, sollen diese Tests in eine Subroutine ausgelagert
werden, die der User nach seinen Anforderungen jeweils editieren kann.
Die Subroutine soll sich in einer separaten Datei befinden, die zur Laufzeit dann von der Hauptapplikation eingelesen wird und deren
Quellcode dann mit dem VBCodeProvider zu einer Assembly wird, auf die dann von der Applikation zugegriffen wird.
Dies funktioniert soweit auch schon; ich kann auch aus der dynamisch kompillierten Subroutine heraus auf Objekte und Public Shared
Variablen der Hauptapplikation zugreifen.
Allerdings wird die dynamsich erstellte Assembly zur selben AppDomain hinzugefügt, wie die Hauptapplikation. D. h. sie läßt sich leider
nur entladen, indem die gesamte Applikation geschlossen wird, was aber nicht in meinem Sinne ist. Ohne Entlademöglichkeit der
Assembly wächst aber leider der Speicherverbrauch ziemlich stark an, da in der dynamischen Subroutine viel mit mehrdimensionalen
Arrays gearbeitet wird.
Ich habe gelesen, daß es eine Möglichkeit gibt, Assemblies wieder zu entladen, wenn sie zu einer anderen AppDomain hinzugefügt
werden, als der AppDomain der Hauptapplikation. Der Begriff Marshalling ist mir dabei außerdem noch über den Weg gelaufen,
aber leider kann ich damit nichts anfangen.
Alles, was ich zu der Thematik gefunden habe, bezog sich nur auf C# und nicht auf VB.NET.
Ich könnte eines der C#-Beispiele ev. sogar zu VB.NET konvertieren, aber ich bekomme es leider nicht hin, das Thema "separate
AppDomain" mit "durch VBCodeProvider dynamisch generierte Assembly" zu verheiraten.
Hier ist eine eingedampfte Beispielapplikation, die aus einer Datei namens "Code.txt" eine Subroutine lädt und mit VBCodeProvider
eine dynamische Assembly erstellt. Könnte mir vielleicht jemand dieses Beispiel so umschreiben, daß mir daraus ersichtlich wird,
wie ich die dynamsiche Assembly in eine separate AppDomain bekomme (und weiterhin daraus auf die Hauptapplikation zugreifen
kann) ?
VB.NET-Quellcode
- Imports System.IO
- Imports System.Reflection
- Imports System.CodeDom
- Imports System.CodeDom.Compiler
- Imports Microsoft.VisualBasic
- Public Class Form1
- Public Shared obj As Object
- Public Shared compResults as Object
- Public Shared Dummy as Integer = 1
- Public Shared Float(1000,1000,50) as Double
- Private Sub Form1_Load( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
- Dim input = My.Computer.FileSystem.ReadAllText("Code.txt")
- Dim code as String = ""
- code = code & "Imports Microsoft.VisualBasic" & vbCrLf
- code = code & "Imports System" & vbCrLf
- code = code & "Imports System.Text" & vbCrLf
- code = code & "Imports System.Drawing" & vbCrLf
- code = code & "Imports System.Diagnostics" & vbCrLf
- code = code & "Imports DynamicCompile.Form1" & vbCrLf
- code = code & "Public Class DynamicClass" & vbCrLf
- code = code & " Public Sub DynamicSub(ByVal f as DynamicCompile.Form1)" & vbCrLf
- code = code & input & vbCrLf
- code = code & " End Sub" & vbCrLf
- code = code & "End Class" & vbCrLf
- Debug.Print(code)
- Debug.Print("Dummy: "+Str(Dummy))
- Dim vbProv = New VBCodeProvider()
- Dim vbParams = New CompilerParameters()
- vbParams.ReferencedAssemblies.Add("mscorlib.dll")
- Dim asm as Assembly
- For Each asm in AppDomain.CurrentDomain.GetAssemblies()
- vbParams.ReferencedAssemblies.Add(asm.Location)
- Next asm
- vbParams.CompilerOptions = "/t:library"
- vbParams.GenerateExecutable = False
- vbParams.GenerateInMemory = True
- vbParams.IncludeDebugInformation = True
- compResults = vbProv.CompileAssemblyFromSource(vbParams, code.ToString)
- If compResults.Errors.Count > 0 Then
- Dim er as CompilerError
- For Each er In compResults.Errors
- MessageBox.Show(er.ToString())
- Next er
- Else
- 'To do:
- 'Um ein Unload der dynamisch kompillierten Assembly zu ermöglichen,
- 'muß diese in einer neuen AppDomain erstellt werden.
- obj = compResults.CompiledAssembly.CreateInstance("DynamicClass")
- End If
- End Sub
- Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
- Dim args() As Object = {Me}
- Dim t As Type
- 'Call the dynamically compiled subroutine twice
- t = obj.GetType().InvokeMember("DynamicSub", BindingFlags.InvokeMethod, Nothing, obj, args)
- t = obj.GetType().InvokeMember("DynamicSub", BindingFlags.InvokeMethod, Nothing, obj, args)
- Debug.Print("Dummy: "+Str(Dummy))
- End Sub
- Public Shared Sub Test(ByVal TextToDisplay as String)
- Debug.Print(TextToDisplay)
- End Sub
- End Class
Hier ist noch der Inhalt der Datei "Code.txt":
VB.NET-Quellcode
- 'This is a comment
- Dim arr(1000,1000,50) as Double
- f.Text = "Form1's title changed by subroutine in dynamically compiled class."
- f.Button1.Backcolor = Color.Red
- f.Textbox1.Text = "Textbox1.Text changed by subroutine in dynamically compiled class."
- f.Label1.Text = "Label1.Text modified"
- Call Test("Subroutine ""Test"" is called from another dynamically compiled class.")
- Debug.Print("""Debug.Print"" is called from another dynamically compiled class.")
- Debug.Print("Dummy: "+Str(Dummy))
- f.Dummy = 2
- Dim i, j, k as Integer
- For i = 0 To 1000
- For j = 0 To 1000
- For k = 0 To 50
- f.Float(i,j,k) = arr(i,j,k)
- Next k
- Next j
- Next i
Ich bedanke mich schon einmal herzlich für jede hilfreiche Antwort !