Sicos1977 / MSGReader

C# Outlook MSG file reader without the need for Outlook
http://sicos1977.github.io/MSGReader
MIT License
489 stars 168 forks source link

v5.5.3 uses Microsoft.IO.RecyclableMemoryStream 3.0.0 #387

Closed elylv closed 9 months ago

elylv commented 9 months ago

using (var msg = new StorageMessage(memorystrem)) gives an exception:

Method not found: Microsoft.IO.RecyclableMemoryStream Microsoft.IO.RecyclableMemoryStreamManager()

It seems v3 of Microsoft.IO.RecyclableMemoryStream does not have this call available any more, and you should be using v2.3.2 instead. Since the package version specified in the nuget is >=3.0.0, even trying to force 2.3.2 doesn't work.

Downgrading to v5.5.1 has dependence on 2.3.2 and does not throw the above exception. Guess you just need to change the required version dependency in the package, or rewrite to avoid using that particular call.

elylv commented 9 months ago

Method not found: Microsoft.IO.RecyclableMemoryStream Microsoft.IO.RecyclableMemoryStreamManager(string, byte[], int, int) to be exact!

Sicos1977 commented 9 months ago

Is this method called from MSGReader or are you using it in your own code?

There are some breaking changes in v3.0 because Microsoft moved things to other places.

elylv commented 9 months ago

It looks like it's being called from the new StorageMessage() in MsgReader. It's not being called in my code.

Sicos1977 commented 9 months ago

I dont have any exceptions when trying to load with a memory stream. The one you see in the screenshot is obvious because I just used an empty memorystream with nothing in it.

image

Sicos1977 commented 9 months ago

Also no problems when reading a real file.

image

Nir1812 commented 9 months ago

I have the same exception. When reverting to Microsoft.IO.RecyclableMemoryStream version 2.3.2 it goes away. But when using v3.0 I get: System.MissingMethodException: Method not found: 'System.IO.MemoryStream Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)'

Sicos1977 commented 9 months ago

I have the same exception. When reverting to Microsoft.IO.RecyclableMemoryStream version 2.3.2 it goes away. But when using v3.0 I get: System.MissingMethodException: Method not found: 'System.IO.MemoryStream Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)'

On what .net version are you?

Numpsy commented 9 months ago

Method not found: 'System.IO.MemoryStream Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)'

One of the breaking changes in v3 is listed as

All overloads of RecyclableMemoryStreamManager.GetStream now return type RecyclableMemoryStream instead of MemoryStream.

which might be an issue if you have other things in your app that depend on v2 and the old signature?

Sicos1977 commented 9 months ago

It would also be nice to see a stack trace so that I know where it goes wrong, just the exception is not enough.

Sicos1977 commented 9 months ago

Method not found: 'System.IO.MemoryStream Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)'

One of the breaking changes in v3 is listed as

All overloads of RecyclableMemoryStreamManager.GetStream now return type RecyclableMemoryStream instead of MemoryStream.

which might be an issue if you have other things in your app that depend on v2 and the old signature?

I guess it goes wrong if you explicitly declare your variable like RecyclableMemoryStream myVar =

I'm used to do it like this var myVar =

Don't know if it is in this case but if the Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)' gets casted to a MemoryStream it can go wrong???

Nir1812 commented 9 months ago

It would also be nice to see a stack trace so that I know where it goes wrong, just the exception is not enough.

at MsgReader.Outlook.Storage.Message.LoadAttachmentStorage(CFStorage storage, String storageName) at MsgReader.Outlook.Storage.Message.LoadStorage(CFStorage storage)

Sicos1977 commented 9 months ago

On what .net version are you?

Nir1812 commented 9 months ago

On what .net version are you?

4.7.2

Sicos1977 commented 9 months ago

I just can't get it reproduced...

The example below also visited the LoadAttachmentStorage method and without any errors. I tried it with the MSGViewer and that one is compiled against .net 4.6.2

image

Sicos1977 commented 9 months ago

Is it with a specific file? I guess it is one with an attachment but do you have it with all files that have an attachment?

Sicos1977 commented 9 months ago

And are you sure that your project is not somehow overwritting version 3.0 with an older version... or that you have some kind of binding redirect somewhere that is pointing to an old version?

Numpsy commented 9 months ago

Don't know if it is in this case but if the Microsoft.IO.RecyclableMemoryStreamManager.GetStream(System.String, Byte[], Int32, Int32)' gets casted to a MemoryStream it can go wrong???

Offhand I'd expect MsgReader that's built against the new version to work, and any other code you happened to have about referencing the old version to have issues, unless as you say the old version is getting loaded somehow.

And are you sure that your project is not somehow overwritting version 3.0 with an older version... or that you have some kind of binding redirect somewhere that is pointing to an old version?

At a risk of making a possibly misleading suggestion, but maybe worth checking - I was just reading this issue where someone had a similar issue in Serilog due to .NET 4.7.2 loading old versions of dlls from the GAC rather than the newer required versions

Sicos1977 commented 9 months ago

Should be fixed in the latest version.

elylv commented 9 months ago

I'm still seeing issues in .net 8 with latest version.

Stack trace on the exception: at MsgReader.Outlook.Storage.GetMapiPropertyFromStreamOrStorage(String propIdentifier) at MsgReader.Outlook.Storage.GetMapiProperty(String propIdentifier) at MsgReader.Outlook.Storage.GetMapiPropertyString(String propIdentifier) at MsgReader.Outlook.Storage.Recipient..ctor(Storage message) at MsgReader.Outlook.Storage.Message.LoadStorage(CFStorage storage) at MsgReader.Outlook.Storage..ctor(Stream storageStream, FileAccess fileAccess) at MsgReader.Outlook.Storage.Message..ctor(Stream storageStream, FileAccess fileAccess) at ...my code

Sicos1977 commented 9 months ago

I had the problem on .net 4.8 and it went away with this commit fb17d395fd73d377b30516036493486884deb525 .

Sicos1977 commented 9 months ago

I have no problems testing against al .net versions

image

Sicos1977 commented 9 months ago

Also no problem loading an MSG file with attachment

image

image

Sicos1977 commented 9 months ago

Also no problems when debugging in .net 8 and walking through the method that is giving you the exception

image

Can you try to debug the code and see what line is raising the exception because I just have no idea why I don't have any problems

elylv commented 9 months ago

This is the code up to the line that causes the exception:

using (MemoryStream ms = new MemoryStream())
{
    await ms.WriteAsync(filedata, 0, filedata.Length);
    try
    {
        using (var msg = new Storage.Message(ms))
        {
Sicos1977 commented 9 months ago

That code is not in th MSGReader project.. is that your own code?

Sicos1977 commented 9 months ago

Works without any problems.

Is fileData a byte array? .. if so why don't you just use the constructor to inject it into the memory stream? It is probably faster because you don't need a state machine

image

Sicos1977 commented 9 months ago

Also without problems on .net 8.. I cant use the await keyword because I can't make test methods async.

image

elylv commented 9 months ago

The data comes from a web upload, not an actual file, so it's already in a byte array. This code also runs in the browser (via Blazor Webassembly). I just tried running the same code on the server and it runs without issue. Running it in the browser seems to cause the problem. I'm not sure if it's some kind of compatibility issue when running in browser mode, I can't see any warnings about "unsupported in browser" for Microsoft.IO.RecyclableMemoryStream

I'll see if I can work around this since I would eventually be sending the data to the server anyway, was just saving on server processing time by processing the mail on the client browser.