Code analysis - Do not dispose object multiple times - c#

i have tried following the rules of code analysis on this method:
public static string Encrypt(string password)
{
string myPassword = string.Empty;
if (!string.IsNullOrEmpty(password))
{
myPassword = password;
byte[] Value = System.Text.Encoding.UTF8.GetBytes(myPassword);
SymmetricAlgorithm mCSP = new RijndaelManaged();
mCSP.Key = _key;
mCSP.IV = _initVector;
using (ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV))
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
{
cs.Write(Value, 0, Value.Length);
cs.FlushFinalBlock();
cs.Close();
myPassword = Convert.ToBase64String(ms.ToArray());
}
}
}
}
return myPassword;
}
added all the Try {} Finaly{} blocks, but it was still yelling at me that i dont respect rule 2202.
anyone can give me a hand with this?
yes, i have read other posts about this subject and tried applying it,
but at the end i still get the same message.

To get rid of the CA2202 warning for cs, simply remove the call to its Close method.
The CA2202 problem for ms is a wee bit more complex. The warning is cropping up because CryptoStream has the effrontery to dispose the stream it received via is constructor, which means that there's one inappropriate call to ms.Close() that you can't avoid. The good news is that this untimely disposition has no side-effects in your case, and the same goes for the double disposition, so you can safely slap on a SuppressMessageAttribute and ignore the problem. (For cases where you actually need to passed stream to survive its unpreventable disposition by something like CryptoStream, the usual technique is to use a stream subclass whose disposition can be prevented by its instantiating code.)

Get rid of these two lines, they aren't needed:
cs.FlushFinalBlock();
cs.Close();

Following the documentation on this topic should lead to this code:
public static string Encrypt(string password)
{
string myPassword = string.Empty;
if (!string.IsNullOrEmpty(password))
{
myPassword = password;
byte[] Value = System.Text.Encoding.UTF8.GetBytes(myPassword);
SymmetricAlgorithm mCSP = new RijndaelManaged();
mCSP.Key = _key;
mCSP.IV = _initVector;
using (ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV))
{
System.IO.MemoryStream ms = null;
try
{
ms = new System.IO.MemoryStream()
var tmp = ms;
using (CryptoStream cs = new CryptoStream(ms, ct,
CryptoStreamMode.Write))
{
ms = null;
cs.Write(Value, 0, Value.Length);
cs.FlushFinalBlock();
cs.Close();
myPassword = Convert.ToBase64String(tmp.ToArray());
}
}
finally
{
if(ms != null)
ms.Dispose();
}
}
}
return myPassword;
}

The documentation on this analysis warning (http://msdn.microsoft.com/en-us/library/ms182334.aspx) gives this example, similar to yours in that it's manipulating streams:
Stream stream = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(stream))
{
stream = null;
// Use the writer object...
}
}
finally
{
if(stream != null)
stream.Dispose();
}
but this still gives the error. The following will solve the error:
Stream stream = null;
StreamWriter writer = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
writer = new StreamWriter(stream))
// Do some stuff on the stream writer..
}
finally
{
if(writer != null)
writer.Dispose();
else if(stream != null)
stream.Dispose();
}
The reason is simple; if the writer will always dispose the stream for you. Only in the scenario the writer is not successfully created should you dispose the stream yourself. But I must admit I like the following syntax a lot more, and if you create a MemoryStream instead of a FileStream the chance of an exception occurring is small and I would prefer suppressing the CA. Please notice that you can stack using statements, so a extra 'nesting level' is often not required.
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
using (StreamWriter writer = new StreamWriter(stream))
{
// Use the writer object...
}

Related

Why do I get an empty result when encrypting a string, even though I flushed the input stream?

I want to encrypt some string through RijndaelManaged and get encrypted result. I want to do it with MemoryStream. But I get the empty string. I get the same problem if I use Rijndael class instead of RijndaelManaged. What I did wrong?
static string EncodeString(string text, byte[] key, byte[] iv) {
RijndaelManaged alg = new RijndaelManaged();
var encryptor = alg.CreateEncryptor(key, iv);
string encodedString = null;
using (var s = new MemoryStream())
using (var cs = new CryptoStream(s, encryptor, CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs)) {
// encrypt the string
sw.Write(text);
sw.Flush();
cs.Flush();
s.Flush();
Console.WriteLine($"Stream position: {s.Position}"); // Oops... It is 0 still. Why?
// get encrypted string
var sr = new StreamReader(s);
s.Position = 0;
encodedString = sr.ReadToEnd(); // I get empty string here
}
return encodedString;
}
Then I use this method:
RijndaelManaged alg = new RijndaelManaged();
alg.GenerateKey();
alg.GenerateIV();
var encodedString = EncodeString("Hello, Dev!", alg.Key, alg.IV); // I get empty string. Why?
You have two issues here:
Problem 1: You try to read the result before it is ready. You need to close the StreamWriter first:
using (var s = new MemoryStream())
using (var cs = new CryptoStream(s, encryptor, CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs)) {
// encrypt the string
sw.Write(text);
Console.WriteLine(s.ToArray().Length); // prints 0
sw.Close();
Console.WriteLine(s.ToArray().Length); // prints 16
...
}
But why do I need this? Didn't you see all those Flush statements in my code? Yes, but Rijndael is a block cypher. It can only encrypt a block once it has read the full block (or you have told it that this was the final partial block). Flush allows further data to be written to the stream, so the encryptor cannot be sure that the block is complete.
You can solve this by explicitly telling the crypto stream that you are done sending input. The reference implementation does this by closing the StreamWriter (and, thus the CryptoStream) with a nested using statement. As soon as the CryptoStream is closed, it flushes the final block.
using (var s = new MemoryStream())
using (var cs = new CryptoStream(s, encryptor, CryptoStreamMode.Write))
{
using (var sw = new StreamWriter(cs))
{
// encrypt the string
sw.Write(text);
}
Console.WriteLine(s.ToArray().Length); // prints 16
...
}
Alternatively, as mentioned by Jimi in the comments, you can call FlushFinalBlock explicitly. In addition, you can skip the StreamWriter by explicitly converting your base string to a byte array:
using (var s = new MemoryStream())
using (var cs = new CryptoStream(s, encryptor, CryptoStreamMode.Write))
{
cs.Write(Encoding.UTF8.GetBytes(text));
cs.FlushFinalBlock();
Console.WriteLine(s.ToArray().Length); // prints 16
...
}
Or, as mentioned by V.Lorz in the comments, you can just dispose the CryptoStream to call FlushFinalBlock implicitly:
using (var s = new MemoryStream())
{
using (var cs = new CryptoStream(s, encryptor, CryptoStreamMode.Write))
{
cs.Write(Encoding.UTF8.GetBytes(text));
}
Console.WriteLine(s.ToArray().Length); // prints 16
...
}
Problem 2: You tried to read the result as a string. Encryption does not work on strings, it works on byte arrays. Thus, trying to read the result as an UTF-8 string will result in garbage.
Instead, you could, for example, use a Base64 representation of the resulting byte array:
return Convert.ToBase64String(s.ToArray());
Here are working fiddles of your code with all those fixes applied:
With StreamWriter: https://dotnetfiddle.net/8kGI4N
Without StreamWriter: https://dotnetfiddle.net/Nno0DF

iTextSharp PdfStamper consistently only writing out 15 bytes

I'm attempting to write a method for encrypting existing pdf's and writing out the encrypted pdf to a memory stream, using the following code:
public byte[] ProtectPdfStreamWithPassword(
string filePath,
string password)
{
using (var outStream = new MemoryStream())
{
using (var reader = new PdfReader(filePath))
{
using (var stamper = new PdfStamper(reader, outStream))
{
var passwordBytes =
Encoding.ASCII.GetBytes(password);
stamper.SetEncryption(
passwordBytes,
passwordBytes,
PdfWriter.AllowPrinting,
PdfWriter.ENCRYPTION_AES_256);
return outStream.ToArray();
}
}
}
}
I'm following the same pattern I've seen used elsewhere online but I'm running into an issue where the MemoryStream being written into only ever has 15 bytes written to it, when the file passed to the PdfReader has around 8Kb. I did not run into this issue when working with FileStreams instead but I'd prefer to use MemoryStreams here, if possible. Any help would be appreciated.
Okay, so the issue for me was returning the MemoryStream bytes from within the PdfStamper using block. There must be an implicit Flush going on that wasn't happening because I was returning the bytes too soon. I refactored my code to the following, which works:
public byte[] ProtectPdfStreamWithPassword(
string filePath,
string password)
{
using (var outStream = new MemoryStream())
{
using (var reader = new PdfReader(filePath))
{
using (var stamper = new PdfStamper(reader, outStream))
{
var passwordBytes =
Encoding.ASCII.GetBytes(password);
stamper.SetEncryption(
passwordBytes,
passwordBytes,
PdfWriter.AllowPrinting,
PdfWriter.ENCRYPTION_AES_256);
}
}
return outStream.ToArray();
}
}

MemoryStream disables reading when returned

In my program, I am basically reading in a file, doing some processing to it, and then passing it back to the main program as a memorystream, which will be handled by a streamreader. This will all be handled by a class beside my main.
The problem is, when I return the memory stream from my method in another class, the "canread" variable is set to false, and thus causes the streamreader initialization to fail.
Below is an example of the problem happening (though in here I'm writing to the memorystream in the other class, but it still causes the same error when i pass it back.
In the class named "Otherclass":
public static MemoryStream ImportantStreamManipulator()
{
MemoryStream MemStream = new MemoryStream();
StreamWriter writer = new StreamWriter(MemStream);
using (writer)
{
//Code that writes stuff to the memorystream via streamwriter
return MemStream;
}
}
The function calls in the main program:
MemoryStream MStream = Otherclass.ImportantStreamManipulator();
StreamReader reader = new StreamReader(MStream);
When I put a breakpoint on the "return MemStream", the "CanRead" property is still set to true. Once I step such that it gets back to my main function, and writes the returned value to MStream, the "CanRead" property is set to false. This then causes an exception in StreamReader saying that MStream could not be read (as the property indicated). The data is in the streams buffer as it should be, but I just can't get it out.
How do I set it so that "CanRead" will report true once it is returned to my main? Or am I misunderstanding how MemoryStream works and how would I accomplish what I want to do?
This is the problem:
using (writer)
{
//Code that writes stuff to the memorystream via streamwriter
return MemStream;
}
You're closing the writer, which closes the MemoryStream. In this case you don't want to do that... although you do need to flush the writer, and rewind the MemoryStream. Just change your code to:
public static MemoryStream ImportantStreamManipulator()
{
// Probably add a comment here stating that the lack of using statements
// is deliberate.
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
// Code that writes stuff to the memorystream via streamwriter
writer.Flush();
stream.Position = 0;
return stream;
}
The StreamWriter takes ownership of the memory stream and when the using statement ends, the MemoryStream is also closed.
See Is there any way to close a StreamWriter without closing its BaseStream?.
As others have stated, the problem is that the Stream is closed when the StreamWriter is closed. One possible way to deal with this is to return a byte array rather than a MemoryStream. This avoids having potentially long running objects that must be disposed by the garbage collector.
public static void Main()
{
OutputData(GetData());
}
public static byte[] GetData()
{
byte[] binaryData = null;
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
string data = "My test data is really great!";
sw.Write(data);
sw.Flush();
binaryData = ms.ToArray();
}
return binaryData;
}
public static void OutputData(byte[] binaryData)
{
using (MemoryStream ms = new MemoryStream(binaryData))
using (StreamReader sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
}
Another method is to copy the Stream to another stream prior to returning. However, this still has the problem that subsequent access to it with a StreamReader will close that stream.
public static void RunSnippet()
{
OutputData(GetData());
}
public static MemoryStream GetData()
{
MemoryStream outputStream = new MemoryStream();
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
string data = "My test data is really great!";
sw.Write(data);
sw.Flush();
ms.WriteTo(outputStream);
outputStream.Seek(0, SeekOrigin.Begin);
}
return outputStream;
}
public static void OutputData(MemoryStream inputStream)
{
using (StreamReader sr = new StreamReader(inputStream))
{
Console.WriteLine(sr.ReadToEnd());
}
}

BinaryFormatter & CryptoStream problem when deserializing

I'm getting a bit desperate here. I'm trying to write an encrypted file with a serialized object to disk and later retrieve the file, decrypt it and deserialize the object back.
UPDATE:
I refactored the code to this:
using (Stream innerStream = File.Create(this.GetFullFileNameForUser(securityContext.User, applicationName)))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateEncryptor(), CryptoStreamMode.Write))
{
// 3. write to the cryptoStream
//BinaryFormatter bf = new BinaryFormatter();
//bf.Serialize(cryptoStream, securityContext);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
xs.Serialize(cryptoStream, securityContext);
}
}
using (Stream innerStream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read))
{
//BinaryFormatter bf = new BinaryFormatter();
//return (SecurityContextDTO)bf.Deserialize(cryptoStream);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
//CryptographicException here
return (SecurityContextDTO)xs.Deserialize(cryptoStream);
}
}
Now I'm getting a cryptographic exception on deserialize: Bad Data
ORIGINAL:
I'm doing this:
public void StoreToFile(SecurityContextDTO securityContext, string applicationName)
{
if (securityContext.LoginResult.IsOfflineMode == false)
{
Stream stream = null;
CryptoStream crStream = null;
try
{
TripleDESCryptoServiceProvider cryptic = GetCryptoProvider();
stream = File.Open(this.GetFullFileNameForUser(securityContext.User, applicationName), FileMode.Create);
crStream = new CryptoStream(stream,
cryptic.CreateEncryptor(), CryptoStreamMode.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(crStream, securityContext);
}
catch(Exception)
{
throw;
}
finally
{
if (crStream != null)
crStream.Close();
}
}
}
public SecurityContextDTO RetrieveFromFile(UserDTO user,string applicationName)
{
SecurityContextDTO objectToSerialize;
Stream stream = null;
CryptoStream crStream=null;
try
{
stream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open);
crStream= new CryptoStream(stream,
GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
//Exception here
objectToSerialize = (SecurityContextDTO)bFormatter.Deserialize(crStream);
}
catch (Exception)
{
objectToSerialize = null;
}
finally
{
if (crStream!=null)
crStream.Close();
}
return objectToSerialize;
}
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose();
}
return cryptic;
}
Encrypting and writing works fine, the file appears on the disk and the content is there (encrypted of course). But when I call the retrieve method I always get a SerializationException
Binary stream '30' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
When I leave the cryptographic methods out everything works fine.
So,
You realize that in this code
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose(); // <------- Don't do this until you are done decrypting.
}
return cryptic;
}
you will ALWAYS dispose of the provider meaning you are always using a random key and iv
You are close. However, the stream you pass into the creation of CryptoStream is always, always, always the buffer that will hold your end result. It is not the stream that holds the data you want to encrypt or decrypt. I put the emphasis in there because I remember learning this for the first time and I did exactly what you were doing. So here:
// this is for encryption
var memStreamEncryptedData = new MemoryStream();
var encryptStream = new CryptoStream(memStreamEncryptedData,
transform, CryptoStreamMode.Write);
// this is for decryption
var memStreamDecryptedData = new MemoryStream();
var decryptStream = new CryptoStream(memStreamDecryptedData,
transform, CryptoStreamMode.Write);
Notice in both cases, CryptoStream is being initialized with a blank output stream. Your stream does not enter into the picture until later. So, during a write, you will do the following:
encryptStream.Write(dataToBeEncrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamEncryptedData now safely holds your encrypted data
And during the read, you will:
decryptStream.Write(dataToBeDecrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamDecryptedData now safely holds your decrypted data
So, to save you some trouble, here's a nice simple Symmetric method that will perform both encryption and decryption. The only difference between this and yours is that I am working directly on byte arrays, but perhaps that augmentation can be an exercise:
public static byte[] Symmetric(bool encrypt, byte[] plaintext, string ikey)
{
if (plaintext.Length == 0) return plaintext;
// setting up the services can be very expensive, so I'll cache them
// into a static dictionary.
SymmetricSetup setup;
if (!_dictSymmetricSetup.TryGetValue(ikey, out setup))
{
setup = new SymmetricSetup();
setup.des = new DESCryptoServiceProvider { Mode = CipherMode.CBC,
Padding = PaddingMode.Zeros };
setup.hash = Hash(Encoding.ASCII.GetBytes(ikey));
setup.key = setup.hash.ForceLength(8, 0);
setup.IV = Encoding.ASCII.GetBytes("init vec");
setup.des.Key = setup.key;
setup.des.IV = setup.IV;
setup.encrypt = setup.des.CreateEncryptor(setup.des.Key, setup.des.IV);
setup.decrypt = setup.des.CreateDecryptor(setup.des.Key, setup.des.IV);
_dictSymmetricSetup[ikey] = setup;
}
var transform = encrypt ? setup.encrypt : setup.decrypt;
var memStreamEncryptedData = new MemoryStream();
var encStream = new CryptoStream(memStreamEncryptedData, transform, CryptoStreamMode.Write);
if (encrypt)
encStream.Write(new[] {(byte) ((8 - (plaintext.Length + 1)%8)%8)}, 0, 1);
encStream.Write(plaintext, 0, plaintext.Length);
encStream.FlushFinalBlock();
encStream.Close();
memStreamEncryptedData.Flush();
var ciphertext = memStreamEncryptedData.ToArray();
byte b;
if (!encrypt)
if (byte.TryParse("" + ciphertext[0], out b))
ciphertext = ciphertext.Skip(1).Take(ciphertext.Length - b - 1).ToArray();
return ciphertext;
}
And to call it, you might do something like this:
static public byte[] DecryptData(this byte[] source, string password) {
return Symmetric(false, source, password);
}
static public byte[] EncryptData(this byte[] source, string password) {
return Symmetric(true, source, password);
}
Again, you'll do something slightly different to work with streams, but hopefully you get the gist. Instead of MemoryStream, it will be whatever stream you need to feed into your serializer.
Some previous posts that can be of use:
How do I encrypt a string in vb.net using RijndaelManaged, and using PKCS5 padding?
Does BinaryFormatter apply any compression?
In later, you can see how I stacked compression with encryption with serialization. And it works.

StreamReader ReadToEnd() returns empty string on first attempt

I know this question has been asked before on Stackoverflow, but could not find an explanation.
When I try to read a string from a compressed byte array I get an empty string on the first attempt, on the second I succed and get the string.
Code example:
public static string Decompress(byte[] gzBuffer)
{
if (gzBuffer == null)
return null;
using (var ms = new MemoryStream(gzBuffer))
{
using (var decompress = new GZipStream(ms, CompressionMode.Decompress))
{
using (var sr = new StreamReader(decompress, Encoding.UTF8))
{
string ret = sr.ReadToEnd();
// this is the extra check that is needed !?
if (ret == "")
ret = sr.ReadToEnd();
return ret;
}
}
}
}
All suggestions are appreciated.
- Victor Cassel
I found the bug. It was as Michael suggested in the compression routine. I missed to call Close() on the GZipStream.
public static byte[] Compress(string text)
{
if (string.IsNullOrEmpty(text))
return null;
byte[] raw = Encoding.UTF8.GetBytes(text);
using (var ms = new MemoryStream())
{
using (var compress = new GZipStream (ms, CompressionMode.Compress))
{
compress.Write(raw, 0, raw.Length);
compress.Close();
return ms.ToArray();
}
}
}
What happened was that the data seemed to get saved in a bad state that required two calls to ReadToEnd() in the decompression routine later on to extract the same data. Very odd!
try adding ms.Position = 0 before string ret = sr.ReadToEnd();
Where is gzBuffer coming from? Did you also write the code that is producing the compressed data?
Perhaps the buffer data you have is invalid or somehow incomplete, or perhaps it consists of multiple deflate streams concatenated together.
I hope this helps.
For ByteArray:
static byte[] CompressToByte(string data)
{
MemoryStream outstream = new MemoryStream();
GZipStream compressionStream =
new GZipStream(outstream, CompressionMode.Compress, true);
StreamWriter writer = new StreamWriter(compressionStream);
writer.Write(data);
writer.Close();
return StreamToByte(outstream);
}
static string Decompress(byte[] data)
{
MemoryStream instream = new MemoryStream(data);
GZipStream compressionStream =
new GZipStream(instream, CompressionMode.Decompress);
StreamReader reader = new StreamReader(compressionStream);
string outtext = reader.ReadToEnd();
reader.Close();
return outtext;
}
public static byte[] StreamToByte(Stream stream)
{
stream.Position = 0;
byte[] buffer = new byte[128];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (!(read > 0))
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
You can replace if(!(read > 0)) with if(read <= 0).
For some reason if(read <= 0) isn't displayed corret above.
For Stream:
static Stream CompressToStream(string data)
{
MemoryStream outstream = new MemoryStream();
GZipStream compressionStream =
new GZipStream(outstream, CompressionMode.Compress, true);
StreamWriter writer = new StreamWriter(compressionStream);
writer.Write(data);
writer.Close();
return outstream;
}
static string Decompress(Stream data)
{
data.Position = 0;
GZipStream compressionStream =
new GZipStream(data, CompressionMode.Decompress);
StreamReader reader = new StreamReader(compressionStream);
string outtext = reader.ReadToEnd();
reader.Close();
return outtext;
}
The MSDN Page on the function mentions the following:
If the current method throws an OutOfMemoryException, the reader's position in the underlying Stream object is advanced by the number of characters the method was able to read, but the characters already read into the internal ReadLine buffer are discarded. If you manipulate the position of the underlying stream after reading data into the buffer, the position of the underlying stream might not match the position of the internal buffer. To reset the internal buffer, call the DiscardBufferedData method; however, this method slows performance and should be called only when absolutely necessary.
Perhaps try calling DiscardBufferedData() before your ReadToEnd() and see what it does (I know you aren't getting the exception, but it's all I can think of...)?

Categories

Resources