VB.NET Resource exe in memory with argument - vb.net

Alright so i am pretty new to really anything in memory execution. I usually just write the bytes from the embedded resource into the file on the hard drive but for the program i am making for a work project it cannot write the exe to the disk.
So i took the code from Load a .NET assembly from the application's resources and run It from memory, but without terminating the main/host application
I modified the code a little bit in what i would think would work for running it with an argument and it does nothing but crash, not really listing any crash details though besides the windows error reporting.
here is the code:
Dim ass As Assembly = Assembly.Load(My.Resources.bbinst)
Dim method As MethodInfo = ass.EntryPoint
Dim parametersArray As Object() = New Object() {"/q /SERIAL=xxx-xxx"}
If (method IsNot Nothing) Then
Dim instance As Object = ass.CreateInstance(method.Name)
method.Invoke(instance, parametersArray)
If (instance IsNot Nothing) AndAlso (instance.GetType().GetInterfaces.Contains(GetType(IDisposable))) Then
DirectCast(instance, IDisposable).Dispose()
End If
instance = Nothing
method = Nothing
ass = Nothing
Else
Throw New EntryPointNotFoundException("Entrypoint not found in the specified resource. Are you sure it is a .NET assembly?")
End If
bbinst is the exe name that is embedded as bbinst.exe
The parametersArray is the argument i want to run which i converted from a C# sample i found else where.
Can someone help me as to why the program just crashes and error reporting pops up second after, i'm not to good as debugging. I also tried to run it without the arguments and it as well crashed the same way.
Any help is awesome, sometimes i have these random projects at work i don't know why they give me lol

A BadImageFormatException is thrown either when you attempt to load an assembly of the wrong bitness, or when you try to load an assembly that cannot be read, run or compiled by the current runtime.
Regarding bitness: 32-bit (x86) applications cannot load 64-bit code, and 64-bit (x64) applications cannot load 32-bit code. It's that simple.
As for not being able to read, run or compile the assembly: If the assembly that you're trying to load was programmed in a completely different language (more precisely: a language without .NET support) then it would also cause the above exception to be thrown.
Your method of executing an embedded application will only work with assemblies that were coded in a .NET language (C#, VB.NET, F#, C++/CLR, etc.). This is because that doesn't only run the application, it tries to load it like a .NET app linked to an Assembly, and/or AppDomain, class so that you can have some control over it and invoke methods inside it.
Your issue: My bet that your problem is caused by your embedded application not being of the same bitness as the host. Make sure both applications are compiled either as x86, x64 or AnyCPU.
However if it turns out that your embedded program isn't even written in a .NET language then that is the cause of your problem. That code of yours can only run .NET programs/DLLs.

You can invoke the EntryPoint by loading it in the assembly :
Public Shared Sub RunSearch(ByVal pPath As String, ByVal pText As String)
'Get assembly
Dim assembly As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
'Get the resource stream
Dim resourceStream As Stream = assembly.GetManifestResourceStream("path.executable name")
If resourceStream Is Nothing Then
MsgBox("Unexisting Path","Error")
End If
'Read the raw bytes of the resource
Dim resourcesBuffer(CInt(resourceStream.Length) - 1) As Byte
resourceStream.Read(resourcesBuffer, 0, resourcesBuffer.Length)
resourceStream.Close()
'Load the assembly
Dim exeAssembly As Reflection.Assembly = Reflection.Assembly.Load(resourcesBuffer)
Dim args() As String = {pPath, pText}
Dim parameters = New Object() {args}
Try
exeAssembly.EntryPoint.Invoke(Nothing, parameters)
Catch
MsgBox("Error during assembly executing","Error")
End Try
End Sub

Related

How can I copy resource files from my Visual Studio VB NET application onto the local system when it's executed?

I want to be able to copy resources I've compiled into the program to a location on the local machine where the application is run. Mostly a few DLLs that my program will not use, but others will (think Installer type of application).. But I can't find a way to reference the resources by path in order to do a File.Copy, for instance:
File.Copy(My.Resources.conversion, BinPath & "conversion.dll")
...tells me "Value of type 'Byte()' cannot be converted to 'String'". And I get why, obviously the first parameter needs to be a string path and not the resource itself. Is there a better way to copy resources or how can I obtain a reference path to the resource so I can use File.Copy?
For what it's worth, I've also tried
File.WriteAllBytes(BinPath & "conversion.dll", My.Resources.conversion)
...which "works" to copy it where I want it, but then I get errors when I try to call regsvr32 on the
new dll: "The module ... was loaded but the entry-point DLLRegisterServer was not found."
If there's a better way altogether, I'm open to any idea.
The following steps work for me:
Change the 'Build Action' of the dll in 'Resources' file to 'Embedded Resource'.
Use the following method to save resource file to disk.
Public Sub WriteResourceToFile(ByVal resourceName As String, ByVal fileName As String)
Using resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)
Using file = New FileStream(fileName, FileMode.Create, FileAccess.Write)
resource.CopyTo(file)
End Using
End Using
End Sub
Example of usage:
WriteResourceToFile("yournameSpace.conversion.dll", BinPath & "conversion.dll")

Sage200c SDK crashing in webforms

We are having a problem with the Sage 200c Extra 2018 SDK when used in Web Forms.
We have created solution with library, win forms and web forms project. We have noticed that when using the 'Win Forms project' it works, but the same example in 'Web Forms project' crashes. Sage 200c SDK documentation does not exclusively talk about Win or Web forms and what configuration each may need.
Could you please help us to get this working in web forms? We have an older version of the SDK working on an older version of Sage 200 v8.
We have upgraded Sage 200 v8 to Sage 200c Extra 2018 Summer Enhancements and tested it with the new client and all is working.
I have noticed on sage City similar questions but no answer.
Here
Here is our code sample:
Private Shared Sub FindCore200()
' get registry info for Sage 200 server path
Dim path As String = String.Empty
Dim root As RegistryKey = Registry.CurrentUser
Dim key As RegistryKey = root.OpenSubKey(REG_PATH)
If key IsNot Nothing Then
Dim value As Object = key.GetValue(REGKEY_VALUE)
If value IsNot Nothing Then
path = TryCast(value, String)
End If
End If
' refer to all installed assemblies based on location of default one
If String.IsNullOrEmpty(path) = False Then
Dim commonDllAssemblyName As String = System.IO.Path.Combine(path, DEFAULT_ASSEMBLY)
If (System.IO.File.Exists(commonDllAssemblyName)) Then
Dim defaultAssembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(commonDllAssemblyName)
Dim type As Type = defaultAssembly.[GetType](ASSEMBLY_RESOLVER)
Dim method As MethodInfo = type.GetMethod(RESOLVER_METHOD)
Dim x = method.Invoke(Nothing, Nothing)
Dim ok = 1
End If
End If
End Sub
when running the application, it always crashes on
application = New Sage.Accounting.Application
Exception Type: System.TypeInitializationException
Message: The type initializer for 'Sage.Accounting.Application' threw an exception.
Inner Exception:
Exception Type: System.IO.FileNotFoundException
Message: Could not load file or assembly 'Sage.MMSAdmin.Util, Version=19.0.0.0, Culture=neutral, PublicKeyToken=b2daa66d74953d11' or one of its dependencies. The system cannot find the file specified.
Are your application pools targeted to the correct version of .net and bit architecture?
If you can physically see the assembly in the path but the app can't, it's usually down to having the wrong version of .net configured. Going from such an old version to a new one, likely requires a .net version change (2.0 to 4.5 for example). It may just be that your winforms solution is targeted to the correct config and it's definitely worth comparing your build and application settings. Check that your targeting the correct CPU architecture in your build too.

Error 438 from using Filesystemobject.OpentTextFile but not on my computer

Note: I'm new to using Visual Studio and writing code outside of VB6 and VBA. Also, I've resolved my problem by using IO.File.
However, I really want to learn why this wouldn't work:
Dim FSO As New FileSystemObject
Dim FSOts As TextStream
FSOts = FSO.OpenTextFile(filepath1, IOMode.ForReading, True)
While FSOts.AtEndOfStream = False
temp = FSOts.ReadLine()
MsgBox(temp)
tempcollection.Add(temp)
End While
FSOts.Close()
It works on my computer, but for some reason it won't on others. I've used this object in a vb script before but in that situation the 2nd argument was 'ForReading' and was written in a different IDE (FEMAP) which referenced the 32bit scrrun.dll. In Visual Studio I noticed the scripting library is pointing to syswow64; I'm not sure if that makes any difference. All distributed sites run 64 bit OS and have this library. In any case I get an error 438 when I try to use:
FSOts = FSO.OpenTextFile(filepath1, IOMode.ForReading, True)
VS will not let me compile it with just 'ForReading'.
Again, I've used this object before in vb6 but the 2nd argument was not iomode.forreading but 'ForReading'. In that situation it worked fine on the same machines that are giving me problems (except for mine of course!).

WScript in VB.NET?

This is a snipet of code from my program:
WSHShell = WScript.CreateObject("WScript.Shell")
But for some reason, "WScript" is not declared. I know that this code works in VBScript but i'm trying to get it to work with vb.net. Whats going wrong?
The WScript object is specific to Windows Script Host and doesn't exist in .NET Framework.
Actually, all of the WScript.Shell object functionality is available in .NET Framework classes. So if you're porting VBScript code to VB.NET, you should rewrite it using .NET classes rather than using Windows Script Host COM objects.
If, for some reason, you prefer to use COM objects anyway, you need to add the appropriate COM library references to your project in order to have these objects available to your application. In case of WScript.Shell, it's %WinDir%\System32\wshom.ocx (or %WinDir%\SysWOW64\wshom.ocx on 64-bit Windows). Then you can write code like this:
Imports IWshRuntimeLibrary
....
Dim shell As WshShell = New WshShell
MsgBox(shell.ExpandEnvironmentStrings("%windir%"))
Alternatively, you can create instances of COM objects using
Activator.CreateInstance(Type.GetTypeFromProgID(ProgID))
and then work with them using late binding. Like this, for example*:
Imports System.Reflection
Imports System.Runtime.InteropServices
...
Dim shell As Object = Nothing
Dim wshtype As Type = Type.GetTypeFromProgID("WScript.Shell")
If Not wshtype Is Nothing Then
shell = Activator.CreateInstance(wshtype)
End If
If Not shell Is Nothing Then
Dim str As String = CStr(wshtype.InvokeMember(
"ExpandEnvironmentStrings",
BindingFlags.InvokeMethod,
Nothing,
shell,
{"%windir%"}
))
MsgBox(str)
' Do something else
Marshal.ReleaseComObject(shell)
End If
* I don't know VB.NET well, so this code may be ugly; feel free to improve.

Importing B.exe into A.exe an then run B.exe from A.exe

I am using Visual Basic 2008 and I have a question about it?
I have a.exe and b.exe ( the a.exe is an vbApp, and b.exe is an executable file ). Is it possible to include the b.exe into a.exe and then running it from a.exe? By, for example, importing the b.exe into vbProject and then running it without extracting it.
The question is a bit vague, but you can definitely do something along those lines, in several different ways.
First, you can certainly compile a separate EXE (I'll call it EXEA) into a VB Project (Call it EXEB). When user runs EXEB, it extracts the resource containing EXEA, saves it as a file (likely to the temp folder or someplace with WRITE rights) and then shells to EXEA.
Another possibility would be to compile external functionality into a DLL, call it DLLA, then compile that dll into a VB project (call it EXEB).
When user runs EXEB, it extracts the resource containing DLLA, storing it as a memory stream, then uses ASSEMBLY.LOAD to load the DLL from the memory stream (instead of from a file), and at that point can create objects from that dll, and use it as normal.
In both these cases though, it's probably better to simply compile the second EXE or DLL and include both in an MSI installation project.
More details in the question might help narrow down other possible solutions as well.
Try this :
1) Open project of B.exe.
2) Create a new module in project B, add "Sub Main" , then write this
Sub Main(Byval args() As String)
Dim X As New Form1 'replace Form1" with your real startup form
X.ShowDialog
End Sub
3) Open properties of that project B, and uncheck checkbox with name "Enable application framework". And change "Startup Object" to "Sub Main"
4) Compile and close project B.
5) Now open project of A.exe, and use following code to run B.exe in memory:
Dim tmpAssembly As System.Reflection.Assembly = System.Reflection.Assembly.Load(System.IO.File.ReadAllBytes("C:\b.exe"))'Replace "C:\b.exe" real b.exe path
Dim TmpMethod As MethodInfo = tmpAssembly.EntryPoint
If TmpMethod IsNot Nothing Then
Dim TmpObject As Object = tmpAssembly.CreateInstance(TmpMethod.Name)
Dim args() As String = Nothing
TmpMethod.Invoke(TmpObject , args)
End If
Me.Close()
CAUTION! You can run applications on memory only if you have done steps 1 and 2 with those applications. Otherwise you will get errors , which are not solved yet...