Use WinDbg to Write Contents of Managed Byte[] to File - windbg

I have a crash dump from a production server that shows an OutOfMemoryException. The exception itself is not relevant here.
I happened to run a !dso to view the stack objects:
0:042> !dso
OS Thread Id: 0x1014 (42)
ESP/REG Object Name
246eeb24 109a21bc System.UnhandledExceptionEventHandler
246eeb2c 39083998 System.Runtime.Remoting.Proxies.__TransparentProxy
246eeb34 39083b5c System.UnhandledExceptionEventArgs
246eeb48 39073280 System.Byte[]
246eec10 2e720050 System.OutOfMemoryException
[snip]
246ef250 0ac1c4d0 System.IO.MemoryStream <-- interesting
I thought the MemoryStream might have something to do with the error, so I dumped it:
0:042> !do 0ac1c4d0
Name: System.IO.MemoryStream
MethodTable: 7932d5e4
EEClass: 790ec318
Size: 52(0x34) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
7933061c 400018a 4 System.Object 0 instance 00000000 __identity
7992cbcc 4001b6c 8 ...ream+ReadDelegate 0 instance 00000000 _readDelegate
7992cc58 4001b6d c ...eam+WriteDelegate 0 instance 00000000 _writeDelegate
7931bd9c 4001b6e 10 ...ng.AutoResetEvent 0 instance 00000000 _asyncActiveEvent
79332c4c 4001b6f 14 System.Int32 1 instance 1 _asyncActiveCount
7932e6fc 4001b6b 574 System.IO.Stream 0 shared static Null
>> Domain:Value 000dc0f0:NotInit 00109d58:109b6abc <<
79333470 4001c16 18 System.Byte[] 0 instance 50710038 _buffer
79332c4c 4001c17 1c System.Int32 1 instance 0 _origin
79332c4c 4001c18 20 System.Int32 1 instance 56071048 _position
79332c4c 4001c19 24 System.Int32 1 instance 56071048 _length
79332c4c 4001c1a 28 System.Int32 1 instance 67108864 _capacity
793044cc 4001c1b 2c System.Boolean 1 instance 1 _expandable
793044cc 4001c1c 2d System.Boolean 1 instance 1 _writable
793044cc 4001c1d 2e System.Boolean 1 instance 1 _exposable
793044cc 4001c1e 2f System.Boolean 1 instance 1 _isOpen
Wow, a 56,071,048 byte buffer seems a bit large. I'd like to see the contents of this buffer:
0:042> !do 50710038
Name: System.Byte[]
MethodTable: 79333470
EEClass: 790eeb6c
Size: 67108876(0x400000c) bytes
Array: Rank 1, Number of elements 67108864, Type Byte
Element Type: System.Byte
Fields:
None
The first 10 elements of the array are below:
0:042> !dumparray -start 0 -length 10 50710038
Name: System.Byte[]
MethodTable: 79333470
EEClass: 790eeb6c
Size: 67108876(0x400000c) bytes
Array: Rank 1, Number of elements 67108864, Type Byte
Element Methodtable: 79333520
[0] 50710040
[1] 50710041
[2] 50710042
[3] 50710043
[4] 50710044
[5] 50710045
[6] 50710046
[7] 50710047
[8] 50710048
[9] 50710049
This is a huge array. I'd rather not !dumparray the whole thing. I'd like to view the output in a file.
Question
Is it possible to dump the contents of this Byte[] to a file?
I am familiar with the .writemem command, but I can't seem to get this to work. I've tried writing the entire length, but WinDbg didn't like that:
0:042> .writemem C:\LargeBuffer.bin 50710040 L56071048
^ Range error in '.writemem C:\LargeBuffer.bin 50710040 l56071048'
Did I format that .writemem command incorrectly?

The L modifier for ranges is limited in size. If you want to get around the limit use the L? range modifier. The following command worked for me:
0:000> !do 0x04cc1000
Name: System.Byte[]
MethodTable: 68374944
EEClass: 680aaf1c
Size: 67108876(0x400000c) bytes
Array: Rank 1, Number of elements 67108864, Type Byte
Element Type:System.Byte
Content: ................................................................................................................................
Fields:
None
0:000> .writemem c:\temp\array.bin 0x04cc1000 L?0x400000c
Writing 400000c bytes

This is what worked for me:
.foreach($str {!DumpHeap /d -mt 00007ff890e96948 -min 0n126500 -short}){r#$t0= dwo(${$str}+8)*2;.writemem e:\temp\str\${$str}.txt ${$str}+c L? #$t0}

Related

Windbg managed objects poi for arrays first element, second element

I can use poi in windbg scripting to traverse the fields and then print the field i am interested in.
For e.g. if i have all objects of type X which has field X.y.z where z is an array, where y is at offset 0x10 and z is at offset 0x8. I can write
.foreach ( dSM { !dumpheap -short -type X})
{
.printf "%p\n", poi(poi(${dSM}+0x10)+0x8);
!dumparray poi(poi(${dSM}+0x10)+0x8)
}
Now i want to print first/second element of all these arrays, how can i do that ?
using !do poi(poi(poi(${dSM}+0x10)+0x8)) does not work.
0:045> !DumpArray /d 000001d3b96787a8
Name: ABC[]
MethodTable: 00007ffc951e76e0
EEClass: 00007ffcf22f4480
Size: 56(0x38) bytes
Array: Rank 1, Number of elements 4, Type CLASS
Element Methodtable: 00007ffc951e6cc0
[0] 000001d3b9678788
[1] null
[2] null
[3] null
0:045> !dumpobj /d poi(000001d3b96787a8)
<Note: this object has an invalid CLASS field>
Invalid object
Array class is:
:045> !DumpClass /d 00007ffcf22f4480
Class Name: System.Object[]
mdToken: 0000000002000000
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Parent Class: 00007ffcf22f5018
Module: 00007ffcf2221000
Method Table: 00007ffcf2949e80
Vtable Slots: 18
Total Method Slots: 1c
Class Attributes: 2101
Transparency: Transparent
NumInstanceFields: 0
NumStaticFields: 0
Given this program:
using System;
namespace WinDbgArrayAccess
{
class Program
{
static void Main()
{
Program[] justAnArray = new Program[20];
for (int i =0; i<justAnArray.Length;i++) justAnArray[i] = new Program();
Console.WriteLine("Access the elements of the array in WinDbg now!");
Console.ReadLine();
}
}
}
You can see
0:006> !DumpArray /d 0336243c
Name: WinDbgArrayAccess.Program[]
MethodTable: 01914db0
EEClass: 71967820
Size: 92(0x5c) bytes
Array: Rank 1, Number of elements 20, Type CLASS
Element Methodtable: 01914d60
[0] 03362498
[1] 033624a4
[2] 033624b0
[3] 033624bc
[4] 033624c8
[5] 033624d4
...
Now you need to find those numbers somewhere in the memory. Since we hardly have a different starting point, let's start at the array's address:
0:006> dp 0336243c L10
0336243c 01914db0 00000014 03362498 033624a4
0336244c 033624b0 033624bc 033624c8 033624d4
0336245c 033624e0 033624ec 033624f8 03362504
0336246c 03362510 0336251c 03362528 03362534
Now, 01914db0 is the type of the object (called Method Table, MT). 0x14 is 0n20, which is the size of the array. And after that, it seems we have the elements, 03362498, 033624a4, 033624b0 etc.
How do we access that programmatically? Well, it's easy now:
0:006> .printf "%p",poi(0336243c+(2+3)*$ptrsize)
033624bc
Where 2 is to skip MT and Length and 3 is the index of the array, giving you the 4th element.
I was able to get first 2 elements by going forward poi(poi(array+10)+8) and poi(poi(array+10)+10) offsets from array
0:298> .foreach (obj { !DumpHeap -short -live -mt 00007ffc951e7ab8}) { .printf "%p\n", ${obj}; !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x8); !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x10); }
000001d379ac94a0
[raw] 000001d379ac8bc8 "XYZ_String"
[raw] 000001d379ac8c88 "XYZ_String_2"
000001d379e87168
[raw] 000001d379e86888 "ABCD_String"
[raw] 000001d379e86948 "ABCD_String_2"
000001d3b972a218

Stacktrace of an inner exception

w3wp process hosting my .NET application is crashing at random times. I have collected a dump file by setting up a second chance exception rule using DebugDiag. Here are the steps I have performed.
The lastevent command shows a .NET exception.
0:027> .lastevent
Last event: 1ae4.2e98: CLR exception - code e0434352 (first/second chance not available)
The stack trace of this thread looks as follows,
0:027> !CLRStack
OS Thread Id: 0x2e98 (68)
Child SP IP Call Site
000000266c1bab18 00007fff6e5d95fc [HelperMethodFrame: 000000266c1bab18]
000000266c1bac00 00007fff5cb38afb System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
000000266c1bcb48 00007fff6657120d [HelperMethodFrame: 000000266c1bcb48]
000000266c1bcc30 00007fff5cb359b5 System.Runtime.AsyncResult.Complete(Boolean)
000000266c1bea00 00007fff6657120d [FaultingExceptionFrame: 000000266c1bea00]
000000266c1bef00 00007fff5bca63a5 System.Web.HttpApplication+AsyncEventExecutionStep.OnAsyncEventCompletion(System.IAsyncResult)
000000266c1bef60 00007fff5cb3586c System.Runtime.AsyncResult.Complete(Boolean)
000000266c1befd0 00007fff570da192 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(System.Object)
000000266c1bf020 00007fff5cb38b63 System.Runtime.IOThreadScheduler+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
000000266c1bf090 00007fff5cb38ac7 System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)
000000266c1bf0f0 00007fff650a045c System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*) [f:\dd\ndp\clr\src\BCL\system\threading\overlapped.cs # 135]
000000266c1bf2a0 00007fff66416793 [GCFrame: 000000266c1bf2a0]
000000266c1bf498 00007fff66416793 [DebuggerU2MCatchHandlerFrame: 000000266c1bf498]
000000266c1bf628 00007fff66416793 [ContextTransitionFrame: 000000266c1bf628]
000000266c1bf858 00007fff66416793 [DebuggerU2MCatchHandlerFrame: 000000266c1bf858]
pe command shows a callback exception
0:027> !pe
Exception object: 0000002552364d38
Exception type: System.Runtime.CallbackException
Message: Async Callback threw an exception.
InnerException: System.NullReferenceException, Use !PrintException 0000002552364ae8 to see more.
StackTrace (generated):
SP IP Function
000000266C1BCC30 00007FFF5CB359B5 System_ServiceModel_Internals_ni!System.Runtime.AsyncResult.Complete(Boolean)+0x235
000000266C1BEFD0 00007FFF570DA192 System_ServiceModel_Activation_ni!System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(System.Object)+0x92
000000266C1BF020 00007FFF5CB38B63 System_ServiceModel_Internals_ni!System.Runtime.IOThreadScheduler+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x53
000000266C1BF090 00007FFF5CB38AFB System_ServiceModel_Internals_ni!System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x6b
000000266C1BF0F0 00007FFF650A045C mscorlib_ni!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x7c
StackTraceString: <none>
HResult: 80131501
There are nested exceptions on this thread. Run with -nested for details
Per output of previous command, I look for nested exceptions
0:027> !PrintException -nested /d 0000002552364ae8
Exception object: 0000002552364ae8
Exception type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
InnerException: <none>
StackTrace (generated):
SP IP Function
000000266C1BEF00 00007FFF5BCA63A5 System_Web_ni!System.Web.HttpApplication+AsyncEventExecutionStep.OnAsyncEventCompletion(System.IAsyncResult)+0x55
000000266C1BEF60 00007FFF5CB3586C System_ServiceModel_Internals_ni!System.Runtime.AsyncResult.Complete(Boolean)+0xec
StackTraceString: <none>
HResult: 80004003
Nested exception -------------------------------------------------------------
Exception object: 0000002552364d38
Exception type: System.Runtime.CallbackException
Message: Async Callback threw an exception.
InnerException: System.NullReferenceException, Use !PrintException 0000002552364ae8 to see more.
StackTrace (generated):
SP IP Function
000000266C1BCC30 00007FFF5CB359B5 System_ServiceModel_Internals_ni!System.Runtime.AsyncResult.Complete(Boolean)+0x235
000000266C1BEFD0 00007FFF570DA192 System_ServiceModel_Activation_ni!System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(System.Object)+0x92
000000266C1BF020 00007FFF5CB38B63 System_ServiceModel_Internals_ni!System.Runtime.IOThreadScheduler+ScheduledOverlapped.IOCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x53
000000266C1BF090 00007FFF5CB38AFB System_ServiceModel_Internals_ni!System.Runtime.Fx+IOCompletionThunk.UnhandledExceptionFrame(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x6b
000000266C1BF0F0 00007FFF650A045C mscorlib_ni!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)+0x7c
StackTraceString: <none>
HResult: 80131501
My next step is to find the stack trace for that NullReferenceException
0:027> !do 0000002552364ae8
Name: System.NullReferenceException
MethodTable: 00007fff652865a0
EEClass: 00007fff64c3f180
Size: 160(0xa0) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
00007fff65276948 400028e 8 System.String 0 instance 000000244f54d350 _className
00007fff6528f6b8 400028f 10 ...ection.MethodBase 0 instance 0000002552366f58 _exceptionMethod
00007fff65276948 4000290 18 System.String 0 instance 0000000000000000 _exceptionMethodString
00007fff65276948 4000291 20 System.String 0 instance 000000244bf27668 _message
00007fff65286788 4000292 28 ...tions.IDictionary 0 instance 00000025523751a8 _data
00007fff65276b78 4000293 30 System.Exception 0 instance 0000000000000000 _innerException
00007fff65276948 4000294 38 System.String 0 instance 0000000000000000 _helpURL
00007fff65276f28 4000295 40 System.Object 0 instance 0000002552364cc0 _stackTrace
00007fff65276f28 4000296 48 System.Object 0 instance 0000000000000000 _watsonBuckets
00007fff65276948 4000297 50 System.String 0 instance 0000000000000000 _stackTraceString
00007fff65276948 4000298 58 System.String 0 instance 0000000000000000 _remoteStackTraceString
00007fff65279288 4000299 88 System.Int32 1 instance 0 _remoteStackIndex
00007fff65276f28 400029a 60 System.Object 0 instance 0000000000000000 _dynamicMethods
00007fff65279288 400029b 8c System.Int32 1 instance -2147467261 _HResult
00007fff65276948 400029c 68 System.String 0 instance 000000255242ce60 _source
00007fff6528fbc0 400029d 78 System.IntPtr 1 instance 0 _xptrs
00007fff65279288 400029e 90 System.Int32 1 instance -532462766 _xcode
00007fff65250340 400029f 80 System.UIntPtr 1 instance 7fff5bca63a4 _ipForWatsonBuckets
00007fff65265538 40002a0 70 ...ializationManager 0 instance 0000002552364c40 _safeSerializationManager
00007fff65276f28 400028d b8 System.Object 0 shared static s_EDILock
>> Domain:Value 000000244acba390:NotInit 000000267072bd80:NotInit <<
Here I attempt to get the stack trace of NullReferenceException. This looks like a SByte array.
0:027> !do 0000002552364cc0
Name: System.SByte[]
MethodTable: 00007fff65202b20
EEClass: 00007fff64c34f60
Size: 120(0x78) bytes
Array: Rank 1, Number of elements 96, Type SByte (Print Array)
Content: ........0Qkv&....c.[.......l&...x..[............kX.\....`..l&...`..\............................
Fields:
None
My expectation is to get a stacktrace/details of what method/line of code/object is responsible for causing this null reference. I also attempt to dump the contents of SByte array but that doesn't provide me any useful information. Any suggestions on how can I get more information about this NullReferenceException?
First of all, I think that !pe -nested already shows the call stack that you're looking for:
0:027> !PrintException -nested /d 0000002552364ae8
[...]
StackTrace (generated):
SP IP Function
000000266C1BEF00 00007FFF5BCA63A5 System_Web_ni!System.Web.HttpApplication+AsyncEventExecutionStep.OnAsyncEventCompletion(System.IAsyncResult)+0x55
000000266C1BEF60 00007FFF5CB3586C System_ServiceModel_Internals_ni!System.Runtime.AsyncResult.Complete(Boolean)+0xec
[...]
Next, a stack trace is exactly what you see in that SByte[]: it's just a bunch of numbers.
Those number do get their meaning only together with PDB files. The PDB file contains the information to turn numbers into names.
Have a look at the values in the SP column and IP column. They are:
000000266C1BEF00
000000266C1BEF60
00007FFF5BCA63A5
00007FFF5CB3586C
And now, use a converter that converts those values into text:
You'll find that the printable characters resssemble those of the output shown in SByte[] by WinDbg:
0:027> !do 0000002552364cc0
[...]
Content: ........0Qkv&....c.[.......l&...x..[............kX.\....`..l&...`..\............................
The order may be different due to little/big-endianness.

Two byte report count for hid report descriptor

I'm trying to create an HID report descriptor for USB 3.0 with a report count of 1024 bytes.
The documentation at usb.org for HID does not seem to mention a two byte report count. Nonetheless, I have seen some people use 0x96 (instead of 0x95) to enter a two byte count, such as:
0x96, 0x00, 0x02, // REPORT_COUNT (512)
which was taken from here:
Custom HID device HID report descriptor
Likewise, from this same example, 0x26 is used for a two byte logical maximum.
Where did this 0x96 and 0x26 field come from? I don't see any documentation for it.
REPORT_COUNT is defined in the Device Class Definition for HID 1.11 document in section 6.2.2.7 Global Items on page 36 as:
Report Count 1001 01 nn Unsigned integer specifying the number of data
fields for the item; determines how many fields are included in the
report for this particular item (and consequently how many bits are
added to the report).
The nn in the above code is the item length indicator (bSize) and is defined earlier in section 6.2.2.2 Short Items as:
bSize Numeric expression specifying size of data:
0 = 0 bytes
1 = 1 byte
2 = 2 bytes
3 = 4 bytes
Rather confusingly, the valid values of bSize are listed in decimal. So, in binary, the bits for nn would be:
00 = 0 bytes (i.e. there is no data associated with this item)
01 = 1 byte
10 = 2 bytes
11 = 4 bytes
Putting it all together for REPORT_COUNT, which is an unsigned integer, the following alternatives could be specified:
1001 01 00 = 0x94 = REPORT_COUNT with no length (can only have value 0?)
1001 01 01 = 0x95 = 1-byte REPORT_COUNT (can have a value from 0 to 255)
1001 01 10 = 0x96 = 2-byte REPORT_COUNT (can have a value from 0 to 65535)
1001 01 11 = 0x97 = 4-byte REPORT_COUNT (can have a value from 0 to 4294967295)
Similarly, for LOGICAL_MAXIMUM, which is a signed integer (usually, there is an exception):
0010 01 00 = 0x24 = LOGICAL_MAXIMUM with no length (can only have value 0?)
0010 01 01 = 0x25 = 1-byte LOGICAL_MAXIMUM (can have a values from -128 to 127)
0010 01 10 = 0x26 = 2-byte LOGICAL_MAXIMUM (can have a value from -32768 to 32767)
0010 01 11 = 0x27 = 4-byte LOGICAL_MAXIMUM (can have a value from -2147483648 to 2147483647)
The specification is unclear on what value a zero-length item defaults to in general. It only mentions, at the end of section 6.2.2.4 Main Items, that MAIN item types and, within that type, INPUT item tags, have a default value of 0:
Remarks - The default data value for all Main items is zero (0).
- An Input item could have a data size of zero (0) bytes. In this case the value of
each data bit for the item can be assumed to be zero. This is functionally
identical to using a item tag that specifies a 4-byte data item followed by four
zero bytes.
It would be reasonable to assume 0 as the default for other item types too, but for REPORT_COUNT (a GLOBAL item) a value of 0 is not really a sensible default (IMHO). The specification doesn't really say.

Fiji get a 16bit tiff stack with unknown tags after importing sequences

In Fiji, I import sequences to get a tiff stack image over 5GB. I cannot see the detailed information in the property, such as Width, Height, Bit depth. The original depth is 16bit. When I use "imfinfo" in Matlab, it always shows 1 but not the length of the stack. Can anyone help me solve this problem? I would like to appreciate your kindness.
Below is the feedback from Matlab when I use imfinfo.
info_red=imfinfo('C:\Users\MyDoc\Desktop\Background Subtraction\FluoRed.tif')
info_red=
Filename: 'C:\Users\MyDoc\Desktop\Background Subtraction\FluoRed.tif'
FileModDate: '02-Sep-2014 07:09:51'
FileSize: 5.3701e+09
Format: 'tif'
FormatVersion: []
Width: 1388
Height: 1040
BitDepth: 16
ColorType: 'grayscale'
FormatSignature: [73 73 42 0]
ByteOrder: 'little-endian'
NewSubFileType: 0
BitsPerSample: 16
Compression: 'Uncompressed'
PhotometricInterpretation: 'BlackIsZero'
StripOffsets: 230904
SamplesPerPixel: 1
RowsPerStrip: 1040
StripByteCounts: 2887040
XResolution: []
YResolution: []
ResolutionUnit: 'Inch'
Colormap: []
PlanarConfiguration: 'Chunky'
TileWidth: []
TileLength: []
TileOffsets: []
TileByteCounts: []
Orientation: 1
FillOrder: 1
GrayResponseUnit: 0.0100
MaxSampleValue: 65535
MinSampleValue: 0
Thresholding: 1
Offset: 8
ImageDescription: 'ImageJ=1.49b
images=1860
frames=1860
finterval=3
tunit=min
loop=false
min=30...'
UnknownTags: [2x1 struct]
when importing tiff stacks with Matlab, you can use the tiff class to get information about your stack, as well as actually opening them.
For example, if you use this:
t = Tiff('FluoRed.tif','r')
you will get a description of your stack which looks somewhat similar to what you get with imfinfo, that is you get a structure in which you can access its fields using standard dot notation. Here is an example with a stack named 'OriginalStack.tif' on my computer:
t =
TIFF File: '/Documents/MATLAB/OriginalStack.tif'
Mode: 'r'
Current Image Directory: 1
Number Of Strips: 1
SubFileType: Tiff.SubFileType.Default
Photometric: Tiff.Photometric.RGB
ImageLength: 364
ImageWidth: 460
RowsPerStrip: 364
BitsPerSample: 8
Compression: Tiff.Compression.None
SampleFormat: Tiff.SampleFormat.UInt
SamplesPerPixel: 3
PlanarConfiguration: Tiff.PlanarConfiguration.Chunky
ImageDescription: ImageJ=1.48v
images=20
slices=20
loop=false
Orientation: Tiff.Orientation.TopLeft
For instance, you can get the image width like so:
Width = t.getTag('ImageWidth')
As you can see, there is a field in the structure called 'ImageDescription', which tells you that there are 20 images in your stack (well my stack actually :). You could manage to get this information with structure indexing, but it's cumbersome since using
t.getTag('ImageDescription')
returns a character array and you would need to play around with regular expressions, for instance, to get the actual number of images.
EDIT: here is how you could do to retrieve the number of slices in your stack:
1) Assign a variable name to the 'ImageDescription' tag from the tiff class object:
ImageDes = t.getTag('ImageDecription');
2) Then use regular expressions to look for numbers present in the character array:
NumberSlices = regexp(ImageDes,'\d*','match')
In my case (20 slices), I get the following:
NumberSlices =
'1' '48' '20' '20'
The first 2 numbers are in ImageJ 1.48 so we don't want them, however you can fetch any of the last two numbers and you're good to go:
NumberSlices = str2double(NumberSlices{3})
If not, the simplest solution in my opinion is to use the output from imfinfo like so:
NumberImages = length(info_red);
which in your case should give 1860.
Sorry if it was very long as an answer; anyhow I think you will find useful the information about the Tiff class if you are to work with stacks in Matlab :)
Hope that helps!

!dumpobj in windbg,what does Domain:Value dynamic statics NYI 002a8428:NotInit mean?

When i use windbg !do to view a address,it output:
0:000> !do 01ef30f4
Name: System.Collections.Generic.List`1[[System.Byte[], mscorlib]]
MethodTable: 0021285c
EEClass: 6313a530
Size: 24(0x18) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
633b70a0 4000ca6 4 System.Object[] 0 instance 01eed1b8 _items
63402df0 4000ca7 c System.Int32 1 instance 0 _size
63402df0 4000ca8 10 System.Int32 1 instance 0 _version
633ffa60 4000ca9 8 System.Object 0 instance 00000000 _syncRoot
633b70a0 4000caa 0 System.Object[] 0 shared static _emptyArray
**Domain:Value dynamic statics NYI 002a8428:NotInit**
What's the meaning of Domain:Value dynamic statics NYI 002a8428:NotInit?
For static fields, !do displays the static field's value in each AppDomain you have. The first value, 002a8428, is the AppDomain address, and the second value is the static field's value in that AppDomain.