none
CLR version for .Net Framework 4 beta 2

    Question

  • Hi,
    I've tried to run an IPC unmanaged/managed using bootstrap injection on the latest .Net 4 beta 2. The application was developped and run Ok on 3.5.
    I've imported the solution on VS2010 beta and changed the framework on the .net 4 beta 2 that I have previously installed. But the solution doesn't work. As I'm using CorBindToRuntimeEx I wonder if the malfunction comes from the CLR. Therefore, my question is: which version of the CLR shall I use in the first parameter of CorBindToRuntimeEx so that to run under 4 beta 2 (I currently use NULL as first parameter, which was supposed to charge the "latest available" on the system).
    Thanks 
    Wednesday, December 30, 2009 9:24 PM

Answers

  • You have mismatch of COM interfaces in CLRCreateInstance call - you ask for ICLRMetaHostPolicy, but cast it to ICLRMetaHost.

    This code will work:
    // Compile: cl.exe /Zi ClrHost.cpp mscoree.lib
    // Run: ClrHost.exe C:\MySample\MySample.dll
    #include <mscoree.h>
    #include <metahost.h>
    
    int wmain(int argc, wchar_t * argv[])
    {
        if (argc != 2) return -1;
        
        ICLRMetaHost * lpMetaHost = NULL;
        HRESULT hr;
        // reference: http://msdn.microsoft.com/en-us/library/dd233134(VS.100).aspx
        hr = CLRCreateInstance(
            CLSID_CLRMetaHost,
            IID_ICLRMetaHost,
            (LPVOID *)&lpMetaHost);
        if (FAILED(hr)) return 1;
        
        DWORD dwVersion = 0;
        DWORD dwImageVersion = 0;
        ICLRRuntimeInfo * lpRuntimeInfo = NULL;
        // Get a reference for the ICLRRuntimeInfo
        hr = lpMetaHost->GetRuntime(
            L"v4.0.21006", // 4.0 Beta2
            IID_ICLRRuntimeInfo,
            (LPVOID *)&lpRuntimeInfo);
        if (FAILED(hr)) return 2;
        
        ICLRRuntimeHost * lpRuntimeHost = NULL;
        // Load the CLR.
        hr = lpRuntimeInfo->GetInterface(
            CLSID_CLRRuntimeHost,
            IID_ICLRRuntimeHost,
            (LPVOID *)&lpRuntimeHost);
        if (FAILED(hr)) return 3;
        
        // Start the CLR by using the hosting version 4
        hr = lpRuntimeHost->Start();
        if (FAILED(hr)) return 4;
        
        DWORD dwRetCode = 0;
        // The function has to be: static int EntryPoint(string sz)
        hr = lpRuntimeHost->ExecuteInDefaultAppDomain(
            argv[1],    // Executable path
            L"MyNamespace.MyClass",
            L"Message",
            L"Hello World!",
            &dwRetCode);
        if (FAILED(hr)) return 5;
        
        return 0;
    }

    -Karel
    Thursday, December 31, 2009 6:09 PM
    Moderator

All replies

  •  

    Hi Opariti,

     

    From you description, the application works well if latest .NET Framework version is 3.5, when the underlying framework is upgraded to 4.0 beta 2, it doesn't work, right?

     

    As you said, if the caller specifies NULL for pwszVersion, the latest version of the runtime is loaded. I did a test to load CLR by passing NULL to the parameter pwszVersion of CorBindToRuntimeEx method, and the CLR is loaded successfully.

    ICLRRuntimeHost* pClrHost;

    HRESULT hr = CorBindToRuntimeEx(NULL, NULL, 0, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*) &pClrHost);

    pClrHost->Start();

     

    DWORD returnValue;

    hr = pClrHost->ExecuteInDefaultAppDomain(

    L"E:\\Projects\\TestProject\\bin\\Debug\\TestProject.exe",

    L"TestNameSpace.MyType",

    L"TestMethod",

    L"Hello",

    &returnValue);

     

    Is there any exception when you loading CLR in unmanaged code? or the CLR is loaded succeed, but your managed code gets runtime exception? Could you please provide more details about the exception, it will be helpful to find out the root cause.


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    Thursday, December 31, 2009 8:46 AM
  • Hi Eric,
    Yes, everything is fine as soon as I stay under 3.5. The reason I want to use 4 version is to have access to Memory Mapped Files methods in C#, which are not available in 3.5. 
    In the meantime I have digged into the MSDN documentation on .Net 4 beta 2, regarding the topic of managed code injection into an unmanaged code process. I see that things are more complicated, a lot of on-going tune-ups. What's certain is that CorBindToRuntimeEx is not valid any more (is "deprecated").
    Here is a complete code done using only the MSDN recommendations. The code builds OK but I have a LNK2019:

    #include "stdafx.h"
    #include <mscoree.h>
    #include <metahost.h>
    
    int _tmain()
    {
        ICLRMetaHost *lpMetaHost = NULL;
        HRESULT hr;
        // reference: http://msdn.microsoft.com/en-us/library/dd233134(VS.100).aspx
        hr = CLRCreateInstance(
            CLSID_CLRMetaHostPolicy,
            IID_ICLRMetaHostPolicy,
            (LPVOID*)&lpMetaHost);
        if (SUCCEEDED(hr))
        {
            DWORD dwVersion = 0;
            DWORD dwImageVersion = 0;
            ICLRRuntimeInfo* lpRuntimeInfo = NULL;
    
            // Get a reference for the ICLRRuntimeInfo
            hr = lpMetaHost->GetRuntime(
                L"v4.0.21006", // 4.0 Beta2
                IID_ICLRRuntimeInfo,
                (LPVOID*)&lpRuntimeInfo);
            if (SUCCEEDED(hr))
            {
                ICLRRuntimeHost* lpRuntimeHost = NULL;
                // Load the CLR.
                hr = lpRuntimeInfo->GetInterface(
                    CLSID_CLRRuntimeHost,
                    IID_ICLRRuntimeHost,
                    (LPVOID*) &lpRuntimeHost);
                if (SUCCEEDED(hr))
                {
                // Start the CLR by using the hosting version 4
                    hr = lpRuntimeHost->Start();
                    if (SUCCEEDED(hr))
                    {
                        DWORD dwRetCode = 0;
    
                        // To function properly, MyAssembly must
                        // have an entry point of type 
                        // static int EntryPoint(string sz)
                        hr = lpRuntimeHost->ExecuteInDefaultAppDomain(
                            L"C:\\MySample\\MySample.dll",
                            L"MyNamespace.MyClass",
                            L"Message",
                            L"Hello World!",
                            &dwRetCode);
                    }
                    lpRuntimeHost->Release();
                }
                lpRuntimeInfo->Release();
                return 0;
            }
            return 1;
        }
        return 1;
    }



    Please give it a try (copied from a VS2010 beta solution); sorry for the code paste quality, it just popped-up like that, though is nicely indented in VS.
    Thanks,
    Opariti

    PS: I found the reason of the link error; I forgot to add this:
    #pragma comment(lib,"MSCorEE.lib")

    But trying to run the example, with a simple C# static method example, I have a run time error at
    hr = lpMetaHost->GetRuntime
    "Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."
    So your clarification of using the right interfaces to load the CLR under 4 beta 2 - using my code above, would be of help for a lot of people.

    Thursday, December 31, 2009 11:36 AM
  • You have mismatch of COM interfaces in CLRCreateInstance call - you ask for ICLRMetaHostPolicy, but cast it to ICLRMetaHost.

    This code will work:
    // Compile: cl.exe /Zi ClrHost.cpp mscoree.lib
    // Run: ClrHost.exe C:\MySample\MySample.dll
    #include <mscoree.h>
    #include <metahost.h>
    
    int wmain(int argc, wchar_t * argv[])
    {
        if (argc != 2) return -1;
        
        ICLRMetaHost * lpMetaHost = NULL;
        HRESULT hr;
        // reference: http://msdn.microsoft.com/en-us/library/dd233134(VS.100).aspx
        hr = CLRCreateInstance(
            CLSID_CLRMetaHost,
            IID_ICLRMetaHost,
            (LPVOID *)&lpMetaHost);
        if (FAILED(hr)) return 1;
        
        DWORD dwVersion = 0;
        DWORD dwImageVersion = 0;
        ICLRRuntimeInfo * lpRuntimeInfo = NULL;
        // Get a reference for the ICLRRuntimeInfo
        hr = lpMetaHost->GetRuntime(
            L"v4.0.21006", // 4.0 Beta2
            IID_ICLRRuntimeInfo,
            (LPVOID *)&lpRuntimeInfo);
        if (FAILED(hr)) return 2;
        
        ICLRRuntimeHost * lpRuntimeHost = NULL;
        // Load the CLR.
        hr = lpRuntimeInfo->GetInterface(
            CLSID_CLRRuntimeHost,
            IID_ICLRRuntimeHost,
            (LPVOID *)&lpRuntimeHost);
        if (FAILED(hr)) return 3;
        
        // Start the CLR by using the hosting version 4
        hr = lpRuntimeHost->Start();
        if (FAILED(hr)) return 4;
        
        DWORD dwRetCode = 0;
        // The function has to be: static int EntryPoint(string sz)
        hr = lpRuntimeHost->ExecuteInDefaultAppDomain(
            argv[1],    // Executable path
            L"MyNamespace.MyClass",
            L"Message",
            L"Hello World!",
            &dwRetCode);
        if (FAILED(hr)) return 5;
        
        return 0;
    }

    -Karel
    Thursday, December 31, 2009 6:09 PM
    Moderator
  • Thanks Karel, that's it!
    Just two issues yet for MSFT:
    1 this documentation (which brought me to an error), needs to be rectfied: http://msdn.microsoft.com/en-us/library/dd233134(VS.100).aspx
    2 the GetRuntime needs to allow as first argument the default use of the last installed CLR version, like in the previous versions (the NULL). Maybe that can be done in the .net 4 stable version. Otherwise you can imagine the problems with our software installations to various clients ...


    Saturday, January 02, 2010 8:36 AM