Using a IO variable before it has been assigned a value in a Try...Catch...Finally - vb.net

I'm trying to use an IO object in VB.net which I'm not initialising from the declaration point. I use the object in several places in a Try..Catch block and then I use it again in the Finally block. For the purpose of my question you can ignore the method calls of my code. VS is showing this warning: Variable 'objSourceDirectory' is used before it has been assigned a value. A null reference exception could result at runtime.
I believe having safe checks in some places in my code the null reference shouldn't happen, but how could I get rid of this warning? I would initialise the variable as empty at declaration point but this can't be possible with IO.DirectoryInfo, as it doesn't have a construction without parameters. How can I fix this?
Dim object1 As IO.DirectoryInfo
Try
mlstProcessedFiles = New Global.System.Collections.Generic.List(Of String)
' Gather Data from import source
object1 = New IO.DirectoryInfo(object2.Location)
MethodD(object2.Location)
MethodA(object1)
MethodC(object2.Location)
' Work through files found in the source. Detect if the file was moved and add it to the manual processing
For Each objFile In object1.GetFiles()
Try
MethodB(objFile, object2)
objFile = Nothing
Catch objFileEx As FileNotFoundException
Catch objDirEx As DirectoryNotFoundException
MethodX(mstrERROR_11_MOVED, objDirEx.Message)
Continue For
End Try
Next
Catch objectException As Exception
Throw
Finally
'Make sure processed files have been moved to their folders
Method1()
Method2()
Method3(object1)
End Try

You haven't shown objSourceDirectory in your code. I assume it is object1 which is used in the Finally.
Yes, you cannot use a variable when it is possible that this variable was not assigned a value. You are using it in the Finally which is executed always, even on error.
Since you haven't assigned a default value it is possible that you get an exception which causes it to remain unassigned. This compiler error prevents you from careless mistakes.
To fix it you could assign Nothing:
Dim object1 As IO.DirectoryInfo = Nothing
but you should check if it's Nothing in the Finally or in Method3.
In this case you could also move the initilization to the declaration which makes it definitely assigned:
Dim object1 As IO.DirectoryInfo = New IO.DirectoryInfo(object2.Location)
Note that the compiler is not smart enough to check if it is possible that an errors is raised before the variable is initialized. It just looks at the Try and "thinks": it's possible that here comes an error.

Related

Access an application and instantiate an object

I am trying to create an instance of a specific class called ExtraScreen from a referenced library application called EXTRA. How can I use the SendKeys function from the ExtraScreen class?
So far I tried this:
Dim software As EXTRA.ExtraScreen
software.SendKeys ("a")
The result is Error:
Object variable or With block variable not set.
You have to also Set it to something:
Dim software As EXTRA.ExtraScreen
Set software = CreateObject("EXTRA.ExtraScreen")
or
Dim software As New EXTRA.ExtraScreen
You have declared an object variable with a specific, early-bound type - which means if the code can compile & run, then the project has a reference to the type library.
Dim software As EXTRA.ExtraScreen
Dim statements aren't executable: you can't put a breakpoint on a Dim statement. All they do is allocate a spot of a given size in memory. In this case, it reserves a spot wide enough to hold an object reference - and nothing else.
On execution, the first statement to execute is this:
software.SendKeys ("a")
But the problem is, if you put a breakpoint here and inspect the Locals toolwindow, you'll find that the software object contains Nothing. In other languages this is known as a "null reference" - the object variable is not set: there's a reserved spot for holding an object reference, but the spot is empty.
You use the New keyword to create an instance of a class - i.e. to create an object. And in VBA object reference assignments require the Set keyword:
Set software = New EXTRA.ExtraScreen
Now if you run that line and inspect your locals, you'll find that software isn't Nothing anymore, and you can inspect its state / properties.
Once an object variable holds a proper object reference, you can legally invoke its members:
software.SendKeys "a"
You can never invoke anything on a Nothing object reference: an object variable that is Nothing is, well, nothing: it's not an object, therefore it has no members to invoke. VBA runtime responds by throwing run-time error 91 "Object (or With block variable) not Set".
The "With block variable" part is referring to the With keyword, which can also hold objects. For example you could do this:
With software
.SendKeys "a"
End With
And you'd get the exact same error if software isn't Set. Consider dropping the local variable altogether, if it only ever needs to live as a local variable inside some specific procedure:
With New EXTRA.ExtraScreen
.SendKeys "a"
End With
In this case the With block is holding the object reference; at End With, the object is gone (avoid jumping in & out of With blocks, specifically for that reason).

VB Object reference not set to an instance of an object

I am simply trying to load an xml file and I cannot figure out how. Here is my code:
Dim root As Xml.XmlDocument = Nothing
root.Load(My.Application.Info.DirectoryPath & "C:\XMLFile1.xml")
It compiles without errors but then gives me "Object reference not set to an instance of an object" when I step through the debugger and it reaches that second line. The file exists where it is supposed to. I've tried almost every variation of the above lines that I could find online (ie with just the path within the parentheses in the second line etc) but still get the same issue.
Look closely at what you're doing:
Dim root As Xml.XmlDocument = Nothing
This line says to create a variable called root but set it to Nothing. That is, don't assign it an instance of any actual object. Then:
root.Load()
You're trying to use the object, which you just explicitly defined as not being an object.
The error has nothing to do with your XML file, it never gets that far. You need an actual instance of an object before you can call members of that object. I think what you're looking for is this:
Dim root As New XmlDocument
root.Load(My.Application.Info.DirectoryPath & "C:\XMLFile1.xml")
This creates an instance of an XmlDocument object and then invokes the Load member on that object. (Though I think the path is wrong, but that's another issue entirely. I can't imagine any path information preceeding the drive letter...)

What is the lifetime of a global variable in excel vba?

I've got a workbook that declares a global variable that is intended to hold a COM object.
Global obj As Object
I initalize it in the Workbook_Open event like so:
Set obj = CreateObject("ComObject.ComObject");
I can see it's created and at that time I can make some COM calls to it.
On my sheet I have a bunch of cells that look like:
=Module.CallToComObject(....)
Inside the Module I have a function
Function CallToComObject(...)
If obj Is Nothing Then
CallToComObject= 0
Else
Dim result As Double
result = obj.GetCalculatedValue(...)
CallToComObject= result
End If
End Function
I can see these work for a bit, but after a few sheet refreshes the obj object is no longer initialized, ie it is set to Nothing.
Can someone explain what I should be looking for that can cause this?
Any of these will reset global variables:
Using "End"
An unhandled runtime error
Editing code
Closing the workbook containing the VB project
That's not necessarily an exhaustive list though...
I would suggest a 5th point in addition to Tim's 4 above: Stepping through code (debugging) and stopping before the end is reached. Possibly this could replace point number 3, as editing code don't seem to cause global variable to lose their values.

Method Calls on Objects that Aren't "Guaranteed" to be Instantiated

I recently wrote a section of code wherein upon finishing, I received a warning from the compiler telling me that one of my variables is being used before it is assigned a value. In practice, the method call on this object will never be made without the object being instantiated beforehand. Here is the snippet of code
Try
fs = New FileStream(fileName, FileMode.Open)
Dim PolarMatrix As PolarMatrix
PolarMatrix = DirectCast(bf.Deserialize(fs), PolarMatrix)
fs.Close()
Return TypeOfStructure.Polar
Catch ex As Exception
fs.Close() 'Warning on this line: Variable 'fs' is used before it has been assinged a value
End Try
I assume I'm receiving this warning because the first line in the Try section may be the line to throw the error, and the Object will never be instantiated. FileName though, is a variable being passed to this method which has already been checked for errors, so it is guaranteed to be correct. The error I'm expecting to perhaps be thrown comes during the deserialization.
So my question: When warnings are given on objects that the compiler thinks may not have been instantiated, does this overrule the user knowing that a problem will never arise on that line? Is it sometimes necessary to add code simply to appease the compiler? Or is what I've done here bad practice?
How are you sure that fs will always be instantiated, even if the filename is correct, it could still fail to open for many other reasons.
However, the easy solution to this problem would be to get rid of the catch completely and use a Using statement instead, as:
Try
Using fs = New FileStream(fileName, FileMode.Open)
Dim PolarMatrix As PolarMatrix
PolarMatrix = DirectCast(bf.Deserialize(fs), PolarMatrix)
Return TypeOfStructure.Polar
End Using
Catch ex as Exception
' do something here
End Try
This means that the fs will be automatically disposed of when this section of code exists, and Stream.Dispose closes the stream.
And to answer your actual question, sometimes the compiler is wrong, and you will have to either ignore the warnings or add some extra code to make them go away, but in general, assume that the compiler is correct until you're absolutely sure that that's not the case.

object reference not set to an instance of object [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 2 years ago.
I have been getting an error in VB .Net
object reference not set to an instance of object.
Can you tell me what are the causes of this error ?
The object has not been initialized before use.
At the top of your code file type:
Option Strict On
Option Explicit On
Let's deconstruct the error message.
"object reference" means a variable you used in your code which referenced an object. The object variable could have been declared by you the or it you might just be using a variable declared inside another object.
"instance of object" Means that the object is blank (or in VB speak, "Nothing"). When you are dealing with object variables, you have to create an instance of that object before referencing it.
"not set to an " means that you tried to access an object, but there was nothing inside of it for the computer to access.
If you create a variable like
Dim aPerson as PersonClass
All you have done was tell the compiler that aPerson will represent a person, but not what person.
You can create a blank copy of the object by using the "New" keyword. For example
Dim aPerson as New PersonClass
If you want to be able to test to see if the object is "nothing" by
If aPerson Is Nothing Then
aPerson = New PersonClass
End If
Hope that helps!
sef,
If the problem is with Database return results, I presume it is in this scenario:
dsData = getSQLData(conn,sql, blah,blah....)
dt = dsData.Tables(0) 'Perhaps the obj ref not set is occurring here
To fix that:
dsData = getSQLData(conn,sql, blah,blah....)
If dsData.Tables.Count = 0 Then Exit Sub
dt = dsData.Tables(0) 'Perhaps the obj ref not set is occurring here
edit: added code formatting tags ...
In general, under the .NET runtime, such a thing happens whenever a variable that's unassigned or assigned the value Nothing (in VB.Net, null in C#) is dereferenced.
Option Strict On and Option Explicit On will help detect instances where this may occur, but it's possible to get a null/Nothing from another function call:
Dim someString As String = someFunctionReturningString();
If ( someString Is Nothing ) Then
Sysm.Console.WriteLine(someString.Length); // will throw the NullReferenceException
End If
and the NullReferenceException is the source of the "object reference not set to an instance of an object".
And if you think it's occuring when no data is returned from a database query then maybe you should test the result before doing an operation on it?
Dim result As String = SqlCommand.ExecuteScalar() 'just for scope'
If result Is Nothing OrElse IsDBNull(result) Then
'no result!'
End If
You can put a logging mechanism in your application so you can isolate the cause of the error. An Exception object has the StackTrace property which is a string that describes the contents of the call stack, with the most recent method call appearing first. By looking at it, you'll have more details on what might be causing the exception.
When working with databases, you can get this error when you try to get a value form a field or row which doesn't exist. i.e. if you're using datasets and you use:
Dim objDt as DataTable = objDs.Tables("tablename")
you get the object "reference not set to an instance of object" if tablename doesn't exists in the Dataset. The same for rows or fields in the datasets.
Well, Error is explaining itself. Since You haven't provided any code sample, we can only say somewhere in your code, you are using a Null object for some task. I got same Error for below code sample.
Dim cmd As IDbCommand
cmd.Parameters.Clear()
As You can see I am going to Clear a Null Object. For that, I'm getting Error
"object reference not set to an instance of an object"
Check your code for such code in your code. Since you haven't given code example we can't highlight the code :)
In case you have a class property , and multiple constructors, you must initialize the property in all constructors.