Multimobile Development: Building Applications for any Smartphone
"Invalid PInvoke metadata format" in OracleClient 1.1 Beta when loaded dynamically from 1.0 code (Advanced question)
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.clr.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.

Carlos J. Quintero
Hi,

I know that the .Net Framework 1.1 is in beta, but I would like to know if
an assembly created with .Net Framework 1.0 can load dynamically an assembly
created with .Net Framework 1.1 and call its methods or if this scenario is
not supported. I ask this because I have found an issue in the OracleClient
1.1 Beta when called dynamically from .Net 1.0 code.

To know what I mean, follow these steps:

1) Install VS.NET 2002 and .Net Framework 1.0 in your machine
2) Install the .Net Framework Data Provider for Oracle that you must
download separately (not included in .Net Framework 1.0)
3) Install VS.Net 2003 Final Beta, which includes .Net Framework 1.1 Beta
and a .Net Framework Data Provider for Oracle. Now, your machine has 2 .Net
Framework Data Providers for Oracle, one for .Net Framework 1.0 and another
for .Net Framework 1.1 Beta.
4) Using VS.Net 2002, create a VB.Net application and merge this code in the
Form1.vb file:

Option Strict Off

Imports System.Reflection

Friend Class Form1
Inherits System.Windows.Forms.Form
....
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Test()
End Sub

Private Sub Test()

Dim objAssembly As System.Reflection.Assembly
Dim objType As Type
Dim objObject As Object

' This loads explicitly the version of the .Net Framework 1.0 and it works
fine
'objAssembly = System.Reflection.Assembly.Load("System.Data.OracleClient,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

' This loads implicitly the version of the .Net Framework 1.1 Beta
(1.0.5000) and it gives "Invalid PInvoke metadata format."
objAssembly =
System.Reflection.Assembly.LoadWithPartialName("System.Data.OracleClient")

If Not objAssembly Is Nothing Then

MessageBox.Show(objAssembly.FullName) ' This should show
"System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"

Try
objType =
objAssembly.GetType("System.Data.OracleClient.OracleConnection", True)

objObject = System.Activator.CreateInstance(objType)

' Assume Option Strict Off for Late Binding
objObject.ConnectionString = "Data Source=MyOracleServiceName;Integrated
Security=yes"
objObject.Open()
objObject.Close()

MessageBox.Show("Test OK")

Catch objException As Exception
MessageBox.Show(objException.ToString)
End Try

End If

End Sub

End Class

5) Run the project from the VS.Net 2002 IDE.

I get a "Invalid PInvoke metadata format" in system.data.oracleclient.dll
when the Open method is called.

Explanation:

- The code loads the assembly of the OracleClient by partial name. It seems
that given two versions of that assembly, the most new assembly is loaded;
in this case, the one of the .Net Framework 1.1 Beta (1.0.5000.0 instead of
1.0.3300.0).

- The Open method causes an exception "Invalid PInvoke metadata format" in
system.data.oracleclient.dll. This exception is thrown in a call
System.Data.OracleClient.SafeNativeMethods.LoadLibraryExA(String lpFileName,
IntPtr hfile, Int32 dwFlags) that the OracleClient does to load the OCI
client library.

- The code is correct because loading the OracleClient 1.0 explicitly using
objAssembly = System.Reflection.Assembly.Load("System.Data.OracleClient,
Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") it
works fine.

- Also, when this project is run from the VS.Net 2003 Final Beta, using the
..Net 1.1 code instead of .Net 1.0 code, it works fine too.

So, it seems that the problem is calling .Net 1.1 code from .Net 1.0 code.

Comments?

Thanks in advance,

Carlos Quintero

Reply to this message...
Vote that this is a GOOD answer...
 
Really good experience at the Apple Store
MonoDroid – looking *awesome*
 
    
Angel Saenz-Badillos[MS] (VIP)
Carlos, awesome post! you certainly have done a lot of research into this
area and Everet has not been out that long. Side by Side is going to be a
major issue with people as we roll out Everet and it is important that
people understand a little of what we are trying to do here. Your post does
a great job of describing the behavior, let me go over a few of the major
points we are dealing with here:

First of all, our goal when releasing Everet is to make it Side by Side
compatible with all other versions of the URT. Side-by-side execution does
not mean that a managed component is compatible with other versions of the
runtime.. What it means is that a managed application can choose what
runtime it executes with, and that multiple versions of the runtime,
applications, and components can coexist on the same computer. The choice of
which runtime version an application uses is set by the application using
configuration files.

Ideally we want to see the code that compiled under a specific version of
the urt running against that version, there are two big exceptions. ASP.NET
and COM loading automatically default to the latest version of the urt
installed in your machine unless you configure them to do otherwise, and the
second exception is forward compatiblity between RTM and Everet. You will be
able to run most RTM applications on Everet without any configuration if RTM
is not present in your computer. I say most because there are some breaking
changes between the two versions, most of these changes are related to
security issues, these are fairly obscure issues like if you try to
PermitOnly before opening an Oledb connection we used to allow you to open
the connection, on Everet it will fail since we are now demanding Full
Trust.

So what about your example? Well when you do the
System.Reflection.Assembly.Load you are running into the COM loading
exception to the rule. When you try to execute both 1.0 and 1.1 components
in the same process you can get unexpected behavior, in this case there has
been a change in the Open method that throws the Pinvoke method.

Looking forward to hearing any comments, suggestions and questions about
side by side,
Hope this helped,
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

"Carlos J. Quintero" <Click here to reveal e-mail address> wrote
in message news:u0DpI7BqCHA.2008@TK2MSFTNGP12...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Carlos J. Quintero
Hi Angel,

[Original message clipped]

Yes, I have came to that conclussion too. Say that you want to load
dynamically the OracleClient 1.0 from .Net 1.0 code and OracleClient 1.1
from .Net 1.1 code. Which is the best approach to do this? I mean:

a) I can use fully qualified assembly names:

In .Net 1.0 code:
objAssembly = Assembly.Load("System.Data.OracleClient, Version=1.0.3300.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089")

In .Net 1.1 code:
objAssembly = Assembly.Load("System.Data.OracleClient, Version=1.0.5500.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089")

But that uses hard-coded data which maybe is not the best idea, because a
future service pack for a given .Net framework can change the version
numbers.

b) I think that I can use the full filename and the method
Assembly.LoadFrom(assemblyFilename) but this requires to guess the full
filenames for the assembly files, which maybe also tricky.

Is there a way to load dynamically an assembly given only the name (such
"System.Data.OracleClient") and major and minor version (such "1.0" or
"1.1") but not the build number?

Thanks in advance,

Carlos Quintero

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Angel Saenz-Badillos[MS] (VIP)
Carlos,

As far as I know you want to use the fully qualified assembly names,
1.0.5000.0 is the v1.1 library. v1.0 is 1.0.3300.0 and future service packs
will not change this. I am not sure about the PublicKeyToken, but I use
fully qualified assembly loads very often and have not had any trouble.

You mention that you want to load this dynamically, is there any reason for
this? The normal scenario for most users here is to rely on side by side
behavior and config files for what they want to tweak. Are you using a
reflection based program or are you trying to mix both 1.0 and 1.1 for some
reason?

Here are some common scenarios:

install RTM then install Everet
app compiled with rtm will run with rtm.
app compiled with everet will run with everet
asp.net app compiled on the fly will use Everett regardless of what it was
developed under.

Everet only installed
app compiled with rtm will run with Everet,

Rtm only installed
app compiled with Everet requires config file to run with RTM.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

"Carlos J. Quintero" <Click here to reveal e-mail address> wrote in
message news:uGb5YtHqCHA.2064@TK2MSFTNGP12...
[Original message clipped]

Reply to this message...
Vote that this is a GOOD answer...
 
 
    
Carlos J. Quintero
Hi,

[Original message clipped]

I will use fully qualified assembly names then.

> You mention that you want to load this dynamically, is there any reason
for
[Original message clipped]

Yes, there is one reason. The code is on an add-in (DLL) hosted on the IDE
that must load dynamically that .Net Data Provider. Although the add-in
could be coded in .Net code 1.0 and used both in VS.Net 2002 and VS.Net 2003
IDEs, it seems that it will be better to code separate versions for each IDE
sharing the same source code and using conditional compilation to load one
data provider or the other depending on the target IDE.

Thanks for all the info,

Carlos

Reply to this message...
Vote that this is a GOOD answer...
 
First volume of Multimobile Development nearly ready to go to press
A mention on Developing for the iPhone and Android: The pros and cons
 
 
System.Activator
System.Data.OracleClient.OracleConnection
System.EventArgs
System.IntPtr
System.Object
System.Reflection.Assembly
System.Windows.Forms.Form
System.Windows.Forms.MessageBox




Multimobile Development: Building Applications for any Smartphone
Ad
BootFX
Reliable and powerful .NET application framework.
iOS, Android and Windows Phone Development Training and Consultancy
Hosted by RackSRV Communications
 
Multimobile Development: Building Applications for any Smartphone
Copyright © AMX Software Ltd 2008-2010. Portions copyright © Matthew Baxter-Reynolds 2001-2010. All rights reserved.
Contact Us - Terms of Use - Privacy Policy - 4.0.30129.1734