StructureToPtr with dot net 4.5.1

GieltjEGieltjE Posts: 29 Bronze 2
edited October 17, 2014 7:59AM in SmartAssembly
The following error appears while running a dot net 4.5.1 assembly (the code is contained in a merged dll):
SmartAssembly.InformationException: SmartAssembly has encountered an invalid symbol:

[mscorlib]System.Runtime.InteropServices.Marshal::StructureToPtr System.Void(!!0, System.IntPtr, System.Boolean)

The most likely cause is that SmartAssembly has used a different version of a dependency from the version used by FYN Retail.exe.

If the details below are wrong, please use the MandatoryPath attribute in the .saproj file to ensure that the correct version of the dependency is found.

Assembly that should contain the missing symbol: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll

SmartAssembly has encountered an error while running your project.
Failed: SmartAssembly.InformationException: SmartAssembly has encountered an invalid symbol:

[mscorlib]System.Runtime.InteropServices.Marshal::StructureToPtr System.Void(!!0, System.IntPtr, System.Boolean)

The most likely cause is that SmartAssembly has used a different version of a dependency from the version used by FYN Retail.exe.

If the details below are wrong, please use the MandatoryPath attribute in the .saproj file to ensure that the correct version of the dependency is found.

Assembly that should contain the missing symbol: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll
Please run SmartAssembly in User-Interface mode for more information.

Setting MandatoryPath doesn't help, the following (tabcontrol extend) code is involved:
protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x1300 + 40)
            {
                Rect rc = (Rect)m.GetLParam(typeof(Rect));
                rc.Left -= 4;
                rc.Right += 4;
                rc.Top -= 1;
                rc.Bottom += 2;
                Marshal.StructureToPtr(rc, m.LParam, true);
            }
            base.WndProc(ref m);
        }

Setting the dll back to dotnet 4.5.0 is a temporary solution

Comments

  • Where did you set mandatorypath to?
  • GieltjEGieltjE Posts: 29 Bronze 2
    I've tried:
    1. C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5
    2. C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1

    If I set the mandatory path for the dll that get's merged it doesn't recognize the dll anymore so it has to be set on the main assembly.
  • Ok, thanks.

    This is basically an error in how we resolve the assembly- if you point the mandatorypath to:


    C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib

    That should now work as its the *real* assembly.
  • GieltjEGieltjE Posts: 29 Bronze 2
    Ok, thanks.

    This is basically an error in how we resolve the assembly- if you point the mandatorypath to:


    C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib

    That should now work as its the *real* assembly.

    Unfortunately that doesn't make a difference.
  • Can you open the mscorlib that you're pointing to in reflector and search for:

    Name: System.Runtime.InteropServices.Marshal

    If its not there- that at least explains why the error hasn't gone away and we'll have to work out how to point to the right mscorlib. If it is there, we need to work out how to get SA to find it.

    Reflector is available as a free trial download from our website.
  • GieltjEGieltjE Posts: 29 Bronze 2
    The function is there but it still won't obfuscate, something that I notice is that even though I point it to the right path it keeps mentioning "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll" instead of the mandatorypath I supply
  • Can you paste in your full smartassembly project file please- I can test here with a simulation based on your project. I can debug with full source code.
  • GieltjEGieltjE Posts: 29 Bronze 2
    I have made a test project with a single dll with a single class:
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    namespace ClassLibrary1
    {
    public class ExtendedTabControl : TabControl
    {
    protected override void WndProc(ref Message m)
    {
    if (m.Msg == 0x1300 + 40)
    {
    Rect rc = (Rect)m.GetLParam(typeof(Rect));
    rc.Left -= 4;
    rc.Right += 4;
    rc.Top -= 1;
    rc.Bottom += 2;
    Marshal.StructureToPtr(rc, m.LParam, true);
    }
    base.WndProc(ref m);
    }
    }

    internal struct Rect
    {
    public int Left, Top, Right, Bottom;
    }
    }

    With the corresponding saproject, I can supply the complete project if requested.
    <SmartAssemblyProject ProjectId="{99790642-89e1-4fc1-828e-b76c9e148872}" Version="2.0">
    <MainAssemblyFileName>.\WindowsFormsApplication1\bin\Release\WindowsFormsApplication1.exe</MainAssemblyFileName>
    <Configuration Name="Release">
    <Options>
    <ExceptionReporting Template="res:{SmartExceptions}.1033.dll" />
    <FeatureUsageReporting Template="res:SmartUsageWithUIConsentFirstRun1033.dll" />
    <StringsEncoding Compress="1" Encode="1" UseImprovedEncoding="1" />
    <StrongNameSigning />
    <OtherOptimizations SealClasses="1" />
    <Obfuscation ChangeMethodParent="1" FieldsNameMangling="3" NameMangling="3" />
    <OtherProtections SuppressIldasm="1" />
    <Debugging />
    </Options>
    <ApplicationName />
    <Destination DestinationFileName=".\WindowsFormsApplication1.exe" />
    <Assemblies>
    <Assembly AssemblyName="WindowsFormsApplication1, Culture=neutral, PublicKeyToken=null">
    <Merging>
    <ResourcesCompression />
    <MemberRefsProxy Proxy="1" />
    <Pruning Prune="1">
    <Exclusion />
    </Pruning>
    <Obfuscation Obfuscate="1">
    <Exclusion />
    </Obfuscation>
    <ControlFlow Obfuscate="1" ObfuscationLevel="4" />
    </Merging>
    <Embedding />
    </Assembly>
    <Assembly AssemblyName="System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Drawing, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Security, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="Accessibility, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Configuration, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Xml, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Deployment, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Core, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Runtime.Serialization.Formatters.Soap, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Data.SqlXml, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="System.Numerics, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <Merging />
    </Assembly>
    <Assembly AssemblyName="SmartAssembly.StringsEncoding, Culture=neutral, PublicKeyToken=7f465a1c156d4d57">
    <Merging>
    <Pruning>
    <Exclusion />
    </Pruning>
    <Obfuscation>
    <Exclusion />
    </Obfuscation>
    </Merging>
    </Assembly>
    <Assembly AssemblyName="SmartAssembly.Zip, Culture=neutral, PublicKeyToken=7f465a1c156d4d57">
    <Merging>
    <Pruning>
    <Exclusion />
    </Pruning>
    <Obfuscation>
    <Exclusion />
    </Obfuscation>
    </Merging>
    </Assembly>
    <Assembly AssemblyName="SmartAssembly.HouseOfCards, Culture=neutral, PublicKeyToken=7f465a1c156d4d57">
    <Merging>
    <Obfuscation>
    <Exclusion />
    </Obfuscation>
    </Merging>
    </Assembly>
    <Assembly AssemblyName="ClassLibrary1, Culture=neutral, PublicKeyToken=null">
    <Merging Merge="1">
    <Pruning Prune="1">
    <Exclusion />
    </Pruning>
    <Obfuscation Obfuscate="1">
    <Exclusion />
    </Obfuscation>
    <ControlFlow Obfuscate="1" ObfuscationLevel="4" />
    <MemberRefsProxy Proxy="1" />
    <ResourcesCompression />
    </Merging>
    <Embedding />
    </Assembly>
    </Assemblies>
    </Configuration>
    </SmartAssemblyProject>
  • Please change the line:

    <Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089">

    to:


    <Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089" mandatorypath="C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib ">
  • GieltjEGieltjE Posts: 29 Bronze 2
    Please change the line:

    <Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089">

    to:


    <Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089" mandatorypath="C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib ">

    Still the same error.
  • Righto- thanks. So we can narrow this down to assembly resolution which is always the most common problem with the product. Is your SA in debug mode? If not, below is the smartassemlby.exe.config file for setting it in debug mode. This will create smartassembly.log in current directory assuming the process has write permissions. The logfile will tell us exactly where SA is picking up its mscorlib from. If it doesn't match the correct version, we'll need to update the path; if it does, we're looking at some caching problem (SA does cache references sometimes).


    <?xml version="1.0"?>
    <configuration>
    <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=1.2.11.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a"/>
    </configSections>
    <startup>
    <supportedRuntime version="v2.0.50727" sku="client"/>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
    </startup>
    <log4net>


    <appender name="TraceLogger" type="log4net.Appender.FileAppender">
    <file value="SmartAssembly.log" />
    <appendToFile value="false" />
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date %-7level %logger: %message%newline%exception" />
    </layout>
    </appender>
    <root>
    <level value="TRACE"/>
    <appender-ref ref="TraceLogger" />
    </root>

    </log4net>
    </configuration>
  • Good news, finally. I have a solution. I apologise how long it took (its a two-part solution which partly explains the complexity).


    1.MandatoryPath="C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll"

    It seems necessary to point to the full physical location of the real mscorlib. This can be found using, for example, Reflector (open it up in, for example, C:\Windows\Microsoft.NET\Framework\v4.0.30319\) and look at the bottom left window- reflector tells you the full physical location)


    2. Smartassembly has a tendency to cache the settings file so one workaround I use is to copy the full install path:

    C:\Program Files\Red Gate\SmartAssembly 6\*.*

    and put it somewhere convenient, such as your desktop, the just run it form this new path- it re-reads all files.


    This has been tested extensively. If you still get problems, please let me know which step and send new smartassembly debug log.
  • GieltjEGieltjE Posts: 29 Bronze 2
    Good news, finally. I have a solution. I apologise how long it took (its a two-part solution which partly explains the complexity).

    1.MandatoryPath="C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll"

    It seems necessary to point to the full physical location of the real mscorlib. This can be found using, for example, Reflector (open it up in, for example, C:\Windows\Microsoft.NET\Framework\v4.0.30319\) and look at the bottom left window- reflector tells you the full physical location)

    2. Smartassembly has a tendency to cache the settings file so one workaround I use is to copy the full install path:

    C:\Program Files\Red Gate\SmartAssembly 6\*.*

    and put it somewhere convenient, such as your desktop, the just run it form this new path- it re-reads all files.

    This has been tested extensively. If you still get problems, please let me know which step and send new smartassembly debug log.

    This solution works until the application references mscorlib 2 and 4 if you reference an dotnet 2 dll. Unfortunately I can't get a debug for some reason.
  • I encountered the same problem. I upgraded from .NET 4.0 to .NET 4.5.2. Even with the MandatoryPath set, I can't get it to work. The reason is that some assembly is referring to .NET 2.0:
    2014-10-16 16:09:02,642 DEBUG   SmartAssembly.AssemblyReader: Resolved assembly {mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e} to C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5mscorlib.dll
    
    2014-10-16 16:09:08,401 DEBUG   SmartAssembly.AssemblyReader: Using {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} in preference to {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    
    &#91;mscorlib&#93;System.Runtime.InteropServices.Marshal::StructureToPtr System.Void(!!0, System.IntPtr, System.Boolean)
    
    The most likely cause is that SmartAssembly has used a different version of a dependency from the version used by EXAPTplus.Core.dll.  
    
    If the details below are wrong, please use the MandatoryPath attribute in the .saproj file to ensure that the correct version of the dependency is found.
    
    Assembly that should contain the missing symbol: C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5mscorlib.dll
    SmartAssembly.InformationException: SmartAssembly has encountered an invalid symbol:
    
    &#91;mscorlib&#93;System.Runtime.InteropServices.Marshal::StructureToPtr System.Void(!!0, System.IntPtr, System.Boolean)
    
    The most likely cause is that SmartAssembly has used a different version of a dependency from the version used by EXAPTplus.Core.dll.  
    
    If the details below are wrong, please use the MandatoryPath attribute in the .saproj file to ensure that the correct version of the dependency is found.
    
    Assembly that should contain the missing symbol: C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5mscorlib.dll
    

    In the .saproj:
    &lt;Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089" MandatoryPath="C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll" &gt;
        &lt;Merging /&gt;
    &lt;/Assembly&gt;
    
  • After lots of updating and testing, I finally figured out the problem: The .NET 2.0 assembly used a different key to sign the assembly, so the MandatoryPath doesn't work.

    With the following change I get it to compile:
    &lt;Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089" MandatoryPath="C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll" /&gt;
    &lt;Assembly AssemblyName="mscorlib, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" MandatoryPath="C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll" /&gt;
    

    However, I now get the following warning:
    One or more of the merged assemblies uses internal members of unmerged assemblies via InternalsVisibleToAttribute. Your assembly may not work.

    However, so far I have not noticed any problems.
Sign In or Register to comment.