-1

I am using VB.Net with Visual Studio 2019 and have been attempting this for a couple days and have been unsuccessful with DoWork. I did do some research and while exploring more threads similar to this, they are 7-12 years old, and do not seem to cut it for me.

I did get an example from Import code from text VB.NET

I am trying to have the Codedom script read the text file and run the code from inside it.

I have a couple errors which I will explain after the below code.

The Textfile called deploythis.txt has MsgBox("Success") inside it.

Imports System.CodeDom.Compiler
Imports System.IO
Imports System.Reflection

Public Class Form1

    Public Interface IScript
        Property Variable1 As String
        Sub DoWork()
    End Interface

    Private Function GenerateScript(code As String) As IScript
        Using provider As New VBCodeProvider()
            Dim parameters As New CompilerParameters()
            parameters.GenerateInMemory = True
            parameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location)
            parameters.ReferencedAssemblies.Add("System.Data.dll")
            parameters.ReferencedAssemblies.Add("System.Xml.dll")
            Dim interfaceNamespace As String = GetType(IScript).Namespace
            Dim codeArray() As String = New String() {"Imports " & interfaceNamespace & Environment.NewLine & code}
            Dim results As CompilerResults = provider.CompileAssemblyFromSource(parameters, codeArray)
            If results.Errors.HasErrors Then
                Throw New Exception("Failed to compile script")
            Else
                Return CType(results.CompiledAssembly.CreateInstance("Script"), IScript)
            End If
        End Using
    End Function

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim dthis As String = "C:\deploythis.txt"
        Dim script As IScript = GenerateScript(File.ReadAllText(dthis))
        script.DoWork()
        MessageBox.Show(script.Variable1)
    End Sub

End Class

When running this script, the first error comes from results. However it does not list an actual error, warning or message. Just highlights Throw New Exception("Failed to compile script")

            Dim results As CompilerResults = provider.CompileAssemblyFromSource(parameters, codeArray)
            If results.Errors.HasErrors Then
                Throw New Exception("Failed to compile script")
            Else
                Return CType(results.CompiledAssembly.CreateInstance("Script"), IScript)
            End If

If I remove Throw New Exception("Failed to compile script") from the if statement,

I result in a new error from script.DoWork(), which says "Object reference not set to an instance of an object."

This error is actually a Warning which says Function GenerateScript doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.

Thanks for your time.

qsNeedAs
  • 1
  • 3
  • Did you not think to look inside that `Errors` property to see what the errors actually are? It's a collection `CompilerError` objects and each one contains information about an error. That seems the obvious place to start. – jmcilhinney May 24 '21 at 05:58
  • thanks for the reply, I updated the errors. only script.dowork() actually displays a warning, the first error does not. – qsNeedAs May 24 '21 at 08:25
  • 1
    *"the first error does not"*. Of course it does. You're just not looking for it. If `results.Errors.HasErrors` is `True` then there are errors but you are simply ignoring all the information provided about them. It is all in `results.Errors` so look at it. `For Each error As CompilerError In results.Errors.HasErrors` and so on. – jmcilhinney May 24 '21 at 08:38
  • The `throw new exception("failed to compile script")` error can be modified, depending on what i call it. but it does not actually display any errors, warnings or messages under Error List. and like i explained above, if I remove that Line, it highlights the main issue, which is the fact that `Function GenerateScript doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.` – qsNeedAs May 24 '21 at 08:47
  • You're compiling code at run time and you don't know something as simple as writing a loop to examine a collection. What is going on here?! Read my previous comment again and do what I said. I'm done here. – jmcilhinney May 24 '21 at 09:19
  • I'v read over this a few times, and I have a theory for you. Might need some confirmation/debugging. Basically, the crux of it is in the GenerateScript, if results.Errors.HasErrors your just Throwing an exception back up the stack and not returning an IScript instance. Then you're trying to access a null IScript with no exception handling. Simple as that. My suggestions, 1) check IScript is not null 2) catch and handle the exception in the button event – Hursey May 24 '21 at 23:41

2 Answers2

1

You only have a Return in the Else part of your If. I think this is only a warning, not an error. Just add a Return to the first path of the If and the compiler should be happy.

If results.Errors.HasErrors Then
    For Each er As CompilerError In results.Errors
        Debug.Print(er.ErrorText)
    Next
    Return Nothing
Else
    Return CType(results.CompiledAssembly.CreateInstance("Script"), IScript)
End If

The in the Button code just check for Nothing and inform the user.

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim dthis As String = "C:\deploythis.txt"
    Dim script As IScript = GenerateScript(File.ReadAllText(dthis))
    If script Is Nothing Then
        MessageBox.Show("Failed to compile script")
    Else
        script.DoWork()
        MessageBox.Show(script.Variable1)
    End If
End Sub
Mary
  • 14,926
  • 3
  • 18
  • 27
  • Thank you for your response Mary. Alright, as this script stands, seems it returns as nothing and isnt capable of deploying the code inside of the textfile. Your addition did solve the errors, just not sure what I am missing, which would allow the script to deploy the code inside the text file. – qsNeedAs May 25 '21 at 00:05
0

I didn't think that this was really an answer to the question being asked but apparently the scope of a comment is too small to get the message across, so I'll provide an answer with more code. Here:

If results.Errors.HasErrors Then

the HasErrors property is telling you that that collection does indeed contain errors. The idea is that you examine those errors to determine what to do about them. You can use the debugger for that but explaining how to debug is beyond the scope of this answer. The simple option is to write some simple code to examine the error information:

For Each error As CompilerError in results.Errors
    Debug.WriteLine(error)
Next
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • I get that you have years and years of more experience then me, but your responses are quite trollish. I didnt feel i needed to explain every single step i have taken to try to resolve these errors. I have already used the debug option in that line and it results with the same error. `Function GenerateScript doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.` I clearly do not have the knowledge or experience to fully understand how to fix this, and instead of helping, youre just calling me out for not understanding. – qsNeedAs May 24 '21 at 22:58