vb.net AES decryption returns "data is incomplete block" - vb.net

I'm aware of the other thread on this issue (AES decryption error " The input data is not a complete block." Error vb.net), but I'm either not implementing the solutions offered there correctly, or something about my particular variant of this issue isn't covered by those solutions. In any event I'm getting the incomplete block error from the following code
Private GD As System.Security.Cryptography.Aes = System.Security.Cryptography.Aes.Create
Private PDB As New System.Security.Cryptography.Rfc2898DeriveBytes(EK, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
Public Function Decrypt(ByVal val As String) As String
Dim ret As String = Nothing
Dim TTB As New System.Text.UTF8Encoding
Try
Dim input() As Byte = TTB.GetBytes(val)
Using ms As New System.IO.MemoryStream(input)
Using cs As New System.Security.Cryptography.CryptoStream(ms, GD.CreateDecryptor(PDB.GetBytes(32), PDB.GetBytes(16)), Security.Cryptography.CryptoStreamMode.Read)
Using sr As New System.IO.StreamReader(cs)
ret = sr.ReadToEnd()
End Using
End Using
End Using
input = nothing
Catch ex As Exception
EL.AddErr("Encountered an error while decrypting the provided text for " & FName & ". Error Details: " & ex.Message, path)
End Try
Return ret
End Function
EK is my key, which I'll not be including. It's just a String though, nothing special.
I've tried several other methods to decrypt based on guidance on the MSDN site, DreamInCode, etc. None worked, but they all had different issues (typically returning a blank string). Seeing as this version of code closely mirrors my encryption code, I'd like to stick with it (or at least as close as I can while still having functional code).

Despite all comments, I still lack understanding of your intentions. Therefore, the sample code below may not provide what you exactly want, but at least should give an idea how to employ cryptographic functions. Particularly, the most notable difference from your approach is that the encryption key and initialization vector are computed once and for all messages, rather than reevaluated on each occasion, because the latter is prone to synchronization errors — such as when you reuse single crypto object to communicate with multiple parties, or when some messages get lost in transmission.
Public Shared Sub Test()
' Note: You should not actually hard-code any sensitive information in your source files, ever!
Dim sKeyPreimage As String = "MySuperPassword"
Dim oMyCrypto As New MyCrypto(sKeyPreimage)
Dim sPlaintext As String = "My super secret data"
Dim sEncrypted As String = oMyCrypto.EncryptText(sPlaintext)
Dim sDecrypted As String = oMyCrypto.DecryptText(sEncrypted)
Console.Out.WriteLine("Plaintext: {0}", sPlaintext) ' "My super secret data"
Console.Out.WriteLine("Encrypted: {0}", sEncrypted) ' "72062997872DC4B4D1BCBF48D5D30DF0D498B20630CAFA28D584CCC3030FC5F1"
Console.Out.WriteLine("Decrypted: {0}", sDecrypted) ' "My super secret data"
End Sub
Public Class MyCrypto
Private Shared TextEncoding As Text.Encoding = Text.Encoding.UTF8
Private CipherEngine As System.Security.Cryptography.SymmetricAlgorithm
' Note: Unlike in the question, same key and IV are reused for all messages.
Private CipherKey() As Byte
Private CipherIV() As Byte
Public Sub New(ByVal sKeyPreimage As String)
Dim abKeyPreimage() As Byte = TextEncoding.GetBytes(sKeyPreimage)
Dim abKeySalt() As Byte = TextEncoding.GetBytes("Ivan Medvedev")
Const KeyDerivationRounds As Integer = 1 << 12
Dim oKeyDerivationEngine As New System.Security.Cryptography.Rfc2898DeriveBytes(abKeyPreimage, abKeySalt, KeyDerivationRounds)
Me.CipherEngine = System.Security.Cryptography.Aes.Create()
Me.CipherEngine.Padding = Security.Cryptography.PaddingMode.PKCS7
Me.CipherKey = oKeyDerivationEngine.GetBytes(Me.CipherEngine.KeySize >> 3)
Me.CipherIV = oKeyDerivationEngine.GetBytes(Me.CipherEngine.BlockSize >> 3)
End Sub
Public Function Encrypt(ByVal abPlaintext() As Byte) As Byte()
Dim abCiphertext() As Byte
Using hStreamSource As New System.IO.MemoryStream(abPlaintext),
hStreamCipher As New System.Security.Cryptography.CryptoStream(
hStreamSource,
Me.CipherEngine.CreateEncryptor(Me.CipherKey, Me.CipherIV),
Security.Cryptography.CryptoStreamMode.Read),
hStreamTarget As New System.IO.MemoryStream
hStreamCipher.CopyTo(hStreamTarget)
abCiphertext = hStreamTarget.ToArray()
End Using
Return abCiphertext
End Function
Public Function Decrypt(ByVal abCiphertext() As Byte) As Byte()
Dim abPlaintext() As Byte
Using hStreamSource As New System.IO.MemoryStream(abCiphertext),
hStreamCipher As New System.Security.Cryptography.CryptoStream(
hStreamSource,
Me.CipherEngine.CreateDecryptor(Me.CipherKey, Me.CipherIV),
Security.Cryptography.CryptoStreamMode.Read),
hStreamTarget As New System.IO.MemoryStream
hStreamCipher.CopyTo(hStreamTarget)
abPlaintext = hStreamTarget.ToArray()
End Using
Return abPlaintext
End Function
Public Function EncryptText(ByVal sPlaintext As String) As String
Dim abPlaintext() As Byte = TextEncoding.GetBytes(sPlaintext)
Dim abCiphertext() As Byte = Me.Encrypt(abPlaintext)
Dim sCiphertext As String = Hex.Format(abCiphertext)
Return sCiphertext
End Function
Public Function DecryptText(ByVal sCiphertext As String) As String
Dim abCiphertext() As Byte = Hex.Parse(sCiphertext)
Dim abPlaintext() As Byte = Me.Decrypt(abCiphertext)
Dim sPlaintext As String = TextEncoding.GetChars(abPlaintext)
Return sPlaintext
End Function
End Class
Public Class Hex
Public Shared Function Format(ByVal abValue() As Byte) As String
Dim asChars(0 To abValue.Length * 2 - 1) As Char
Dim ndxChar As Integer = 0
For ndxByte As Integer = 0 To abValue.Length - 1
Dim bNibbleHi As Byte = abValue(ndxByte) >> 4, bNibbleLo As Byte = CByte(abValue(ndxByte) And &HFUS)
asChars(ndxChar) = Convert.ToChar(If(bNibbleHi <= 9, &H30US + bNibbleHi, &H37US + bNibbleHi)) : ndxChar += 1
asChars(ndxChar) = Convert.ToChar(If(bNibbleLo <= 9, &H30US + bNibbleLo, &H37US + bNibbleLo)) : ndxChar += 1
Next
Return New String(asChars)
End Function
Public Shared Function Parse(ByVal sValue As String) As Byte()
If String.IsNullOrEmpty(sValue) Then Return New Byte() {}
If (sValue.Length Mod 2) > 0 Then Return Nothing
Dim ndxText As Integer = 0
Dim ndxByteMax As Integer = (sValue.Length \ 2) - 1
Dim abValue(0 To ndxByteMax) As Byte
Try
For ndxByte As Integer = 0 To ndxByteMax
abValue(ndxByte) = Convert.ToByte(sValue.Substring(ndxText, 2), 16)
ndxText += 2
Next
Catch ex As Exception
Return Nothing
End Try
Return abValue
End Function
End Class
Again, please, note that this is just an example. I am not endorsing any kind of protection techniques shown here, especially because your task remains unknown. The code above simply illustrates the syntax and semantics — not how to do it right.

Related

How to translate this javascript code to vb.net

It's a simple code
var contentHash = CryptoJS.SHA512(JSON.stringify(requestBody)).toString(CryptoJS.enc.Hex);
Also it's actually simpler. I think requestBody is just an empty string.
https://bittrex.github.io/api/v3#topic-Authentication
What I tried is to do
Dim hasher = New System.Security.Cryptography.HMACSHA512(System.Text.Encoding.UTF8.GetBytes(""))
Dim contentHash = ExchangesClass.getString(hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes("")))
Where ExchangeClass.getString is
Public Shared Function getString(sigs As Byte()) As String
Dim list = New Generic.List(Of String)
For Each b In sigs
Dim chunk = b.ToString("x2")
list.Add(chunk)
Next
Dim result = String.Concat(list)
Dim result2 = BitConverter.ToString(sigs).Replace("-", "").ToLower()
Debug.Assert(result = result2)
Return result
End Function
But that's sort of weird. Why would anyone want a hash of an empty string. Unless I am missing something. I do not see where requestBody is. Perhaps because I use only read only API of bittrex
This code works
So
var contentHash = CryptoJS.SHA512(JSON.stringify(requestBody)).toString(CryptoJS.enc.Hex);
becomes
Protected Overridable Function computeSigNoHmac(content As String) As String
Dim hasher2 = New System.Security.Cryptography.SHA512Managed() 'create hashers based on those bytes
Dim hashbytes = hasher2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content)) 'compute the hash and get bytes
Dim sighash2 = BitConverter.ToString(hashbytes).Replace("-", "").ToLower() 'turn bytes into hex string (0-9a-f)
Return sighash2
End Function
Also, for completion,
var signature = CryptoJS.HmacSHA512(preSign, apiSecret).toString(CryptoJS.enc.Hex);
Becomes
Protected Overridable Function computeSig(content As String, secret As String) As String
Dim secretinBytes = System.Text.Encoding.UTF8.GetBytes(secret) 'Turn secret hex into bytes (0-9a-f)
Dim hasher2 = New System.Security.Cryptography.HMACSHA512(secretinBytes) 'create hashers based on those bytes
'Dim hasher3 = New System.Security.Cryptography.SHA512(secretinBytes) 'create hashers based on those bytes
Dim hashbytes = hasher2.ComputeHash(System.Text.Encoding.UTF8.GetBytes(content)) 'compute the hash and get bytes
Dim sighash2 = BitConverter.ToString(hashbytes).Replace("-", "").ToLower() 'turn bytes into hex string (0-9a-f)
Return sighash2
End Function

VB.NET - Randomize() with a function call in a string.replace method

I have a chat system and i want to put a "random string generator".
In my chat i have to write "%random%" and it is replaces with a random string.
I have a problem though, if i type "%random%%random%%random%" for example, it will generate the same string 3 times.
• Here is my function:
Public Function getRandomString(ByVal len As Integer) As String
Randomize()
Dim stringMap as string = "abcdefghijklmnopqrstuwvxyz0123456789"
Dim rndString As String = ""
Dim rnd As New Random()
For i As Integer = 0 To len - 1
Randomize()
rndString &= stringMap.Substring(rnd.Next(0, stringMap.Length), 1)
Next
Return rndString
End Function
• And here is my function call:
Dim msg As String = "Random string: %random%%random%%random%"
msg = msg.Replace("%random%", getRandomString(8))
MsgBox(msg)
The output for example: Random string: 5z15if725z15if725z15if72
I guess this is because it keeps the 1st return value in memory and pastes it, how can i fix that ?
Do i have to make a string.replace function myself ? Thanks
Oh no! You shouldn't call Randomize() here at all! Random is used in combination with the Rnd() function of VB. Creating a new Random object is enough here.
The reason you are getting the same results every time is because you are creating a new Random every time. You should reuse the same object to get different results.
'Create the object once
Private Shared rnd As New Random()
Public Function getRandomString(ByVal len As Integer) As String
Dim stringMap as string = "abcdefghijklmnopqrstuwvxyz0123456789"
Dim rndString As String = ""
For i As Integer = 0 To len - 1
rndString &= stringMap.Substring(rnd.Next(0, stringMap.Length), 1)
Next
Return rndString
End Function
EDIT: I realize that in addition to the above changes, you need to call the getRandomString function for every "%random%". String.Replace only calls the function once and pastes the result everywhere. With Regex, you could do something like this:
msg = new Regex("%random%").Replace(input, Function (match) getRandomString(8))
An easy way to do it is to find the first occurrence of "%random%", replace that, then repeat as necessary.
Written as a console application:
Option Infer On
Module Module1
Dim rand As New Random
Public Function getRandomString(ByVal len As Integer) As String
Dim stringMap As String = "abcdefghijklmnopqrstuwvxyz0123456789"
Dim rndString As String = ""
For i As Integer = 0 To len - 1
rndString &= stringMap.Substring(rand.Next(0, stringMap.Length), 1)
Next
Return rndString
End Function
Function ReplaceRandoms(s As String) As String
Dim stringToReplace = "%random%"
Dim r = s.IndexOf(stringToReplace)
While r >= 0
s = s.Remove(r, stringToReplace.Length).Insert(r, getRandomString(stringToReplace.Length))
r = s.IndexOf(stringToReplace)
End While
Return s
End Function
Sub Main()
Dim msg As String = "Random string: %random%%random%%random%"
msg = ReplaceRandoms(msg)
Console.WriteLine(msg)
Console.ReadLine()
End Sub
End Module

Split string after the = sign

I can't seem to work out how to get a value from my string using VB.net
If I have a string in my textbox that says:
WWW-Authenticate: Digest realm="MyServer",qop="auth",algorithm="MD5",maxbuf=1000,nonce="3b010c090c0a0000c0a80157c7007f03c5",opaque="4e6573732041636365737320436f6e74"
How can I get each of the values after the = in the string.
I have tried using
Dim s = "WWW-Authenticate: Digest realm='MyServer',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
Dim pattern = "="
Dim matches = Regex.Matches(s, pattern)
Dim values = matches.OfType(Of Match).Select(Function(m) m.Value)
For Each v In values
MsgBox(v)
Next
But it only returns the = in the messagebox.
I want to be able to get just the part after the = sign.
Anyone able to help?
I have tried using the following but it still includes the realm= qop= etc.. in the string. (but includes it at the end of the next item.
Dim s = "WWW-Authenticate: Digest realm='Ness Access Control',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
Dim result_array As Array = Split(s, "=", 6)
For Each v In result_array
MsgBox(v)
Next
Regular Expressions!
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim s As String = "WWW-Authenticate: Digest realm='MyServer',qop='auth',algorithm='MD5',maxbuf=1000,nonce='3b010c090c0a0000c0a80157c7007f03c5',opaque='4e6573732041636365737320436f6e74'"
'Regular Expression, matches word before equals, and word after equals
Dim r As New Regex("(\w+)\='([^']+)'")
'All the matches!
Dim matches As MatchCollection = r.Matches(s)
For Each m As Match In matches
'm.Groups(1) = realm, qop, algorithm...
'm.Groups(2) = MyServer, auth, MD5...
Console.WriteLine(m.Groups(2))
Next
Console.ReadLine()
End Sub
End Module
And if you want everything in a nice key-value dictionary:
Dim dict As New Dictionary(Of String, String)
For Each m As Match In matches
'm.Groups(1) = realm, qop, algorithm...
'm.Groups(2) = MyServer, auth, MD5...
dict(m.Groups(1).ToString()) = dict(m.Groups(2).ToString())
Next
A case for a specific string extension.
How to transform a specific formatted string in a Dictionary with keys and values
Public Module StringModuleExtensions
<Extension()>
Public Function ToStringDictionary(ByVal str as String, _
ByVal OuterSeparator as Char, _
ByVal NameValueSeparator as Char) _
As Dictionary(of String, String)
Dim dicText = New Dictionary(Of String, String)()
if Not String.IsNullOrEmpty(str) then
Dim arrStrings() = str.TrimEnd(OuterSeparator).Split(OuterSeparator)
For Each s in arrStrings
Dim posSep = s.IndexOf(NameValueSeparator)
Dim name = s.Substring(0, posSep)
Dim value = s.Substring(posSep + 1)
dicText.Add(name, value)
Next
End If
return dicText
End Function
End Module
Call with
Dim test = "WWW-Authenticate: Digest realm=""MyServer"",qop=""auth"",algorithm=""MD5"", maxbuf=1000,nonce=""3b010c090c0a0000c0a80157c7007f03c5"",opaque=""4e6573732041636365737320436f6e74"""
Dim dict = test.ToStringDictionary(","c, "="c)
For Each s in dict.Keys
Console.WriteLine(dict(s))
Next
(probably you need to remove the WWW-Authenticate line before.
You are looking for the split() function.
Dim logArray() As String
logArray = Split(s, "=")
For count = 0 To logArr.Length - 1
MsgBox(logArray(count))
Next

build/check hash value for file

I'm having hard time with this one. Can someone either point me in the right direction for checking/building hash codes for an uploaded file or else tell me what I'm doing wrong with the code below?
getFileSHA256(softwareUpload.PostedFile) 'Line that calls the function includes a reference to an uploaded file
Private Function getFileSHA256(ByVal theFile As Web.HttpPostedFile) As String
Dim SHA256CSP As New SHA256Managed()
Dim byteHash() As Byte = SHA256CSP.ComputeHash(theFile.InputStream)
Return ByteArrayToString(byteHash)
End Function
Private Function ByteArrayToString(ByVal arrInput() As Byte) As String
Dim sb As New System.Text.StringBuilder(arrInput.Length * 2)
For i As Integer = 0 To arrInput.Length - 1
sb.Append(arrInput(i).ToString("X2"))
Next
Return sb.ToString().ToLower
End Function
I should add that the function works, but the return does not match other programs' sha256 values.
EDIT ------
There are two other functions that I'm using in my code. SHA1 gets the same kind of results as the SHA256; the results do not match trusted sources.
However, the MD5 works as expected.
Private Function getFileSHA1(ByVal theFile As Web.HttpPostedFile) As String
Dim SHA1CSP As New SHA1CryptoServiceProvider()
Dim byteHash() As Byte = SHA1CSP.ComputeHash(theFile.InputStream)
Return ByteArrayToString(byteHash)
End Function
Private Function getFileMd5(ByVal theFile As Web.HttpPostedFile) As String
Dim Md5CSP As New System.Security.Cryptography.MD5CryptoServiceProvider
Dim byteHash() As Byte = Md5CSP.ComputeHash(theFile.InputStream)
Return ByteArrayToString(byteHash)
End Function
I plan to consolidate these functions once I know they are working as expected.
The only difference between these is that MD5 is using "MD5CryptoServiceProvider" and it works as expected. SHA1 is also using "SHA1CryptoServiceProvider" but it does not match trusted sources.
I did some testing here, it appears that for text files SHA256Managed works perfectly.
My code is below, I used your implementation of ByteArrayToString:
Sub Main()
Dim s As New SHA256Managed
Dim fileBytes() As Byte = IO.File.ReadAllBytes("s:\sha256.txt")
Dim hash() As Byte = s.ComputeHash(fileBytes)
Dim referenceHash As String = "18ffd9682c5535a2b2798ca51b13e9490df326f185a83fe6e059f8ff47d92105"
Dim calculatedHash As String = ByteArrayToString(hash)
MsgBox(calculatedHash = referenceHash) 'outputs True
End Sub
Private Function ByteArrayToString(ByVal arrInput() As Byte) As String
Dim sb As New System.Text.StringBuilder(arrInput.Length * 2)
For i As Integer = 0 To arrInput.Length - 1
sb.Append(arrInput(i).ToString("X2"))
Next
Return sb.ToString().ToLower
End Function
For testing purposes, I created a file called sha256.txt under S: with the following contents:
my test file
(no trailing spaces or newline)
I got the reference hash value from here, by feeding same data.
Also check this and this - the fact you get non-match could be related to platform and/or implementation of your trusted source, or needing an extra conversion step.

How to correctly read a random access file in VB.NET

I am attempting to read a random access file, but I am getting the following error on the first file Error 5 (unable to read beyond end of the stream). I am not sure what I am doing wrong here, how might I fix this issue?
Structure StdSections
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(15), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=15)> Public A() As Char 'BEAM --- complete beam designation 15
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(2), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2)> Public B() As Char 'DSG --- shape ie "W" or "C" 2
Dim C As Single 'DN --- nominal depth of section 4
Dim d As Single 'WGT --- weight 4
.
.
.
End structure
''Note 'File1'is the existing RAF and holds complete path!
Dim i,ffr,fLength,lastmembNo as integer
sectionFound = False
Dim std As new StdSections
fLength = Len(std)
If fLength = 0 Then fLength = 168 ' 177
ffr = FreeFile()
FileOpen(ffr, File1, OpenMode.Random, OpenAccess.Read, OpenShare.LockRead, fLength)
lastmembNo = CInt(LOF(ffr)) \ fLength
For i = 1 To lastmembNo
FileGet(ffr, std, i)
>>Error 5 (unable to read beyond end of the stream) <<<
If Trim(memberID) = Trim(std.A) Then
sectionFound = True
end if
next i
Wow Freefile! That's a blast from the past!
I haven't really used the old OpenFile etc. file access methods in VB.NET, so I'm just speculating, but in .NET many of the variable types got changed in size. e.g. an Integer is now 32-bits (4 bytes), I think a Boolean is different, though a Single is still 4 bytes.
Also, strings in .NET are by default in Unicode, not ASCII, so you cannot rely on 1 character=1 byte in a .NET String variable. In fact, .NET actualy "JIT compiles" programs on the PC before running, so you can't really lay out structures in memory easily like the old days.
If you want to switch to the new "Stream" based objects, here's some code to get you started:
Dim strFilename As String = "C:\Junk\Junk.txt"
Dim strTest As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Call My.Computer.FileSystem.WriteAllText(strFilename, strTest, False)
Dim byt(2) As Byte
Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
fs.Seek(16, SeekOrigin.Begin)
fs.Read(byt, 0, 3)
Dim s As String = Chr(byt(0)) & Chr(byt(1)) & Chr(byt(2))
MsgBox(s)
fs.Seek(5, SeekOrigin.Begin)
fs.Write(byt, 0, 3)
End Using
Dim strModded As String = My.Computer.FileSystem.ReadAllText(strFilename)
MsgBox(strModded)
I wouldn't blame you for keeping the old method though: with the new method, you'll need to define a class, and then have a custom routine to convert from Byte() to the properties of the class. More work than simply loading bytes from the file into memory.
OK, I think you should switch to the ".NET way", as follows:
Imports System.IO
Imports System.Xml
Public Class Form1
Public Const gintRecLen_CONST As Integer = 177
Class StdSections2
Private mstrA As String
Public Property A() As String
Get
Return mstrA
End Get
Set(ByVal value As String)
If value.Length <> 15 Then
Throw New Exception("Wrong size")
End If
mstrA = value
End Set
End Property
Private mstrB As String
Public Property B() As String
Get
Return mstrB
End Get
Set(ByVal value As String)
If value.Length <> 2 Then
Throw New Exception("Wrong size")
End If
mstrB = value
End Set
End Property
Public C(39) As Single
Public Shared Function FromBytes(byt() As Byte) As StdSections2
Dim output As New StdSections2
If byt.Length <> gintRecLen_CONST Then
Throw New Exception("Wrong size")
End If
For i As Integer = 0 To 14
output.mstrA &= Chr(byt(i))
Next i
For i As Integer = 15 To 16
output.mstrB &= Chr(byt(i))
Next i
For i As Integer = 0 To 39
Dim bytTemp(3) As Byte
output.C(i) = BitConverter.ToSingle(byt, 17 + 4 * i)
Next i
Return output
End Function
End Class
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim strFilename As String = "C:\Junk\Junk.txt"
Dim strMemberID As String = "foo"
Dim intRecCount As Integer = CInt(My.Computer.FileSystem.GetFileInfo(strFilename).Length) \ gintRecLen_CONST
Dim blnSectionFound As Boolean = False
Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
For intRec As Integer = 0 To intRecCount - 1
Dim intRecPos As Integer = gintRecLen_CONST * intRec
fs.Seek(intRecPos, SeekOrigin.Begin)
Dim byt(gintRecLen_CONST - 1) As Byte
fs.Read(byt, 0, gintRecLen_CONST)
Dim ss2 As StdSections2 = StdSections2.FromBytes(byt)
'MsgBox(ss2.A & ":" & ss2.C(3)) 'debugging
If strMemberID.Trim = ss2.A.Trim Then
blnSectionFound = True
Exit For
End If
Next intRec
End Using
MsgBox(blnSectionFound.ToString)
End Sub
End Class
We define a class called StdSections2 which uses .NET strings and an array of Singles. We use 0-based arrays everywhere. We load the file using the new FileStream object, and use the Seek() command to find the position we want. We then load raw bytes out of the file, and use Chr() and BitConverter.ToSingle() to convert the raw bytes into strings and singles.
I'm not sure about your example but this one however, works:
Public Class Form1
Const maxLenName = 30
Structure person
<VBFixedString(maxLenName)> Dim name As String
Dim age As Byte
End Structure
Private Sub Form1_Load(sender As [Object], e As EventArgs) Handles MyBase.Load
Dim entryIn As New person
Dim recordLen As Integer = Len(entryIn)
Dim entry As person
If FileIO.FileSystem.FileExists("test.raf") Then Kill("test.raf")
FileOpen(1, "test.raf", OpenMode.Random,,, recordLen)
'write
entry.name = LSet("Bill", maxLenName)
entry.age = 25
FilePut(1, entry, 6) 'write to 6th record
'read
Dim nRecords As Integer = LOF(1) \ recordLen
FileGet(1, entryIn, nRecords)
FileClose(1)
Dim personName As String = RTrim(entryIn.name)
Dim personAge As Byte = entryIn.age
MsgBox(personName & "'s age is " & personAge)
End Sub
End Class