Compiling and running code in runtime - vb.net

I am trying to compile and run code at runtime. I am using the below code to achieve this. However, when i trying to invoke the method, simply a "Find Source" file browser dialog opens and the code is not run. Can anyone please help me here.
Dim VBP As New VBCodeProvider
Dim CVB As System.CodeDom.Compiler.ICodeCompiler
CVB = VBP.CreateCompiler
Dim PM As New System.CodeDom.Compiler.CompilerParameters
PM.GenerateInMemory = True
PM.GenerateExecutable = True
PM.OutputAssembly = "RunCode.dll"
PM.MainClass = "MainClass"
PM.IncludeDebugInformation = True
Dim ASM As System.Reflection.Assembly
For Each ASM In AppDomain.CurrentDomain.GetAssemblies
PM.ReferencedAssemblies.Add(ASM.Location)
Next
Dim CompileResults As System.CodeDom.Compiler.CompilerResults
CompileResults = CVB.CompileAssemblyFromSource(PM, sCode)
Dim CompileErrors As System.CodeDom.Compiler.CompilerError
For Each CompileErrors In CompileResults.Errors
RTMainScript.AppendText(vbCrLf & CompileErrors.ErrorNumber & ": " & CompileErrors.ErrorText & ", " & CompileErrors.Line)
Next
Dim objRun As New Object
Dim vArgs() As Object
objRun = CompileResults.CompiledAssembly.CreateInstance("RunCode.MainClass", False, BindingFlags.CreateInstance, Nothing, vArgs, Nothing, Nothing)
If Not objRun Is Nothing Then
Dim oMethodInfo As MethodInfo = objRun.GetType().GetMethod("Main")
Dim oRetObj As Object = oMethodInfo.Invoke(objRun, BindingFlags.Static Or BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic, Nothing, Nothing, Nothing) 'Find source dialog appears here
Else
MsgBox("Compile Error")
End If

The code you provided is incomplete. You are using this method to compile the code:
CompileResults = CVB.CompileAssemblyFromSource(PM, sCode)
But you actually never specified what sCode is. If you are getting an open file browser dialog, then I am quite sure that your sCode is the cause of it. It must have been set somewhere while calculating the variable value to open a file.
If you are trying to change a piece of code that was used to compile from a file then changing the method from CompileAssemblyFromFile() to CompileAssemblyFromSource() is not enough. You need to dig more into the code and change all related methods.

Ensure your threading model is STA.
OpenFileDialog and similar objects will not operate correctly if the threading model is set to MTA.
If you must use MTA for some other reason then you can create your own custom OpenFileDialog class; sort of sucks.

Related

Running VB.Net code in my program, without creating instances, or parameters. Is it possible?

I am currently trying to make a program where you can type a VB.NET script into a richtextbox (strCode) and then execute it. Like as if I executed it in Visual Studio.
My current code look like this:
Dim objCompilerParameters As New CompilerParameters
objCompilerParameters.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")
objCompilerParameters.GenerateInMemory = True
Dim objCompileResults As CompilerResults
Dim Provider As CodeDomProvider = CodeDomProvider.CreateProvider("VisualBasic")
objCompileResults = Provider.CompileAssemblyFromSource(objCompilerParameters, strCode)
' 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")
'----------------------------------------------------------------------------------------------------
' Create a parameter to be passed into the ExecuteCode function in class DynamicCode.
Dim objFunctionParameters(0) As Object
objFunctionParameters(0) = "Parameter 1"
'----------------------------------------------------------------------------------------------------
'Creating Result
Dim objResult As Object = objTheClass.GetType.InvokeMember("ExecuteCode", _
BindingFlags.InvokeMethod, Nothing, objTheClass, objFunctionParameters)
'---------------------
This runs fine .. as long as the namespace in my script is "Dynam", and the public class is "TestClass". Also the Public Function has to be named "ExecuteCode". Just like in the script.
Is there a way to create this, without having to hardcode the function and class names? So I can just call the classes, and functions whatever the user wants to call them.
Thanks in advance. I hope it made a little sense. If not, please let me know.

Extracting `dll` files from the Resources after they been added using CodeDOM in VB.Net

I'v seen a lot of answers here on stackoverflow, but none of them help me with exactly what i need and almost all of them in C# when i need VB, so i hope someone will help me with my problem, which is this :
I have compiled a exe file in vb.net using CodeDOM, and i added two dll file to its resources and that worked just fine and you can even notice that the size of the exe has increase after adding the resources, but when i run the exe file like that My.Resources.Touchless, it gives me an error saying that
"Resources" is not a member of "My".
And what i need is to read these dll files from the compiled exe file and then extract them using File.WriteAllBytes()..., if i didn't try to extract the files from the resources and instead of that i copied them manually to the executable path, the application will work perfectly, so the problem is just with trying to call the dll files from the resources.
Here is some code :
Public Shared Function Compile(ByVal Output As String, ByVal Source As String, ByVal Icon As String, ByVal resources As String) As Boolean
Dim Parameters As New CompilerParameters()
Dim cResults As CompilerResults = Nothing
Dim Compiler As CodeDomProvider = CodeDomProvider.CreateProvider("VB")
Parameters.GenerateExecutable = True
Parameters.TreatWarningsAsErrors = False
Parameters.OutputAssembly = Output
Parameters.MainClass = "MyNamespace.MainWindow"
Parameters.EmbeddedResources.Add(Path.GetTempPath & "TouchlessLib.dll")
Parameters.EmbeddedResources.Add(Path.GetTempPath & "WebCamLib.dll")
Parameters.ReferencedAssemblies.AddRange(New String() {"System.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "System.Management.dll", Path.GetTempPath & "TouchlessLib.dll"})
Parameters.CompilerOptions = "/platform:x86 /target:winexe"
If Not String.IsNullOrEmpty(Icon) Then
File.Copy(Icon, "icon.ico")
Parameters.CompilerOptions += " /win32icon:" & "icon.ico"
End If
cResults = Compiler.CompileAssemblyFromSource(Parameters, Source)
If cResults.Errors.Count > 0 Then
For Each compile_error As CompilerError In cResults.Errors
Dim [error] As CompilerError = compile_error
Console.Beep()
MsgBox("Error: " & [error].ErrorText & vbCr & vbLf & [error].Line)
Next
Return False
End If
If Not (String.IsNullOrEmpty(Icon)) Then
File.Delete("icon.ico")
End If
Return True
End Function
When i call them from the compiled exe file like this :
File.WriteAllBytes(Application.StartupPath & "\TouchlessLib.dll", My.Resources.TouchlessLib)
File.WriteAllBytes(Application.StartupPath & "\WebCamLib.dll", My.Resources.WebCamLib)
... i get the following error message :
"Resources" is not a member of "My".
Try adding this class:
Imports System.Dynamic
Imports System.Reflection
Public Class DynamicResources
Inherits DynamicObject
Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As Object) As Boolean
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resouceNames As String() = asm.GetManifestResourceNames
For Each s As String In resouceNames
Dim name As String = IO.Path.GetFileNameWithoutExtension(s)
Dim Manager As New Resources.ResourceManager(name, asm)
Try
Dim resource = Manager.GetObject(binder.Name)
If Not resource Is Nothing Then
result = resource
Return True
End If
Catch ex As Exception
End Try
Next
Return False
End Function
End Class
You can use it like this:
Dim root as string=Application.StartupPath
File.WriteAllBytes(Path.Combine(root, "TouchlessLib.dll"), DynamicResources.TouchlessLib)
File.WriteAllBytes(Path.Combine(root, "WebCamLib.dll"), DynamicResources.WebCamLib)
The My namespace and any associated functionality is created via auto-generated code. Since your code is now the code generator and not the IDE, you will not have those niceties unless your code provides it.
To extract an embedded resource, you need to include code similar to the following in the source code you are compiling with CodeDOM.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resouceNames As String() = asm.GetManifestResourceNames
For Each s As String In resouceNames
Dim fi As New FileInfo(s)
Using strm As Stream = asm.GetManifestResourceStream(s)
Using fs As Stream = fi.Create()
strm.CopyTo(fs)
End Using
End Using
Next
Make sure that you also include:
Imports System.Reflection
Imports System.IO
This code retrieves the executing Assembly obtains an array of embedded resource names. It then calls GetManifestResourceStream method to get the named resource as a stream. This stream is copied to a file stream.
Modify the example to suite your needs.
Note that I have not included any error checking/handling in this example. Anything dealing with IO should have some error handling.
Edit:
Based on the comment below, it appears that only a copy/paste type answer will do for the OP.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resourceName As String
Dim fi As FileInfo
resourceName = "TouchlessLib.dll"
fi = New FileInfo(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, resourceName))
Using strm As Stream = asm.GetManifestResourceStream(resourceName)
Using fs As Stream = fi.Create()
strm.CopyTo(fs)
End Using
End Using

Variable 'TargetProcess' hides a variable in an enclosing block

So im making a dll injector and im getting this error: Variable 'TargetProcess' hides a variable in an enclosing block.
Code:
Dim httpclient = New Net.WebClient
httpclient.Credentials = New Net.NetworkCredential("ftp_username", "ftp_password")
httpclient.DownloadFile("ftp:/you.gifrsite.com/Cheat.dll", Application.StartupPath & "\Cheat.dll")
IO.File.Move(Application.StartupPath & "\Cheat.dll", Cheat)
Dim TargetProcess As Process() = Process.GetProcessesByName("PROCESS NAME")
If TargetProcess.Length = 0 Then Me.TextBox1.Text = ("Waiting for GAME.exe")
The compiler error is meaningful, you have two variables with the same name inside this scope. Rename one of both. Since Process.GetProcessesByName returns an Process()(so possibly multiple) i'd name it targetProcesses(plural):
Dim targetProcesses As Process() = Process.GetProcessesByName("PROCESS NAME")

Compiling VB Code With CodeDom

Read up on it, couldn't find anything that worked for me.
Basically, I have a file called SourceCode.vb in my resources.
I'm trying to use:
Dim objCodeCompiler As System.CodeDom.Compiler.ICodeCompiler = New VBCodeProvider().CreateCompiler
Dim objCompilerParameters As New System.CodeDom.Compiler.CompilerParameters()
objCompilerParameters.ReferencedAssemblies.Add("System.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")
objCompilerParameters.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Drawing.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Data.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Deployment.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Xml.dll")
objCompilerParameters.GenerateExecutable = True
objCompilerParameters.GenerateInMemory = False
objCompilerParameters.CompilerOptions = "/target:winexe"
objCompilerParameters.OutputAssembly = "C:\"
Dim strCode As String = My.Resources.SourceCode.ToString
Dim objCompileResults As System.CodeDom.Compiler.CompilerResults = objCodeCompiler.CompileAssemblyFromSource(objCompilerParameters, strCode)
If objCompileResults.Errors.HasErrors Then
MsgBox("Error: Line>" & objCompileResults.Errors(0).Line.ToString & ", " & objCompileResults.Errors(0).ErrorText)
Exit Sub
End If
I need it to compile the code and make the file and place it in C:\ - For some reason its not working. Error is:
error: line>0, no input sources specified
Any ideas? Thanks in advance.
Edit: Problem was that I needed to add an actual name for the file after the output. Thanks for the help Hans.
It's actually because you are setting OutputAssembly to a location when it expects an assembly name. It should be:
objCompilerParameters.OutputAssembly = "AssemblyName.exe"
If you want to set the location of the output assembly, add it to your compiler options.
objCompilerParameters.CompilerOptions = "/target:winexe /out:C:\\AssemblyName.exe"
Although, I believe if you want to write to the C: drive, you will need to run your program as administrator.

Cannot Close Down MS Word From .NET

I have the following snippet of code. It works (opens all the Word documents in a directory and then closes them down)...but it doesn't clean up after itself when I totally exit the program.
By this I mean that if I look at the TaskManager once I exit the VB.NET application I see the WINWORD.EXE even though it did not exist before I opened the application.
Here's the declarations I have:
Dim WordApp As Microsoft.Office.Interop.Word.Application
Dim aDoc As Microsoft.Office.Interop.Word.Document
Dim missing As Object = System.Reflection.Missing.Value
Dim nullobj As Object = System.Reflection.Missing.Value
Dim MYreadOnly As Object = False
Dim isVisible As Object = False
And here's the code:
Private Sub cmdGenerate_Click(sender As System.Object, e As System.EventArgs) Handles cmdGenerateKeywords.Click
Dim xmldoc As New XmlDataDocument()
Dim xmlnode As XmlNodeList
Dim i As Integer
Dim fs As FileStream
WordApp = New Microsoft.Office.Interop.Word.Application
WordApp.Visible = False
For Each f As FileInfo In New DirectoryInfo(txtFolderName.Text).GetFiles("*.docx")
' Open the document that was chosen by the dialog
aDoc = WordApp.Documents.Open(f.FullName, missing, [MYreadOnly], _
missing, missing, missing, missing, missing, missing, missing, _
missing, isVisible)
'aDoc.Close()
aDoc = Nothing
Next
'Close the Word Document
'aDoc.Close(nullobj, nullobj, nullobj)
WordApp.Application.Quit()
WordApp = Nothing
End Sub
As you can tell I've commented and uncommented various statements in regards to closing down Word documents and the Word Application itself. Nothing I have tried seems to be able to get rid of that pesky WINWORD.EXE
Something seems to have a lock and will not let it close down? Is that it?
Run explicitly Garbage Collector, as is shown in this article:
// Clean up the unmanaged Word COM resources by forcing a garbage
// collection as soon as the calling function is off the stack (at
// which point these objects are no longer rooted).
GC.Collect();
GC.WaitForPendingFinalizers();
// GC needs to be called twice in order to get the Finalizers called
// - the first time in, it simply makes a list of what is to be
// finalized, the second time in, it actually is finalizing. Only
// then will the object do its automatic ReleaseComObject.
GC.Collect();
GC.WaitForPendingFinalizers();
Despite link above, my experience is that run once is enough. But second call doesn't throw an error, so do it this way.
fs.Close()
fs.Dispose()
http://msdn.microsoft.com/en-us/library/system.io.filestream.dispose.aspx
This releases your resources. Might allow other close methods to work. I read through the code twice and do not see you using "fs" anywhere like I would expect.