سؤال

لماذا البرمجية التالية في بعض الأحيان يسبب استثناء مع محتويات "CLIPBRD_E_CANT_OPEN":

Clipboard.SetText(str);

هذا يحدث عادة في المرة الأولى الحافظة المستخدمة في التطبيق و ليس بعد ذلك.

هل كانت مفيدة؟

المحلول

في الواقع, أعتقد أن هذا هو خطأ Win32 API.

تعيين البيانات في الحافظة ، عليك أن فتحه أولا.فقط عملية واحدة يمكن أن يكون الحافظة مفتوحة في وقت واحد.لذلك ، عند التحقق ، إذا عملية أخرى قد الحافظة فتح لأي سبب من الأسباب, محاولة فتحه سوف تفشل.

انها مجرد أن ذلك يحدث "الخدمات الطرفية" بتتبع الحافظة ، و على الإصدارات القديمة من ويندوز (قبل Vista) ، لديك لفتح الحافظة إلى رؤية ما في الداخل...الذي ينتهي حظر لك.الحل الوحيد هو الانتظار حتى "الخدمات الطرفية" يغلق الحافظة ثم حاول مرة أخرى.

من المهم أن ندرك أن هذه ليست محددة إلى "الخدمات الطرفية" ، على الرغم من:فإنه يمكن أن يحدث مع أي شيء.العمل مع الحافظة في Win32 عملاق حالة السباق.ولكن منذ حسب التصميم المفترض أن تحشر مع الحافظة في الاستجابة إلى إدخال المستخدم ، وهذا عادة لا تمثل مشكلة.

نصائح أخرى

وهذا هو سبب الخلل/ميزة في "الخدمات الطرفية" الحافظة (و ممكن أشياء أخرى)،.صافي تنفيذ الحافظة.تأخير في فتح الحافظة أسباب الخطأ الذي يمر عادة في غضون بضع ميلي ثانية.

الحل هو أن تحاول مرات متعددة في حلقة النوم في بين.

for (int i = 0; i < 10; i++)
{
    try
    {
        Clipboard.SetText(str);
        return;
    }
    catch { }
    System.Threading.Thread.Sleep(10);
} 

أعرف أن هذا السؤال هو قديم ولكن المشكلة لا تزال موجودة.كما ذكر من قبل, يحدث هذا الاستثناء عند الحافظة النظام يتم حظر من قبل عملية أخرى.للأسف, العديد من أدوات القص, برامج الصور و نسخ الملفات من الأدوات التي يمكن أن تمنع الحافظة ويندوز.لذلك سوف تحصل على استثناء في كل مرة حاولت استخدام Clipboard.SetText(str) عند هذه الأداة هو مثبتا على الكمبيوتر الخاص بك.

الحل:

أبدا استخدام

Clipboard.SetText(str);

استخدم بدلا من ذلك

Clipboard.SetDataObject(str);

في الواقع يمكن أن يكون هناك مسألة أخرى في متناول اليد.إطار الدعوة (سواء WPF و winform النكهات) إلى شيء من هذا القبيل (رمز من عاكس):

private static void SetDataInternal(string format, object data)
{
    bool flag;
    if (IsDataFormatAutoConvert(format))
    {
        flag = true;
    }
    else
    {
        flag = false;
    }
    IDataObject obj2 = new DataObject();
    obj2.SetData(format, data, flag);
    SetDataObject(obj2, true);
}

علما بأن SetDataObject يسمى دائما مع صحيحا في هذه الحالة.

داخليا أن يطلق اثنين استدعاءات win32 api واحدة إلى مجموعة بيانات واحدة لطرد من التطبيق الخاص بك حتى انها متوفرة بعد التطبيق يغلق.

لقد رأيت العديد من التطبيقات (كروم المساعد و مدير التحميل) أن الاستماع إلى الحافظة الحدث.في أقرب وقت المكالمة الأولى يضرب التطبيق سيتم فتح الحافظة للنظر في البيانات ، والثانية دعوة لطرد سوف تفشل.

لم أجد حلا جيدا إلا أن أكتب بلدي الطبقة الحافظة التي تستخدم مباشرة win32 API أو الاتصال setDataObject مباشرة مع كاذبة حفظ البيانات بعد التطبيق يغلق.

لقد تم حل هذه المشكلة عن بلدي التطبيق باستخدام الأصلي Win32 وظائف:OpenClipboard(), CloseClipboard() و SetClipboardData().

تحت فئة مجمع صنعت.يمكن لأي شخص من فضلك استعراض ذلك ، أقول إذا كان صحيحا أم لا.وخصوصا عندما التعليمات البرمجية المدارة تشغيل x64 التطبيق (يمكنني استخدام أي وحدة المعالجة المركزية في المشروع خيارات). ماذا يحدث عند ارتباط إلى x86 من المكتبات x64 التطبيق ؟

شكرا لك!

هنا كود:

public static class ClipboardNative
{
    [DllImport("user32.dll")]
    private static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("user32.dll")]
    private static extern bool CloseClipboard();

    [DllImport("user32.dll")]
    private static extern bool SetClipboardData(uint uFormat, IntPtr data);

    private const uint CF_UNICODETEXT = 13;

    public static bool CopyTextToClipboard(string text)
    {
        if (!OpenClipboard(IntPtr.Zero)){
            return false;
        }

        var global = Marshal.StringToHGlobalUni(text);

        SetClipboardData(CF_UNICODETEXT, global);
        CloseClipboard();

        //-------------------------------------------
        // Not sure, but it looks like we do not need 
        // to free HGLOBAL because Clipboard is now 
        // responsible for the copied data. (?)
        //
        // Otherwise the second call will crash
        // the app with a Win32 exception 
        // inside OpenClipboard() function
        //-------------------------------------------
        // Marshal.FreeHGlobal(global);

        return true;
    }
}

هذا يحدث لي في تطبيق WPF.حصلت OpenClipboard فشل (استثناء من HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN)).

يمكنني استخدام

ApplicationCommands.Copy.Execute(null, myDataGrid);

الحل هو مسح الحافظة الأولى

Clipboard.Clear();
ApplicationCommands.Copy.Execute(null, myDataGrid);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top