serialization shared memory problem

N

norvinl

Hi,

I'm serializing a class and using shared memory / deserialization to
send it to other processes.

I can serialize with one app and deserialize with another instance of
the same app.

But if I try to deserialize with another different app, I get an
exception (the assembly RegionViewer is the app that serialized the
data):

<Exception>
An unhandled exception of type
'System.Runtime.Serialization.SerializationException' occurred in
mscorlib.dll

Additional information: Cannot find the assembly RegionViewer,
Version=1.0.2466.11715, Culture=neutral, PublicKeyToken=null.
</Exception>

Is this a security thing with serializing? Is there some way of getting
around it?

Thanks,
Norvin
 
N

norvinl

Hi Chris ,

Chris said:
Do you need to set typeFilterLevel=Full ?

Just a guess really, more info here...
http://msdn2.microsoft.com/en-us/library/5dxse167.aspx

Wow, that filterTypeLevel looks like a nightmare. Since I'm not
remoting, and the class I want to copy is fairly simple, perhaps a step
back is in order. Maybe I don't need to be serializing here.

A question: I have a class, I have a destination pointer, how can I do
the equivalent of memcpy( ptrDestination, &myClass, sizeof(myClass); ?

It looks like all the overloads for Marshal.Copy require some kind of
byte array representation of the data.

Below is my class definition:

public class Sync
{
public string sensorType;
public string imageType;
public string imageNumber;
public string imageChannel;
public string imageFace;
public string extension;
public Point vScroll;
public int overlayAlpha;
public decimal xScale;
public decimal yScale;
public FLAGS signal;
public string currentFolder;
public Rectangle highlightRect;
}
 
W

Willy Denoyette [MVP]

| Hi Chris ,
|
| Chris Fulstow wrote:
| > Do you need to set typeFilterLevel=Full ?
| >
| > Just a guess really, more info here...
| > http://msdn2.microsoft.com/en-us/library/5dxse167.aspx
| >
|
| Wow, that filterTypeLevel looks like a nightmare. Since I'm not
| remoting, and the class I want to copy is fairly simple, perhaps a step
| back is in order. Maybe I don't need to be serializing here.
|
| A question: I have a class, I have a destination pointer, how can I do
| the equivalent of memcpy( ptrDestination, &myClass, sizeof(myClass); ?
|
| It looks like all the overloads for Marshal.Copy require some kind of
| byte array representation of the data.
|
| Below is my class definition:
|
| public class Sync
| {
| public string sensorType;
| public string imageType;
| public string imageNumber;
| public string imageChannel;
| public string imageFace;
| public string extension;
| public Point vScroll;
| public int overlayAlpha;
| public decimal xScale;
| public decimal yScale;
| public FLAGS signal;
| public string currentFolder;
| public Rectangle highlightRect;
| }
|


You could use a BinaryFormater to serialize the object to a MemoryStream.
Following is a small snip that illustrates how one could go for the
serializer, the deserializer should perform the inverse operations.


Sync mySync = new Sync();
....
IntPtr pBuffer = MapViewOfFile(....);

MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, mySync);
// Write the mapped portion length at the start of the shared memory
buffer.
// The deserializer must pick up this size from the shared portion to
reconstruct the object.
Marshal.WriteInt32(new IntPtr(pBuffer), (int)ms.Length);
byte[] mngdBuffer = ms.GetBuffer();
Marshal.Copy(mngdBuffer, 0, new IntPtr((int)pBuffer + 4),
(int)ms.Length);
UnmapViewOfFile(pBuffer);

Willy.
 
N

norvinl

Hi Willy,
| A question: I have a class, I have a destination pointer, how can I do
| the equivalent of memcpy( ptrDestination, &myClass, sizeof(myClass); ?


You could use a BinaryFormater to serialize the object to a MemoryStream.
Following is a small snip that illustrates how one could go for the
serializer, the deserializer should perform the inverse operations.

What you suggest is exactly what I'm doing at the moment. As my initial
post in this thread indicates, I have security issues when I try to
deserialize a stream that was serialized in another app.

So:
- either there is a simple way to get around those security exceptions.
After all, I have control of the code for both the app doing the
serializing as well as the app doing the deserializing.
- OR there must be a simple way to copy a class to memory without first
having to serialize it.

Any suggestions to accomplish either of the above?

Norvin
 
G

Gino

I did something similar almost 2 years ago, so I don't remember the details,
but I had the same problem that you are having. I was serializing an object
and sending it over the network and then deserialized it and was getting an
error. After searching on google it turned out that when an app serializes
an object it puts some identifying information in a property that the
deserializing app will not have which is what caused the error. As I
remember it, I had to set this property to nothing, and that took care of
the problem.
 
W

Willy Denoyette [MVP]

| Hi Willy,
|
| Willy Denoyette [MVP] wrote:
| >
| > | A question: I have a class, I have a destination pointer, how can I do
| > | the equivalent of memcpy( ptrDestination, &myClass, sizeof(myClass); ?
| >
| >
| > You could use a BinaryFormater to serialize the object to a
MemoryStream.
| > Following is a small snip that illustrates how one could go for the
| > serializer, the deserializer should perform the inverse operations.
|
| What you suggest is exactly what I'm doing at the moment. As my initial
| post in this thread indicates, I have security issues when I try to
| deserialize a stream that was serialized in another app.
|
| So:
| - either there is a simple way to get around those security exceptions.
| After all, I have control of the code for both the app doing the
| serializing as well as the app doing the deserializing.
| - OR there must be a simple way to copy a class to memory without first
| having to serialize it.
|
| Any suggestions to accomplish either of the above?
|
| Norvin
|

I don't see where the security exception comes from.

This should work, supposed at the serializer side you have something like
this:

Sync mySync= new Sync();
mySync.sensorType = "....";
// other fields
MemoryStream ms = new MemoryStream();
IntPtr pBuf = // pointer returned from the MapViewOfFile API call
if (pBuf != IntPtr.Zero)
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, mySync);
Marshal.WriteInt32(pBuf, (int)ms.Length);
byte[] buff = ms.GetBuffer();
Marshal.Copy(buff, 0, new IntPtr((int)pBuf + 4), (int)ms.Length);
}
...

and at the deserializer side, this:
..
int len = 0;
len = Marshal.ReadInt32(pBuf, 0);
byte[] data = new byte[len];
Marshal.Copy(new IntPtr((int)pBuf + sizeof(int)), data, 0, len);
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(data);
Sync s = (Sync) bf.Deserialize(ms);
Console.WriteLine("{0} {1} {2} {3}", s.sensorType, s.vScroll,
s.overlayAlpha, s.xScale);

and both use the same type "Sync" from a shared assembly.

Willy.
 
N

norvinl

Hi Gino,

This sounds like the same problem I'm seeing. The exception that I'm
getting complains that it can't find info about the app that did the
serializing:

"Cannot find the assembly RegionViewer,
Version=1.0.2466.11715, Culture=neutral, PublicKeyToken=null."

where RegionViewer is the app that did the serializing. Do you happen
to remember what object the property was in? The formatter, or the
stream itself?

Thanks,
Norvin
 
N

norvinl

If anyone is interested, I ended up solving this problem.

If you serialize in one app, and want to deserialize in another app, an
exception will be thrown if dotnet can't load the assembly that did the
serializing.

Option 1: register the serializing app in the GAC. I didn't try this,
but I assume it would work
Option 2: use the SerializationBinder class to effectively fool the
deserializing app into thinking that it did the serializing:


when setting your BinaryFormatter up to deserialize, set the Binder
property to the class below:

BinaryFormatter b = new BinaryFormatter();
b.Binder = new FooDeserializationBinder();
myClasss = (MyClass) b.Deserialize(stream);

sealed class FooDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string
typeName)
{
return Type.GetType(typeName + ", " +
Assembly.GetExecutingAssembly().FullName);
}
}
 
W

Willy Denoyette [MVP]

Weird, you shouldn't get a "security" exception when a type failed to load,
you should receive a typeload exception.
Also you don't need the type that did the serialization, what you need is
the type you are serializing/deserializing. This type can be installed as a
(preferably) private or as a global assembly, depending your needs. The
SerializationBinder is an option, but IMO shouldn't be used in this case,
it's an option when you need to deserialize to a different version.

Willy.


| If anyone is interested, I ended up solving this problem.
|
| If you serialize in one app, and want to deserialize in another app, an
| exception will be thrown if dotnet can't load the assembly that did the
| serializing.
|
| Option 1: register the serializing app in the GAC. I didn't try this,
| but I assume it would work
| Option 2: use the SerializationBinder class to effectively fool the
| deserializing app into thinking that it did the serializing:
|
|
| when setting your BinaryFormatter up to deserialize, set the Binder
| property to the class below:
|
| BinaryFormatter b = new BinaryFormatter();
| b.Binder = new FooDeserializationBinder();
| myClasss = (MyClass) b.Deserialize(stream);
|
| sealed class FooDeserializationBinder : SerializationBinder
| {
| public override Type BindToType(string assemblyName, string
| typeName)
| {
| return Type.GetType(typeName + ", " +
| Assembly.GetExecutingAssembly().FullName);
| }
| }
|
| (e-mail address removed) wrote:
| > Hi Gino,
| >
| > This sounds like the same problem I'm seeing. The exception that I'm
| > getting complains that it can't find info about the app that did the
| > serializing:
| >
| > "Cannot find the assembly RegionViewer,
| > Version=1.0.2466.11715, Culture=neutral, PublicKeyToken=null."
| >
| > where RegionViewer is the app that did the serializing. Do you happen
| > to remember what object the property was in? The formatter, or the
| > stream itself?
| >
| > Thanks,
| > Norvin
| >
| >
| >
| > Gino wrote:
| > > I did something similar almost 2 years ago, so I don't remember the
details,
| > > but I had the same problem that you are having. I was serializing an
object
| > > and sending it over the network and then deserialized it and was
getting an
| > > error. After searching on google it turned out that when an app
serializes
| > > an object it puts some identifying information in a property that the
| > > deserializing app will not have which is what caused the error. As I
| > > remember it, I had to set this property to nothing, and that took care
of
| > > the problem.
| > >
| > >
| > >
| > > | > > > Hi Willy,
| > > >
| > > > Willy Denoyette [MVP] wrote:
| > > >>
| > > >> | A question: I have a class, I have a destination pointer, how can
I do
| > > >> | the equivalent of memcpy( ptrDestination, &myClass,
sizeof(myClass); ?
| > > >>
| > > >>
| > > >> You could use a BinaryFormater to serialize the object to a
MemoryStream.
| > > >> Following is a small snip that illustrates how one could go for the
| > > >> serializer, the deserializer should perform the inverse operations.
| > > >
| > > > What you suggest is exactly what I'm doing at the moment. As my
initial
| > > > post in this thread indicates, I have security issues when I try to
| > > > deserialize a stream that was serialized in another app.
| > > >
| > > > So:
| > > > - either there is a simple way to get around those security
exceptions.
| > > > After all, I have control of the code for both the app doing the
| > > > serializing as well as the app doing the deserializing.
| > > > - OR there must be a simple way to copy a class to memory without
first
| > > > having to serialize it.
| > > >
| > > > Any suggestions to accomplish either of the above?
| > > >
| > > > Norvin
| > > >
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top