Read VB 6 binary file in C# - c#

I have a binary file written by VB6 application and now would like to use C# application to read the VB6 exported binary file. I have used the Microsoft.VisualBasic.dll into my C# project.
However there are some data inconsistency in C# application but I have check it in VB.net and it works nicely as well. (I convert from VB6 to VB.net, then VB.net to C#)
The screenshot represents the result from reading binary file by using C# and VB.Net application.
VB.Net is my expected result and now my C# application was showing inconsistency result
Both are double values in C# and VB.NET, and based on my observation, the int, string values looks fine.
In C# I was using statement shown as below, BinaryDetails is struct and inside have few double variables
ValueType DetailsValueType = (ValueType)BinaryDetails;
FileSystem.FileOpen(FileNumber, FileName, OpenMode.Binary, OpenAccess.Read);
FileSystem.FileGet(FileNumber, ref DetailsValueType);
I have change the data type in C# from double to float, still not my expected result:

You can reverse-engineer this kind of mishap with a little test program:
class Program {
static void Main(string[] args) {
var value1 = 3.49563395756763E-310;
var bytes1 = BitConverter.GetBytes(value1);
Console.WriteLine(BitConverter.ToString(bytes1));
var value2 = 101.325;
var bytes2 = BitConverter.GetBytes(value2);
Console.WriteLine(BitConverter.ToString(bytes2));
}
}
Output:
CC-CC-CC-54-59-40-00-00
CD-CC-CC-CC-CC-54-59-40
Note how you are definitely on the right track, you are reading correct byte values from the file. Those doubles have CC-54-59-40 in common. It is just that you read the data misaligned. You started reading too late, off by 2 bytes.
That's because your BinaryDetails is not an exact match with the data in the file. Do keep in mind that you have to assume the file contains VB6 data types. They are slightly different from C# types:
VB6 file data is tightly packed, you need [StructLayout(LayoutKind.Sequential, Pack = 1)]
A VB6 Integer is a C# short
A VB6 Long is a C# int
A VB6 Boolean is a C# short with -1 = True, 0 = False;
VB6 strings have a fixed width, you need to read them as byte[]
Ought to be enough to solve the problem. And of course keep in mind that it is very simple to use a VB.NET assembly from a C# program.

Related

How to read binary file in C# which is created in Delphi

I have source code available for a legacy Delphi application that creates/reads a binary file. I have to read that binary file in a C# application.
The code in Delphi is something like this :
fs := TFileStream.Create(dst,fmOpenRead);
try
while fs.Position<fs.Size do begin
fs.Read(sSomeVar,sizeof(dDateTime));
fs.Read(sSomeVar1,sizeof(sIntValue));
fs.Read(sSomeVar2,sizeof(sCardinalValue1));
fs.Read(sSomeVar3,sizeof(sStringValue));
....
It appears that I have read the entire file into a byte[] and then interpret number of bytes to correct data type(for e.g. integer, string, uint1)?
I couldn't find a c# example anywhere.
Thanks,

c# invoke c++ how to pass value with unit8

I have a c# script I need to run in my C# application.
here is my c++ function,i hope can invoke it with c# in my c# application
the c++ prototype :
int ApplibUsbSimple_Login(UINT8 *buff)
i use c# invoke it:
[DllImport("test.dll", EntryPoint = "login")]
public static extern int Login(????? buff)
i have seach the answer in google and stackoverflow just now,but i could not
get the answer.
how should i replace the ????? with correct variable
As others already noted, if the UINT8 type used in your native function represents an 8-bit byte, you can map it to the byte type in C#.
Moreover, according to this MSDN doc page, if you take a look at the C-Style Arrays section, you can use this C# code for your byte array parameter:
[MarshalAs(UnmanagedType.LPArray)] byte[] buff
In addition, there are a few questions for you: How can the native C-interface function know the size of the input array? Is this array 0-terminated? Is there another parameter in that function that specifies the size of the array in bytes? Is the size of the array fixed and specified as part of the function documentation?
I think you can use byte[]
See https://learn.microsoft.com/en-us/dotnet/articles/csharp/language-reference/keywords/byte
Sure, C# doesn't have the exact type uint8, but the equivalent is byte.

C# string multi-byte c++ , gif binary data convert to png or image

I'm seriously stuck in this problem.
this problem caused because i'm weak with C# concept.
all i want do is electronic equipment return gif format data. which is binary i believe.
so i want convert this data to image.
/// below is just send command to instrument that i want " Returns an image of the display in .gif format "
my6705B.WriteString("hcop:sdump:data?", true);
string image_format = my6705B.ReadString();
So i received gif data from instrument, manual said this is " Returns an image of the display in .gif format " ==> I believe this is binary format.
below link is what's in side in string image_format.
string image_format
http://i.stack.imgur.com/UcYqV.png
my goal is convert this string to image file. (png or jpg whatever)
so i convert this string variable to byte array.
below is my code after this command ....
//// this also couldn't work ~~~
System.Text.UnicodeEncoding encode = new System.Text.UnicodeEncoding();
byte[] byte_array22 = encode.GetBytes(image_format);
MemoryStream ms4 = new MemoryStream(byte_array22);
Image image = Image.FromStream(ms4); //// error point
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png");
//// this also couldn't work ~~~
byte[] byte_array22 = Encoding.Unicode.GetBytes(image_format);
MemoryStream ms4 = new MemoryStream(byte_array22);
Image image = Image.FromStream(ms4, true, true); /// always error here,,,
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png", System.Drawing.Imaging.ImageFormat.Png);
both code didn't work and error point is same. i commented error point.
and anyway string to byte array is work.
I'm pain with this problem several days.
but my vendor make this code with C++,, this is working .
let me share my vendor's code,.this is implemented C++.
char szReadBuffer[102400] = {'\0', };
char szReadBinary[102400] = {'\0', };
m_iStatus = viOpenDefaultRM(&m_vDefaultRM);
m_iStatus = viOpen(m_vDefaultRM, (LPSTR)(LPCTSTR)m_strVISA, VI_NULL, VI_NULL, (ViPSession)&m_iDevHandle);
m_iStatus = viSetAttribute(m_iDevHandle, VI_ATTR_TMO_VALUE, 15000);
m_iStatus = QueryGPIB("HCOPy:SDUMp:DATA?", szReadBuffer, sizeof(szReadBuffer));
//Store the results in a text file
CFile file;
file.Open("PICTURE.GIF", CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
memcpy(szReadBinary, &szReadBuffer[2], sizeof(szReadBuffer));
file.Write(szReadBinary, sizeof(szReadBinary));
file.Close();
i think important point is what they declare. they declare char[] .
and adviced me that this C++ code did use String MultiByte ? (just hear from him)
i have no exp with C++.
and if i follow this c++ code then working.
my goal is implement with C#. so need to follow C++ code.
please advice my problem.
It can be confusing sometimes to port C++ to C# if you're unfamiliar with one or the other (never mind both! :) ). One thing to keep in mind: there's no "byte" type in C++. Instead, binary data is stored in char[] arrays, just like C strings.
On the other hand, C# distinguishes between the two. So when you see a char[] in C++ that's being used to store binary data instead of character data, the C# equivalent is a byte[], not a char[] or System.String as it might be for other C++ usages of char[].
Your "my6705B" object appears to be some kind of abstraction of your hardware device. Presumably in addition to the WriteString() and ReadString() methods, there are methods that can be used to write and read binary data, using a byte[] type instead of characters or strings. Use that instead.
Let's assume the proper method is named "ReadBytes()". Then your code would look like this:
byte[] image_format = my6705B.ReadBytes();
MemoryStream ms4 = new MemoryStream(image_format);
Image image = Image.FromStream(ms4);
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png");
Now, that may or may not be exactly what you need. You haven't provided enough information about the "my6705B" object. Many I/O APIs allow for partial reads of available data, so it's possible you would need to read from the device in a loop until you know (somehow) that you've received all of the available bytes for the image. Or maybe the type you're using for the "my6705B" object handles that all for you. I have no way to know…you'll have to figure that out yourself.
But hopefully the above gets you oriented enough wrt the C++ vs C# issues to get you a little further.

Passing data between Python and C# without writing a file

I would like to pass binary information between Python and C#. I would assume that you can open a standard in/out channel and read and write to that like a file, but there are a lot of moving parts, and I don't know C# too well. I want to do this sort of thing, but without writing a file.
# python code
with open(DATA_PIPE_FILE_PATH, 'wb') as fid:
fid.write(blob)
subprocess.Popen(C_SHARP_EXECUTABLE_FILE_PATH)
with open(DATA_PIPE_FILE_PATH, 'rb') as fid:
'Do stuff with the data'
// C# code
static int Main(string[] args){
byte[] binaryData = File.ReadAllBytes(DataPipeFilePath);
byte[] outputData;
// Create outputData
File.WriteAllBytes(outputData)
I've tried several different ways of using standard in/out, but I've had no luck matching them up, like I said, there are a lot of moving parts. I've tried things like
p = subprocess.Popen(C_SHARP_EXECUTABLE_FILE_PATH, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write(blob)
p.stdin.close()
or
p = subprocess.Popen(C_SHARP_EXECUTABLE_FILE_PATH, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = p.communicate(blob)
on the python side along with
TextReader tIn = Console.In;
TextWriter tOut = Console.Out;
String str = tIn.ReadToEnd();
//etc...
as well as a couple of other things that didn't work on the C# side. I've had mild success with some things, but I've changed it around so much that I don't remember what has worked for what. Could somebody give me a hint as to which pieces would work the best, or if this is even possible?
The data I want to pass has null and other non-printable characters.
This python code was correct
p = Popen(C_SHARP_EXECUTABLE_FILE_PATH, stdout=PIPE, stdin=PIPE, stderr=PIPE)
out, err = p.communicate(blob)
And on the C# side, I got it to work with
Stream ms = Console.OpenStandardInput();
One possibility would be to use something like Python for .NET, which provides interop directly between C# and (standard, C) Python.
Depending on what your Python routines need to do, IronPython can also be a good option, as this is directly consumable and usable from within C#.
Both of these options avoid trying to communicate through the command line, as you have direct access to the Python objects from .NET, and vice versa.

Is there any library out there for c# that has the equivalent to "Unpack" in PHP and what is "Unpack"

I just want to convert a piece of PHP code to C# so I need it's equivalent.
And what does unpack really do? I'm very interested in this function.
Unpack reads the binary data according to the data type you tell it to parse as and returns the values in an array.
The closest thing I can think to this would be to a struct within C(++) / C#, where it populates the struct's members with information from the binary data. A struct within C style languages is like an object, but without methods.
I can't think of any good examples right now on how to read data into a struct, but that's because I'm not really very good at C or C++ or C# for that matter. Try looking at this for examples on how to read data into structs ... or as always ... google it.
Public Shared Function unpack(str As String) As String
Dim x As Integer
Dim rstStr As String = ""
For x = 0 To str.Length - 1
rstStr &= Convert.ToString(Asc(str.Substring(x, 1)), 16)
Next
Return rstStr
End Function

Categories