I am instantiating a deserializing class to fetch data from a binary-formatted data file. This appraoch seems to work fine most of the time, except when some of the data files get larger than 2-4 MB, and the following exception is thrown (at the code line with comments, below):
"The runtime has encountered a fatal error. The address of the error was at 0x722de24f, on thread 0x30e0. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack."
Here is the code:
<Serializable()>
Public Class deserializedata
Public Property sernumrows As Integer
Public Property sernumcols As Integer
Public Property serx As Object(,)
Public snumrows, snumcols As Integer
Public sx As Object(,)
Sub New(ByRef snumrows As Integer, ByRef snumcols As Integer, ByRef sx(,) As Object, ByVal sfilename as String)
Dim param_obj(0) As Object
param_obj(0) = sfilename
Call deser(param_obj)
End Sub
Sub deser(ByVal param_obj)
sfilename = param_obj(0)
Using stream As FileStream = File.Open(sfilename, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim formatter As New BinaryFormatter()
Dim myser As Object = formatter.Deserialize(stream) 'this is where exception is being thrown
snumrows = myser.sernumrows
snumcols = myser.sernumcols
sx = myser.serx
stream.Close()
End Using
End Sub
End Class
Related
I am trying to retrieve Sharepoint list data using Microsoft.Sharepoint.Client library using vb.net windows form.
Below is the vb.net code for reference.
Imports Microsoft.SharePoint.Client
Public Class sharepoint_list
Private client_context As ClientContext
Private Sub sharepoint_list_Load(sender As Object, e As EventArgs) Handles MyBase.Load
client_context = New ClientContext("siteurl#user.com")
Dim web_ As Web = client_context.Web
client_context.Credentials = New SharePointOnlineCredentials("user#user.com", GetPassword("user#user.com", "mypass#123"))
client_context.Load(web_)
client_context.ExecuteQuery()
MsgBox(web_.Title)
End Sub
Public Function GetPassword(username As String, password As String) As Security.SecureString
Dim keyinfo As ConsoleKeyInfo
Dim securePass As Security.SecureString
securePass = New Security.SecureString
For Each c As Char In password
securePass.AppendChar(keyinfo.KeyChar)
Next
Return securePass
End Function
End Class
Whenever I try to run this piece of code, It throws an error with the following message
'.', hexadecimal value 0x00, is an invalid character.
and the following message on the console
A first chance exception of type 'System.ArgumentException' occurred
in System.Xml.dll
Any help would be appreciable.
Thanks in advance.
Modify the GetPassword method as below:
Public Function GetPassword(password As String) As Security.SecureString
Dim securePass As Security.SecureString
securePass = New Security.SecureString
For Each c As Char In password
securePass.AppendChar(c)
Next
Return securePass
End Function
Change the line of code below
client_context.Credentials = New SharePointOnlineCredentials("user#user.com", GetPassword("user#user.com", "mypass#123"))
to
client_context.Credentials = New SharePointOnlineCredentials("user#user.com", GetPassword("mypass#123"))
I was wondering, how can I get the percentage of this being done, so I can display it on a progress bar?
ZipFile.CreateFromDirectory("C:\temp\folder", "C:\temp\folder.zip")
and also
ZipFile.ExtractToDirectory("C:\temp\folder.zip", "C:\temp\folder")
This doesnt have any events or callbacks that you can use to report progress. Simply means you cant with the .Net version. If you used the 7-Zip library you can do this easily.
I came across this question while checking for related questions for the identical question, asked for C# code. It is true that the .NET static ZipFile class does not offer progress reporting. However, it is not hard to do using the ZipArchive implementation, available since earlier versions of .NET.
The key is to use a Stream wrapper that will report bytes read and written, and insert that in the data pipeline while creating or extracting the archive.
I wrote a version in C# for an answer to the other question, and since I didn't find any VB.NET examples, figured it would be helpful to include a VB.NET version on this question.
(Arguably, I could include both examples in a single answer and propose closing one of the questions as a duplicate of the other. But since it's doubtful the close vote would result in an actual closure, the connection between the two questions would not be as obvious as it should be. I think for best visibility to future users trying to find the solution appropriate for their needs, leaving this as two different questions is better.)
The foundation of the solution is the Stream wrapper class:
StreamWithProgress.vb
Imports System.IO
Public Class StreamWithProgress
Inherits Stream
' NOTE For illustration purposes. For production code, one would want To
' override *all* of the virtual methods, delegating to the base _stream object,
' to ensure performance optimizations in the base _stream object aren't
' bypassed.
Private ReadOnly _stream As Stream
Private ReadOnly _readProgress As IProgress(Of Integer)
Private ReadOnly _writeProgress As IProgress(Of Integer)
Public Sub New(Stream As Stream, readProgress As IProgress(Of Integer), writeProgress As IProgress(Of Integer))
_stream = Stream
_readProgress = readProgress
_writeProgress = writeProgress
End Sub
Public Overrides ReadOnly Property CanRead As Boolean
Get
Return _stream.CanRead
End Get
End Property
Public Overrides ReadOnly Property CanSeek As Boolean
Get
Return _stream.CanSeek
End Get
End Property
Public Overrides ReadOnly Property CanWrite As Boolean
Get
Return _stream.CanWrite
End Get
End Property
Public Overrides ReadOnly Property Length As Long
Get
Return _stream.Length
End Get
End Property
Public Overrides Property Position As Long
Get
Return _stream.Position
End Get
Set(value As Long)
_stream.Position = value
End Set
End Property
Public Overrides Sub Flush()
_stream.Flush()
End Sub
Public Overrides Sub SetLength(value As Long)
_stream.SetLength(value)
End Sub
Public Overrides Function Seek(offset As Long, origin As SeekOrigin) As Long
Return _stream.Seek(offset, origin)
End Function
Public Overrides Sub Write(buffer() As Byte, offset As Integer, count As Integer)
_stream.Write(buffer, offset, count)
_writeProgress?.Report(count)
End Sub
Public Overrides Function Read(buffer() As Byte, offset As Integer, count As Integer) As Integer
Dim bytesRead As Integer = _stream.Read(buffer, offset, count)
_readProgress?.Report(bytesRead)
Return bytesRead
End Function
End Class
The wrapper class can be used to implement progress-aware versions of the ZipFile static methods:
ZipFileWithProgress.vb
Imports System.IO
Imports System.IO.Compression
NotInheritable Class ZipFileWithProgress
Private Sub New()
End Sub
Public Shared Sub CreateFromDirectory(
sourceDirectoryName As String,
destinationArchiveFileName As String,
progress As IProgress(Of Double))
sourceDirectoryName = Path.GetFullPath(sourceDirectoryName)
Dim sourceFiles As FileInfo() = New DirectoryInfo(sourceDirectoryName).GetFiles("*", SearchOption.AllDirectories)
Dim totalBytes As Double = sourceFiles.Sum(Function(f) f.Length)
Dim currentBytes As Long = 0
Using archive As ZipArchive = ZipFile.Open(destinationArchiveFileName, ZipArchiveMode.Create)
For Each fileInfo As FileInfo In sourceFiles
' NOTE: naive method To Get Sub-path from file name, relative to
' input directory. Production code should be more robust than this.
' Either use Path class Or similar to parse directory separators And
' reconstruct output file name, Or change this entire method to be
' recursive so that it can follow the sub-directories And include them
' in the entry name as they are processed.
Dim entryName As String = fileInfo.FullName.Substring(sourceDirectoryName.Length + 1)
Dim entry As ZipArchiveEntry = archive.CreateEntry(entryName)
entry.LastWriteTime = fileInfo.LastWriteTime
Using inputStream As Stream = File.OpenRead(fileInfo.FullName)
Using outputStream As Stream = entry.Open()
Dim progressStream As Stream = New StreamWithProgress(inputStream,
New BasicProgress(Of Integer)(
Sub(i)
currentBytes += i
progress.Report(currentBytes / totalBytes)
End Sub), Nothing)
progressStream.CopyTo(outputStream)
End Using
End Using
Next
End Using
End Sub
Public Shared Sub ExtractToDirectory(
sourceArchiveFileName As String,
destinationDirectoryName As String,
progress As IProgress(Of Double))
Using archive As ZipArchive = ZipFile.OpenRead(sourceArchiveFileName)
Dim totalBytes As Double = archive.Entries.Sum(Function(e) e.Length)
Dim currentBytes As Long = 0
For Each entry As ZipArchiveEntry In archive.Entries
Dim fileName As String = Path.Combine(destinationDirectoryName, entry.FullName)
Directory.CreateDirectory(Path.GetDirectoryName(fileName))
Using inputStream As Stream = entry.Open()
Using outputStream As Stream = File.OpenWrite(fileName)
Dim progressStream As Stream = New StreamWithProgress(outputStream, Nothing,
New BasicProgress(Of Integer)(
Sub(i)
currentBytes += i
progress.Report(currentBytes / totalBytes)
End Sub))
inputStream.CopyTo(progressStream)
End Using
End Using
File.SetLastWriteTime(fileName, entry.LastWriteTime.LocalDateTime)
Next
End Using
End Sub
End Class
The .NET built-in implementation of IProgress(Of T) is intended for use in contexts where there is a UI thread where progress reporting events should be raised. As such, when used in a console program, like which I used to test this code, it will default to using the thread pool to raise the events, allowing for the possibility of out-of-order reports. To address this, the above uses a simpler implementation of IProgress(Of T), one that simply invokes the handler directly and synchronously.
BasicProgress.vb
Class BasicProgress(Of T)
Implements IProgress(Of T)
Private ReadOnly _handler As Action(Of T)
Public Sub New(handler As Action(Of T))
_handler = handler
End Sub
Private Sub Report(value As T) Implements IProgress(Of T).Report
_handler(value)
End Sub
End Class
And naturally, it's useful to have an example with which to test and demonstrate the code.
Module1.vb
Imports System.IO
Module Module1
Sub Main(args As String())
Dim sourceDirectory As String = args(0),
archive As String = args(1),
archiveDirectory As String = Path.GetDirectoryName(Path.GetFullPath(archive)),
unpackDirectoryName As String = Guid.NewGuid().ToString()
File.Delete(archive)
ZipFileWithProgress.CreateFromDirectory(sourceDirectory, archive,
New BasicProgress(Of Double)(
Sub(p)
Console.WriteLine($"{p:P2} archiving complete")
End Sub))
ZipFileWithProgress.ExtractToDirectory(archive, unpackDirectoryName,
New BasicProgress(Of Double)(
Sub(p)
Console.WriteLine($"{p:P0} extracting complete")
End Sub))
End Sub
End Module
Additional notes regarding this implementation can be found in my answer to the related question.
I'm trying to call the method 'MyMethod' of class 'CMyClass'. This method has a parameter of type "CBaseClass", and I'm passing an object of type "CDerivedClass".
Class CBaseClass
Public m_AMember As String
Sub MethodOne()
// DoSomething
End Sub
End Class
Class CDerivedClass
Inherits CBaseClass
Public m_MyMember As Integer
Sub MethodTwo()
// DoSomething
End Sub
End Class
Class CMyClass
Sub MyMethod(ByVal obj As CBaseClass)
// DoSomething
End Sub
End Class
Sub Main()
'load assembly
Dim objAssembly As Assembly = Assembly.LoadFrom("myfile.dll")
'create class instance and MethodInfo object
Dim t As Type = objAssembly.GetType("MyNamespace.CMyClass")
Dim obj As Object = Activator.CreateInstance(t)
Debug.Assert(obj IsNot Nothing)
Dim m As MethodInfo = t.GetMethod("MyMethod")
Debug.Assert(m IsNot Nothing)
'Init arguments (only one)
Dim par As New CDerivedClass()
Dim parameters As Object() = New Object(0) {par}
'invoke method
m.Invoke(obj, parameters) '<<<< ArgumentException here!
End Sub
The argument exception says "object of type 'MyNamespace.CDerivedClass' cannot be converted to type 'MyNamespace.CBaseClass'.
I changed "ByRef" to "ByVal" in MyMethod signature, but nothing changed.
I tried to change type of 'par' object with:
Dim par As CBaseClass = New CDerivedClass()
without success.
How I can invoke correctly the method "MyMethod" with an instance of derived class?
Thank you very much.
I just tried your code in a stand alone project and it worked fine. I only adjusted the assembly line to get the current assembly instead of from a file, and I changed the name in GetType to reflect my namespace. My guess is that perhaps your DLL you are loading is out of date, or you have duplicate definitions of the classes in your calling assembly, and thats why it cannot do the type conversion.
Imports System.Reflection
Module Module1
Sub Main()
'load assembly
Dim objAssembly As Assembly = Assembly.GetExecutingAssembly()
'create class instance and MethodInfo object
Dim t As Type = objAssembly.GetType("ConsoleApplication1.CMyClass")
Dim obj As Object = Activator.CreateInstance(t)
Debug.Assert(obj IsNot Nothing)
Dim m As MethodInfo = t.GetMethod("MyMethod")
Debug.Assert(m IsNot Nothing)
'Init arguments (only one)
Dim par As New CDerivedClass()
Dim parameters As Object() = New Object(0) {par}
'invoke method
m.Invoke(obj, parameters) '<<<< No ArgumentException here!
End Sub
End Module
Class CBaseClass
Public m_AMember As String
Sub MethodOne()
End Sub
End Class
Class CDerivedClass
Inherits CBaseClass
Public m_MyMember As Integer
Sub MethodTwo()
End Sub
End Class
Class CMyClass
Sub MyMethod(ByVal obj As CBaseClass)
End Sub
End Class
Finally I solved using serialization...
So 'par' is the string containing the serialized object of type CDerivedClass in the calling project.
MyMethod is changed to:
MyMethod(xml_CBaseClass As String)
In dll project the string parameter xml_CBaseClass is deserialized creating an object of CBaseClass.
Note: since I have derived type, Deserialization of derived class give another problem. The solution is https://stackoverflow.com/a/590711/1315873
(I just made a little change, using StringWriter for serialization, StringReader for deserialization, instead of using MemoryBuffer).
CBaseClass has fixed derived types so I wrote them hard-coded, but to be flexible you can do something like:
Dim subTypes as New List(Of Type) '<- all classes derived from 'myType'
For Each t In myType.Assembly.GetTypes()
If t.IsSubclassOf(myType) Then
subTypes.Add(t)
End If
Next
CBaseClass and all its derivated classes must have constructor New() without parameters.
I load assemblies using LoadFrom() since I don't know their names (I use Dir() to get all them from a known fixed folder).
I have just learnt how to set up a GUI in a separate thread...
Private myGui As SomeGui
Public Class myAsyncState
Public a As Boolean = True
Public b As Integer = 100
End Class
Public Sub Caller()
'
myGui = New SomeGui()
' setup
myGui.Begin()
Dim a as Boolean = False
Dim b as Integer = 1
Dim state As myAsyncState = New myAsyncState(a, b)
Dim step1 As New xDelegate(AddressOf xMethod)
Dim callBack As New AsyncCallback(AddressOf xMethod_Callback)
Dim asyncResultTest As IAsyncResult = step1.BeginInvoke(a, b, callBack, state)
End Sub
Private Delegate Sub xDelegate(Byval a as Integer, ByVal b As Boolean)
Public Sub xMethod(Byval a as Integer, ByVal b As Boolean)
End Sub
Private Sub xMethod_Callback(ByVal ia As IAsyncResult)
Dim myAsyncResult As AsyncResult = CType(ia, AsyncResult)
Dim myAsyncMethodCaller As xDelegate = CType(myAsyncResult.AsyncDelegate, xDelegate)
Dim state As myAsyncState = CType(myAsyncResult.AsyncState, myAsyncState)
myAsyncMethodCaller.EndInvoke(ia)
xMethod_Finish(state.a, state.b)
End Sub
Private Sub xMethod_Finish(ByVal a As Integer, ByVal b As Boolean)
If Me.InvokeRequired Then
Invoke(New xDelegate(AddressOf xMethod_Finish), New Object() {a, b}) ' here
' Also tried Invoke(New xDelegate(AddressOf xMethod_Finish), a, b) though the above is what I have seen in documentation
' also tried to make Dim state As myAsyncState = New myAsyncState(a, b) and use it as an argument
Else
yMethod(a, b)
myGui.Finish()
End If
End Sub
I was returning and passing values, it was all so good... and then I returned to it to test it, and got an error:
A first chance exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
An unhandled exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in System.Windows.Forms.dll
Additional information: The given key was not present in the dictionary.
The exception was after "xMethod" completed, on the line I show "here" - in the xMethod_Finish. It looks like there are some mismatched parameters - but I thought I had them all correct - and I put a lot of effort in understanding how to pass parameters to the delegate, so that they can also be passed to the subsequent method, after the EndInvoke of the first one (that will still be in the GUI thread).
Please help me see what I am doing wrong. Thank you.
Your invokation looks correct.
The error is likely in the yMethod or myGui.Finish() methods. Exceptions can become a little hidden when they occur in an invoked method. Check the exception's InnerException property to gain more information and the stack trace of what's causing the KeyNotFoundException.
You can set a breakpoint in the problem methods to debug the error.
In VB.NET, I am trying to retrieve what services are running on a TS using the following code:
Imports System.ServiceProcess
...
Dim dictservice As Generic.Dictionary(Of String, Services)
Public Sub GetService()
Dim localServices As ServiceController() = ServiceController.GetServices()
For Each service As ServiceController In localServices
dictservice.Add(service.DisplayName, New Services(service.DisplayName, service.ServiceName, service.Status.ToString))
Next
End Sub
My services class is as follows:
Class Services
Private _displayName As String
Private _serviceName As String
Private _serviceStatus As String
Sub New(ByVal DisplayName As String, ByVal ServiceName As Object, ByVal ServiceStatus As String)
_displayName = DisplayName
_serviceName = ServiceName
_serviceStatus = ServiceStatus
End Sub
Public Overrides Function ToString() As String
Return _serviceStatus
End Function
End Class
When i step through in debug mode it seems to being to populate the dictionary
display name: Application Experience
service name: AElookUpSVC
service status: Running (4)
When it tries to move onto the next item i get the following error:
Null reference exception was unhandled:
Object reference not set to an instance of an object.
I can't for the life of me work out where it is finding a null reference?
You need to initialize your dictionary with New:
Dim dictservice As New Generic.Dictionary(Of String, Services)
Public Sub GetService()
Dim localServices As ServiceController() = ServiceController.GetServices()
For Each service As ServiceController In localServices
dictservice.Add(service.DisplayName, New Services(service.DisplayName, service.ServiceName, service.Status.ToString))
Next
End Sub
Right now it's Nothing, hence the NullReferenceException.
The most likely problem appears to be that dictService is Nothing and hence you get a NullReferenceException. Where do you initialize / declare dictService and are you certain the initialization happens before this method?
If this is not the problem have you tried running this with the debugger attached? it should point you to the line that is failing.