Beckhoff / TF6000_ADS_DOTNET_V5_Samples

Sample code for the Version 6.X series of the TwinCAT ADS .NET Packages
https://infosys.beckhoff.com/content/1033/tc3_ads.net/9407515403.html?id=6770980177009971601
BSD Zero Clause License
38 stars 15 forks source link

StringMarshaler throws null reference exception #60

Open maxxie85 opened 3 hours ago

maxxie85 commented 3 hours ago

I have a very strange exception happening on a client machine where I get a null reference exception. The weird part is that the same program does run an similar machines but somehow this one is different.

XAE is 3.1.4024.62 (was .56) The PLC is a CX9020 running on 3.1.4024.35

ADS library versions tried 6.1.290.0 and 6.1.298.0

Stack trace

System.NullReferenceException: Object reference not set to an instance of an object.
   at TwinCAT.TypeSystem.StringMarshaler..ctor(Encoding encoding, StringConvertMode mode)
   at TwinCAT.TypeSystem.PrimitiveTypeMarshaler..ctor(Encoding encoding)
   at TwinCAT.TypeSystem.PrimitiveTypeMarshaler.get_Default()
   at TwinCAT.TypeSystem.SymbolicAnyTypeMarshaler..ctor(Encoding defaultValueEncoding)
   at TwinCAT.TypeSystem.InstanceValueMarshaler..ctor(Encoding defaultValueEncoding)
   at TwinCAT.ValueAccess.ValueFactory..ctor(ValueCreationModes mode)
   at TwinCAT.Ads.TypeSystem.SymbolLoaderFactory.createValueAccessor(IAdsConnection connection, SymbolLoaderSettings settings)
   at TwinCAT.Ads.TypeSystem.AdsSymbolServer.OnCreateLoader()
   at TwinCAT.Ads.TypeSystem.AdsSymbolServer.createLoader()
   at TwinCAT.Ads.TypeSystem.AdsSymbolServer.GetSymbolsAsync(CancellationToken cancel)
   at MPTCore.TwinCAT.Common.Services.CommunicationServiceBase.InitializeAsync(IAdsSession adsSession, CancellationToken cancellationToken, TimeSpan period) in C:\Source\GIT\MPTCore.TwinCAT\src\MPTCore.TwinCAT\Common\Services\CommunicationServiceBase.cs:line 98

It was a challenge to get the remote debugger attached and breaking at the right moment. I think it's because the Encoding is null, but not to sure. I can't see any other details than in the picture below.

afbeelding

RalfHeitmann commented 3 hours ago

Hi maxxie85, great analysis. I think the ADS Default Encoding is not determined properly on that machine. Our Code:

        /// <summary>
        /// Gets the default encoding.
        /// </summary>
        /// <remarks>
        /// Since TwinCAT 4026, the UTF8 Encoding will be the default
        /// Historically in older TwinCAT installations, the Default encoding is ANSI with Windows active (e.g. CodePage 1252 (West-European))
        /// Because the AdsClient doesn't know what the actual communication partner is (4026 or older) we try to default to ANSI.
        /// The AdsClient holds its own actual encoding in SymbolNameEncoding/SymbolNameMarshaler with the (ADS) read settings from SymbolUploadInfo.
        /// </remarks>
        /// <value>The default encoding.</value>
        public static Encoding DefaultEncoding
        {
            get
            {
                // This returns the Windows Active Code Page on .NET Full Framework e.g. (ANSI 1252)
                // and UTF8 on .NET Core Systems!
                Encoding? ret = Encoding.Default;

#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER
                try
                {
                    // Trying to register the ANSI CodePage for .NET CORE
                    // see https://stackoverflow.com/questions/75803153/c-sharp-method-encoding-getencoding-wont-find-the-windows-1252-encoding
                    EncodingProvider provider = CodePagesEncodingProvider.Instance;
                    Encoding.RegisterProvider(provider);
                    // Because on .NET Core the Default Encoding is UTF8, which is not what we want for historical reasons.
                    ret = CodePagesEncodingProvider.Instance.GetEncoding(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage);
                }
                catch (Exception)
                {
                    // Because have registered the Provider this shouldn't happen.

                    // see https://stackoverflow.com/questions/75803153/c-sharp-method-encoding-getencoding-wont-find-the-windows-1252-encoding
                    // UTF8 is the most appropriate in this case
                    //ret = Encoding.ASCII;
                    // As Fallback UTF8 is always better than ASCII because it supports more scenarios.
                    ret = Encoding.UTF8;
                }
#endif
                return ret;
            }
        }

This seem to return null in the case that the ANSICodePage is not installed. Why this is the case with your client machine - I don't now, but our implementation above isn't fully correct. Probably you could find out, which Encoding/Codepage and operating system the client is running.

I will change the returned encoding to UTF8 for that case ...

maxxie85 commented 2 hours ago

Hi Ralf,

Thanks for the quick response. I have to double check the code page that's active on the machine. I have to make a new appointment with the client to gain remote access.

Another thing that might give some insight, I have reverted the application to a known working version. This version is using ADS 6.1.203. With the code snipped you shared, does it make sense it isn't working with ADS 6.1.290?

RalfHeitmann commented 9 minutes ago

The problem should be introduced with Version 2.1.286. Versions before that should work.