You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用GetTextAsync时触发Invalid FORMATETC structure异常排查

问题分析与解决方案

核心异常原因:剪贴板API混用 + 线程违规

你遇到的Invalid FORMATETC structure occurred异常,本质是同时混用了UWP剪贴板API(Windows.ApplicationModel.DataTransfer.Clipboard)和WinForms剪贴板API(System.Windows.Forms.Clipboard),再加上异步事件回调里直接操作剪贴板未遵循UI线程调用要求,导致剪贴板格式冲突。

分步修复方案

1. 统一剪贴板操作API

WPF程序直接使用原生的System.Windows.Clipboard,彻底摒弃UWP或WinForms的剪贴板类,避免跨框架格式冲突。

2. 修正异步线程问题

剪贴板操作必须在UI线程执行,异步回调里通过Dispatcher切换到UI线程;同时替换阻塞UI的Thread.Sleep(500)为非阻塞的await Task.Delay(500),防止界面卡死。

3. 资源文件读取优化(两种方式可选)

  • StringReader方式:只要资源是正确嵌入的文本格式,原写法本身没问题,无需替换;
  • StreamReader方式:若要改用流读取,通过资源管理器获取嵌入资源的流即可。

修复后的完整代码

public partial class MainWindow : System.Windows.Window
{
    string line;
    string currentClipboardContent;
    string expectedClipboardContent;
    string vocabularygerman = Properties.Resources.vocabularygerman;
    string vocabularyfrench = Properties.Resources.vocabularyfrench;
    int lineNumber;

    public MainWindow()
    {
        InitializeComponent();
        // 采用WPF原生剪贴板监听事件,更贴合框架线程模型
        System.Windows.Clipboard.AddPasteHandler(this, ClipboardChangedHandler);
    }

    private async void ClipboardChangedHandler(object sender, DataObjectPastingEventArgs e)
    {
        if (e.DataObject.GetDataPresent(DataFormats.Text))
        {
            currentClipboardContent = e.DataObject.GetData(DataFormats.Text) as string;
            if (expectedClipboardContent != currentClipboardContent)
            {
                await Task.Delay(500); // 非阻塞等待,避免重复触发

                // StringReader读取资源文本(原逻辑保留,修正剪贴板操作)
                using (var reader = new StringReader(vocabularygerman))
                {
                    lineNumber = 0;
                    while ((line = reader.ReadLine()) != null)
                    {
                        lineNumber++;
                        if (line.Contains(currentClipboardContent))
                        {
                            // 切换到UI线程设置剪贴板,替换为目标行文本
                            await Dispatcher.InvokeAsync(() => 
                            {
                                System.Windows.Clipboard.SetText(line);
                            });
                            break;
                        }
                    }
                }

                // 更新预期内容,防止循环触发事件
                expectedClipboardContent = System.Windows.Clipboard.GetText();
            }
        }
    }

    // 若需改用StreamReader读取嵌入资源,可使用此方法
    private void ReadResourceViaStreamReader()
    {
        using (var stream = Properties.Resources.ResourceManager.GetStream("vocabularygerman"))
        {
            if (stream != null)
            {
                using (var reader = new StreamReader(stream))
                {
                    string fullContent = reader.ReadToEnd();
                    // 按需求处理文本内容
                }
            }
        }
    }
}

额外注意事项

  • 原代码中SetDataObject(lineNumber)是设置行号,不符合你“替换为单词所在行”的需求,已修正为SetText(line);
  • 确保资源文件vocabularygerman.txt的生成操作设置为“嵌入的资源”,否则无法通过Properties.Resources正常访问;
  • expectedClipboardContent的判断逻辑必须保留,避免设置剪贴板后再次触发事件形成循环。

内容的提问来源于stack exchange,提问作者Biswind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:05:22