I have a C# windows service installed on a 32 bit windows server 2003 machine that I wish to debug.
The problem I have is that a log file error message tells me the following:
System.NullReferenceException: Object reference not set to an instance of an object.
at VideoProcessor.ResetCameraProperties(DataServiceObject dso)
at VideoProcessor.AddServer(DataServiceObject dso)
at VideoProcessor.LoadServers()
at VideoProcessor.Start()
atVideoServerComponent.Connect()
The actual code for the function ResetCameraProperties is:
protected void ResetCameraProperties(DataServiceObject dso)
{
// Find the CameraType.
//Type videoCameraType = TypeManager.Instance["XFire.Common.VideoObjects.VideoServer"];
if (_videoCameraType == null) return;
//Load cameras from the Data Service Layer
string whereClause = "ServerID = ?";
object[] args = new object[] { dso["ObjectID"] };
IDataServiceCollection videoCameraDsoCollection = ClientServerConnection.Instance.FindCollection(_videoCameraType, whereClause, args, null, CollectionOptions.FilterByPartitionResponsibility) as IDataServiceCollection;
if (videoCameraDsoCollection == null || 0 == videoCameraDsoCollection.Count)
return;
videoCameraDsoCollection.LoadContainerOnEnumeration = false;
foreach (DataServiceObject camera in videoCameraDsoCollection)
{
if (!(bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Offline"))
{
// If the server is disconnected, then we know everything should be offline.
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Unknown");
camera[CameraKey.Videoloss] = true;
}
else if ((bool)dso[RecorderKey.Online] && (int)dso[RecorderKey.VideoServerAlarm] == (int)VideoServerComponent.GetVideoServerAlarm("Online"))
{
camera[CameraKey.VideoCameraAlarm] = VideoServerComponent.GetEnumValueOfType("XFire.Common.VideoObjectDefinitions.VideoCameraAlarm", "Normal");
camera[CameraKey.Videoloss] = false;
}
// Save the camera.
ServerResult result = ClientServerConnection.Instance.PersistObject(camera, null);
if (result.Fault != null)
{
if (VideoTrace.TraceError) Trace.WriteLine(result.Fault.Message);
}
}
I have opened windbg and did File-->Attach to process
I have set breakpoints in the function above using the steps outlined here: https://learn.microsoft.com/en-us/archive/blogs/alejacma/managed-debugging-with-windbg-preparing-the-environment
When the breakpoint is hit I step forward using F10 but all I see is the following:
Setting breakpoint: bp 05A0A260 [VideoProcessor.*ResetCameraProperties (XFire.Common.DataServiceLayer.DataServiceObject)] Adding pending breakpoints... 0:024> g DriverWindowsService.OnStop Service stopping... Breakpoint 0 hit eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78 eip=05a0a260 esp=0674e68c ebp=0674e6b0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a260 55 push ebp 0:024> p eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78 eip=05a0a261 esp=0674e688 ebp=0674e6b0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a261 8bec mov ebp,esp 0:024> p eax=00000001 ebx=00902870 ecx=00a1e020 edx=01066e78 esi=00affb48 edi=01066e78 eip=05a0a263 esp=0674e688 ebp=0674e688 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 05a0a263 57 push edi
This means nothign to me at present (I'm a windbg newbie)
I have the pdb file for the windows service (I got from the Visual Studio Debug Output folder) and have copied itto my target machine in a folder C:\Symbols.
In winDbg I did File-->Symbol FIle path and set it to the location of this pdb file I copied over. My symbol path is as follows: C:\symcache;C:\Symbols;srvc:\symcachehttp://msdl.microsoft.com/download/symbols
In Windbg I did View-->Watch and I typed in the name of a variable that is inside the function above (videoCameraType). But I got the following error:
*** Either you specified an unqualified symbol, or your debugger *** *** doesn't have full symbol information. Unqualified symbol *** *** resolution is turned off by default. Please either specify a *** *** fully qualified symbol module!symbolname, or enable resolution *** *** of unqualified symbols by typing ".symopt- 100". Note that *** *** enabling unqualified symbol resolution with network symbol *** *** server shares in the symbol path may cause the debugger to *** *** appear to hang for long periods of time when an incorrect *** *** symbol name is typed or the network symbol server is down. ***
*** For some commands to work properly, your symbol path *** *** must point to .pdb files that have full type information. ***
*** Certain .pdb files (such as the public OS symbols) do not *** *** contain the required information. Contact the group that *** *** provided you with these symbols if you need this command to *** *** work. ***
*** Type referenced: _videoCameraType ***
How can I view variables and generally see what is going on in my code???? I also have the source code for the windows service if thats any help.
Thanks
First thing is that your symbol files are probably not matching binaries as there is no source file paths and line numbers in your exception stack trace. You mentioned that you copied them from the Visual Studio Debug Output, so I assume that you have binaries compiled in Release (with no symbols) and pdb files from Debug. This won't work. What you need to do is change the project settings for your service, recompile and deploy it (you should now have pdb, dll and exe files in the release output folder). This should generate a much more meaningful stack trace for your exception.
Now, the second part. You need to distinguish a managed environment from the native one. In windbg you are debugging the CLR as it is seen by the operating system, thus you are debugging not only your C# application but the CLR interpreter that compiles your ILASM (compiled C# code) to native CPU instructions and then executes them. So you are a layer below what you normally see in VS (with managed debugger attached). Keeping that in mind you need to either dig into CLR internals and try to figure out what the addresses in registers mean or use some sort of translator which will do this heavy work for you. And this is where SOS comes into play. You've already used it when you set the breakpoint. As you are only interested in knowing a value of your variable you need to first find out at what address the CLR lied it out for you. From what I see the _videoCameraType
is a private class member, isn't it? If so you may dump managed objects from the stack using !dso
command. You should see something similar to the output below:
> !dso
OS Thread Id: 0xad8 (0)
RSP/REG Object Name
000000000068E8F0 00000000025f2bc8 Program+Test
000000000068E8F8 00000000025f2be0 System.String test
000000000068E910 00000000025f2bc8 Program+Test
000000000068E918 00000000025f2bc8 Program+Test
where Program+Test
would be replaced by your class name. Then you may dump the object content using !do
command and the address from the Object
column:
> !do 00000000025f2bc8
Name: Program+Test
MethodTable: 000007fe58333a08
EEClass: 000007fe584422b8
Size: 24(0x18) bytes
File: D:\temp\Test.exe
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dcb318 4000001 8 System.String 0 instance 00000000025f2be0 _testVariable
Find the class member by its name and use !do
command once again but using address from the Value
column (this works for reference types). In our example it would be:
0:000> !do 00000000025f2be0
Name: System.String
MethodTable: 000007feb4dcb318
EEClass: 000007feb4733720
Size: 34(0x22) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: test
Fields:
MT Field Offset Type VT Attr Value Name
000007feb4dce0c8 40000aa 8 System.Int32 1 instance 4 m_stringLength
000007feb4dcc600 40000ab c System.Char 1 instance 74 m_firstChar
000007feb4dcb318 40000ac 18 System.String 0 shared static Empty
>> Domain:Value 000000000074f960:NotInit <<
Things get trickier if you need to figure out what a value of a local variable is. You may try with !CLRStack -a
which usually does not show much in release builds. You are then left with analysis of the generated assembly (!U @rip
) in order to find out where the address of your variables landed (registry, stack). After figuring this out, issue again the !do
command with the address you've found. Happy debugging :)
Adding to this thread since it shows up in Google searches:
The following worked for me:
(If application uses .net 4 use .loadby sos clr to load the SOS debugger extension)
Once you are on the right thread first use !clrstack -p to dump the stack along with the addresses of the local variables.
Now use the address of the local variable of interest to dump it using !do .
Then using the addresses from the output that you get - you can use !do again (use the Value field here for the address of a specific member). You can continue till you are able to see the value you desire.
(You can also use this approach to dump members of the "this" pointer which you obtain from the stack. This may have some variables of interest based on what you are looking for)
See http://blogs.msdn.com/b/alejacma/archive/2009/08/11/managed-debugging-with-windbg-thread-stacks-part-1.aspx
Debugging is exciting! Have fun with it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With