none
CompileAssemblyFromSource - Namespace or Type ... doesn't contain any public member. I need a Guru! RRS feed

  • Question

  • I have an app that allows users to create their own vb functions and execute on the fly.  I do this using the CodeDom.  I'm by no means an expert at this.  my model is fairly simple, my code reads their script and passes in an argument and retrieves it back from the objFunctionParameters().

     

    Here is their code Script:

    'VB.NET Template Script<br/>
    Imports System<br/>
    Imports System.IO<br/>
    Imports System.Windows.Forms<br/>
    Imports Microsoft.VisualBasic<br/>
    imports System.Data.SqlClient<br/>
    <br/>
    Namespace Dynam<br/>
    	Public Class DynamicCode<br/>
    <br/>
    		Public Function ExecuteCode(ByVal ParamArray prmParameters() As Object) As Object<br/>
    			Dim objYourCode As New YourCodeClass<br/>
    			Dim oErr As Integer = 0 'This is the value you are required to return back to the compiler to indicate your own errState. 1 = True, 0 = False.<br/>
    			Dim oErrMsg As String = String.Empty 'This is a message you can return back, you must throw oErr != 0 to retrieve the message in Dexterity.<br/>
    			OErr = objYourCode.changeData(oErrMsg)<br/>
    <br/>
    			'The return statement should never be modified since we parse out the error and the modified noString in our code model.<br/>
    			'Do NOT change the ChrW(130), we use this as a delimiter to parse out your return.<br/>
    			Return Str(oErr) & ChrW(130) & oErrMsg<br/>
    <br/>
    		End Function<br/>
    <br/>
    	End Class<br/>
    <br/>
    	Public Class YourCodeClass<br/>
    <br/>
    		''' <summary><br/>
    		''' This example will show how you can manipulate data and return your own err state.<br/>
    		''' </summary><br/>
    		''' <returns>oErr. Valid values are 0 for no errors or 1 for errors found.</returns><br/>
    		''' <remarks></remarks><br/>
    		Public Function changeData(ByRef nErrMsg As String) As Integer<br/>
    		Try<br/>
    			Dim sqlCmd As New SqlCommand<br/>
    			MsgBox("Do your code here. Remember to include necessary libraries.")<br/>
    		Catch ex As Exception<br/>
    			nErrMsg = ex.Message<br/>
    			Return 1<br/>
    		End Try<br/>
    		Return 0<br/>
    		End Function<br/>
    <br/>
    	End Class<br/>
    End Namespace<br/>
    
    

    Here is the code that executes their script:

     Public Function scriptExecuteTemplate(ByVal nSourceCode As String) As Integer
        '
        ' Instantiate the VB compiler.
        '
        Dim objCodeCompiler As ICodeCompiler = New VBCodeProvider().CreateCompiler
    
        '
        ' Pass parameters into the compiler.
        '
        Dim objCompilerParameters As New CompilerParameters
        objCompilerParameters.ReferencedAssemblies.Add("System.dll")
        objCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")
        objCompilerParameters.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
        objCompilerParameters.GenerateInMemory = True
    
        ' Get te source code and compile it.
        '
        Dim objCompileResults As CompilerResults = objCodeCompiler.CompileAssemblyFromSource(objCompilerParameters, nSourceCode)
    
        '
        ' Check for compiler errors.
        '
        If objCompileResults.Errors.HasErrors Then
          _errMsg = ("Error: Line>" & objCompileResults.Errors(0).Line.ToString & ", " & objCompileResults.Errors(0).ErrorText)
          Return 1
          'MsgBox("Error: Line>" & objCompileResults.Errors(0).Line.ToString & ", " & objCompileResults.Errors(0).ErrorText)
          Exit Function
        End If
    
        '
        ' Get a reference to the assembly.
        '
        Dim objAssembly As System.Reflection.Assembly = objCompileResults.CompiledAssembly
    
        '
        ' Create an instance of the DynamicCode class referenced in the source code.
        '
        Dim objTheClass As Object = objAssembly.CreateInstance("Dynam.DynamicCode")
    
        If objTheClass Is Nothing Then
          _errMsg = "Unable to load class."
          Return 1
          Exit Function
        End If
    
        '
        ' Create a parameter to be passed into the ExecuteCode function in class DynamicCode.
        '
        Dim objFunctionParameters(0) As Object
        objFunctionParameters(0) = nSourceCode
    
        '
        ' Call the DynamicCode.ExecuteCode
        '
        '
        Try
          Dim objResult As Object = objTheClass.GetType.InvokeMember("ExecuteCode", _
                  BindingFlags.InvokeMethod, Nothing, objTheClass, objFunctionParameters)
    
          Dim results() As String = Split(objResult.ToString(), ChrW(130), 2)
          Dim err As Integer = CInt(results(0))
          _errMsg = results(1)
          Return err
        Catch ex As Exception
          _errMsg = "Error:" & ex.Message
          Return 1
        End Try
    
        Return 0
      End Function
    

    Generally, I can do pretty much any vb in the passthru scripting including text parsing and streaming.  However, I noticed when I use the ADODB or System.Data.SqlClient libraries, I get the Error:

    Error: Line>6, Namespace or type specified in the Imports 'System.Data.SqlClient' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases.
    

    I sure this problem pops up under other libraries as well.  I've tried Dimm sqlConn As System.Data.SqlClient and remove the Imports System.Data.SqlClient statement, (Then the compiler complains that System.Data.SqlClient.SqlCommand is not defined).

    I know this can be done since, theoretically, the IDE is of the same nature of what I'm done.  I just don't posses the knowledge of the inner workings of CodeDom.

    PPPPLease Help!  Got a deadline that is passing by me as I type this.

     


    Greg Kowieski The World On-Line
    Tuesday, January 11, 2011 3:35 AM

Answers

  • When you want to use libraries, you have to reference these. For that you already have some objCompilerParameters.ReferencedAssemblies.Add calls in your code. Make sure that you add all references that the user is allowed to use.

    With kind regards,

    Konrad

    • Marked as answer by Greg Kowieski Tuesday, January 11, 2011 7:07 PM
    Tuesday, January 11, 2011 5:22 AM

All replies

  • When you want to use libraries, you have to reference these. For that you already have some objCompilerParameters.ReferencedAssemblies.Add calls in your code. Make sure that you add all references that the user is allowed to use.

    With kind regards,

    Konrad

    • Marked as answer by Greg Kowieski Tuesday, January 11, 2011 7:07 PM
    Tuesday, January 11, 2011 5:22 AM
  • I tried that too.  When I add :objCompilerParameters.ReferencedAssemblies.Add("System.Data.SqlClient.dll" ) The compiler tells me it can't find the library.

    However, if I objCompilerParameters.ReferencedAssemblies.Add("System.Data.dll" ), it seems to work.  why wouldn't referencing System.Data.SqlClient.dll work as well.  I see that the library exists on the harddrive.


    Greg Kowieski The World On-Line
    Tuesday, January 11, 2011 3:04 PM
  • btw, you are the guru for the day.  Thanks so much for you insight and help!
    Greg Kowieski The World On-Line
    Tuesday, January 11, 2011 7:07 PM
  • Hi,

    I looked on my system. Maybe the assembly that is referenced must be on a special location? System.Data.dll is part of the GAC. So maybe an workaround could be to simply install the System.Data-SqlClient.dll into the GAC, too.

    The documentation on MSDN that I saw didn't say much about the requirements so I am really wondering a little about this.

    With kind regards,

    Konrad

    Tuesday, January 11, 2011 7:29 PM