Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Windows范围的beta UTF-8支持功能时在Winforms中调整RTF的错误_C#_Winforms_Utf 8_Richtextbox_Rtf - Fatal编程技术网

C# 使用Windows范围的beta UTF-8支持功能时在Winforms中调整RTF的错误

C# 使用Windows范围的beta UTF-8支持功能时在Winforms中调整RTF的错误,c#,winforms,utf-8,richtextbox,rtf,C#,Winforms,Utf 8,Richtextbox,Rtf,我想我在Windows或.NET中发现了一个bug,正在寻找解决方法 要重现此问题,请首先启用Windows功能“Beta:使用Unicode UTF-8获得全球语言支持” 您可能需要重新启动计算机 现在只需在Winforms/C#中创建两个RichTextBox组件,然后添加事件: private void richTextBox1_TextChanged(object sender, EventArgs e) { string s = richTextBox

我想我在Windows或.NET中发现了一个bug,正在寻找解决方法

要重现此问题,请首先启用Windows功能“Beta:使用Unicode UTF-8获得全球语言支持”

您可能需要重新启动计算机

现在只需在Winforms/C#中创建两个RichTextBox组件,然后添加事件:

    private void richTextBox1_TextChanged(object sender, EventArgs e)
    {
        string s = richTextBox1.Rtf;
        richTextBox2.Rtf = s;
    }
最后,运行该程序,只需在第一个RichTextBox中键入一些内容,当它试图写入
richTextBox2.Rtf
时,就会出现“文件格式无效”的消息。如果Windows功能“Beta:使用Unicode UTF-8实现全球语言支持”被禁用,它不会崩溃

我在考虑两种可能的解决方法:

1:以某种方式在C#应用程序中禁用整个“Beta:使用Unicode UTF-8实现全球语言支持”功能,并假装它从未启用过

2:在调整其他RichTextBox的RTF之前,以某种方式编辑RTF字符串,以符合新RTF应该具有的任何未知要求。考虑到第一个RichTextBox应该具有完全相同的RTF,这似乎违反直觉,但无论如何



Microsoft开放了WinForms库的源代码,因此您可以自己深入了解源代码:

流线输入法位于以下第3140行:

它看起来确实像一个bug,而且由于它是BETA版,最好的做法是在Microsoft登录

如果用库中的代码替换RichTextBox控件类,您将能够看到错误发生在以下哪一行:

System.Windows.Forms.RichTextBox.StreamIn(流数据,Int32标志)

更新:

这实际上是一个已知的问题,

已向Microsoft报告:

MSFT的Kyle Wang已经将其缩小为操作系统问题:

PC1(OS Build.437可以重现该问题):

环境:

测试:

PC2(OS Build.348无法重现该问题):

环境:

测试:


在MSDN中,当尝试设置RTF时,它将检查起始字符串是否等于“{\RTF”,但当启用此功能时,格式将以“{\urtf”开头,这将导致microsoft显式抛出异常

MSDN参考:

string str = Encoding.Default.GetString(bytes);

if (!SZ_RTF_TAG.Equals(str)) // SZ_RTF_TAG ="{\\rtf";

    throw new ArgumentException(SR.GetString(SR.InvalidFileFormat));
要避免这种情况,您需要将.net framework升级到4.7或禁用测试版功能。此问题将出现在Windows 1803和1809版本中。 类似的线索如下


什么崩溃?是从第一个文本框读取还是写入第二个文本框?什么是完整堆栈跟踪?@canton7:写入第二个。编辑问题以澄清并添加异常文本,如果这就是您所说的“完整堆栈跟踪”。好吧,这是beta版。RTF是不可靠的,是最后剩下的文本格式之一,它的核心是基于代码页的,不能用Unicode编码。你可能会在本世纪完成的RichTextBox版本中取得成功,并在写字板小程序中使用。我见过许多与beta UTF-8语言环境设置相关的错误,所以这并不令人惊讶尝试过Han的建议吗?我复制您的问题的唯一方法是将.Net版本<4.7.Net 4.7及以上默认设置为RichEdit50控件,而不是先前版本中使用的RichEdit20。嗯,我假设您指的是扩展RichTextBox类并重写
StreamIn
方法。问题是我无法获取
RichTextBoxConstants
NativeMethods
GetErrorValue64
HandleRef
等。要解决的问题还有很多编译错误。检查我的更新,看起来它已经出现在Microsoft的雷达上,并且已经缩小了范围。看起来好像重新引入了回归。您好,谢谢您的支持对这个问题进行研究和故障排除。我的理解是,即使使用.Net 4.7,如果操作系统版本是1803或1809,它也会导致ArgumentException?你是说.Net 4.7将在1803和1809上工作吗?顺便说一句,我已经帮你解决了Microsoft Connect案例,他们在你身上关闭它有点狡猾。有趣。现在,我将使用Hans的RichEdit50解决方案,因为我现在想继续使用.NET 3.5,而.NET 4.7可能无论如何都会使用RichEdit50。@DanW
我现在想继续使用.NET 3.5
该运行时在几年前就不受支持了。最早支持的版本是.NET 4.5.2。如果您想使用不受支持的运行时,请不要启用测试版功能而且在运行时不会被修复是的,虽然我是前15名赏金猎人中的一员,但这是你应得的!@PanagiotisKanavos:我不启用或关心这个beta UTF8功能;但是我的一些用户启用了,当它崩溃时,他们会感到困惑。这就是问题。NET3.5适用于更广泛的PC,因此我坚持使用这个功能的理由。
 private void StreamIn(string str, int flags)
    {
        if (str.Length == 0)
        {
            // Destroy the selection if callers was setting
            // selection text
            //
            if ((RichTextBoxConstants.SFF_SELECTION & flags) != 0)
            {
                SendMessage(Interop.WindowMessages.WM_CLEAR, 0, 0);
                ProtectedError = false;
                return;
            }
            // WM_SETTEXT is allowed even if we have protected text
            //
            SendMessage(Interop.WindowMessages.WM_SETTEXT, 0, "");
            return;
        }

        // Rather than work only some of the time with null characters,
        // we're going to be consistent and never work with them.
        int nullTerminatedLength = str.IndexOf((char)0);
        if (nullTerminatedLength != -1)
        {
            str = str.Substring(0, nullTerminatedLength);
        }

        // get the string into a byte array
        byte[] encodedBytes;
        if ((flags & RichTextBoxConstants.SF_UNICODE) != 0)
        {
            encodedBytes = Encoding.Unicode.GetBytes(str);
        }
        else
        {
            encodedBytes = Encoding.Default.GetBytes(str);
        }
        editStream = new MemoryStream(encodedBytes.Length);
        editStream.Write(encodedBytes, 0, encodedBytes.Length);
        editStream.Position = 0;
        StreamIn(editStream, flags);
    }

    private void StreamIn(Stream data, int flags)
    {
        // clear out the selection only if we are replacing all the text
        //
        if ((flags & RichTextBoxConstants.SFF_SELECTION) == 0)
        {
            NativeMethods.CHARRANGE cr = new NativeMethods.CHARRANGE();
            UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_EXSETSEL, 0, cr);
        }

        try
        {
            editStream = data;
            Debug.Assert(data != null, "StreamIn passed a null stream");

            // If SF_RTF is requested then check for the RTF tag at the start
            // of the file.  We don't load if the tag is not there
            // 
            if ((flags & RichTextBoxConstants.SF_RTF) != 0)
            {
                long streamStart = editStream.Position;
                byte[] bytes = new byte[SZ_RTF_TAG.Length];
                editStream.Read(bytes, (int)streamStart, SZ_RTF_TAG.Length);
                string str = Encoding.Default.GetString(bytes);
                if (!SZ_RTF_TAG.Equals(str))
                {
                    throw new ArgumentException(SR.InvalidFileFormat);
                }

                // put us back at the start of the file
                editStream.Position = streamStart;
            }

            int cookieVal = 0;
            // set up structure to do stream operation
            NativeMethods.EDITSTREAM es = new NativeMethods.EDITSTREAM();
            if ((flags & RichTextBoxConstants.SF_UNICODE) != 0)
            {
                cookieVal = INPUT | UNICODE;
            }
            else
            {
                cookieVal = INPUT | ANSI;
            }
            if ((flags & RichTextBoxConstants.SF_RTF) != 0)
            {
                cookieVal |= RTF;
            }
            else
            {
                cookieVal |= TEXTLF;
            }
            es.dwCookie = (IntPtr)cookieVal;
            es.pfnCallback = new NativeMethods.EditStreamCallback(EditStreamProc);

            // gives us TextBox compatible behavior, programatic text change shouldn't
            // be limited...
            //
            SendMessage(Interop.EditMessages.EM_EXLIMITTEXT, 0, int.MaxValue);



            // go get the text for the control
            // Needed for 64-bit
            if (IntPtr.Size == 8)
            {
                NativeMethods.EDITSTREAM64 es64 = ConvertToEDITSTREAM64(es);
                UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMIN, flags, es64);

                //Assign back dwError value
                es.dwError = GetErrorValue64(es64);
            }
            else
            {
                UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), Interop.EditMessages.EM_STREAMIN, flags, es);
            }

            UpdateMaxLength();

            // If we failed to load because of protected
            // text then return protect event was fired so no
            // exception is required for the the error
            if (GetProtectedError())
            {
                return;
            }

            if (es.dwError != 0)
            {
                throw new InvalidOperationException(SR.LoadTextError);
            }

            // set the modify tag on the control
            SendMessage(Interop.EditMessages.EM_SETMODIFY, -1, 0);

            // EM_GETLINECOUNT will cause the RichTextBoxConstants to recalculate its line indexes
            SendMessage(Interop.EditMessages.EM_GETLINECOUNT, 0, 0);


        }
        finally
        {
            // release any storage space held.
            editStream = null;
        }
    }
string str = Encoding.Default.GetString(bytes);

if (!SZ_RTF_TAG.Equals(str)) // SZ_RTF_TAG ="{\\rtf";

    throw new ArgumentException(SR.GetString(SR.InvalidFileFormat));