سؤال

لدي بعض رمز IO يقرأ دفقا ضمن جرب..شوتات. انها تحمل IOException والمكالمات system.runtime.interopservices.marshal.gethrforexception ()داخل الصيد، في محاولة لاتخاذ إجراءات مختلفة على أساس HRESULT. شيء من هذا القبيل:

try 
{
    stream.Read(...);
}
catch (IOException ioexc1)
{
   uint hr = (uint) Marshal.GetHRForException(ioexc1);
   if (hr == ...) 
      do_one_thing();
   else
      do_another();
}

يتم توقيع الجمعية مع allowpartiallytrustedcallersattribute..

ولكن تشغيل هذا الرمز داخل ASP.NET مع Trust = "متوسط"، أحصل على هذا الاستثناء:

Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

أسئلة زوجين:

  1. أعتقد أن الاستثناء يحدث لأن GetHRForeforexception يدعو إلى رمز غير مدار، وهو غير مسموح به في الثقة المتوسطة. صيح؟
  2. يتم إلقاء هذا الاستثناء، وليس في وقت تنفيذ gethroreforexception، ولكن في الوقت الذي تكون فيه الطريقة هي jit'ed - صحيح؟ (يظهر StackTrace طريقتي، لكنني مؤكد أنني 99٪ لم يحدث استثناء IO)
  3. إذا كان الأمر كذلك، فهل هناك طريقة بالنسبة لي لتغيير السلوك في بيئة ثقة جزئية، بحيث لا أسمي GetHRForexception (رمز غير مدار) حيث لا يسمح به؟ بمعنى آخر، كيف يمكنني السماح ل JIT بالنجاح في تجميع الوقت، مع تقييم أيضا في وقت التشغيل ما إذا كان يجب أن يسمي الكود GetHRForexception ()؟ شيء من هذا القبيل:

catch (IOException ioexc1)
{
   if (!OkToCallUnmanaged())
       throw ioexc1; 

   uint hr = (uint) Marshal.GetHRForException(ioexc1);
   if (hr == ...) 
      do_one_thing();
   else
      do_another();
}

أعتقد أن هناك آلية وقت التشغيل لاختبار ما إذا كانت الأذونات متوفرة، لكن لم تتمكن من العثور عليها.


تعديل: يكون هذا المادة بلوق الاجابة؟ يقول Shawnfa of Microsoft أنه لا يمكنك القيام بمحاولة ... Catch (SecurityException) حول طريقة محمية بواسطة LinkDemand. إذا كانت Methera () المكالمات Methodb ()، ويتم تمييز MethodB () مع LinkDemand من أجل الثقة الكاملة، ثم يتم فحص LinkDemand مع منهجي هو Jit'ed. لذلك لتجنب SecurityException، أحتاج إلى استخراج Marshal.gethrforexception في طريقة منفصلة. هل هذا صحيح؟

يتم تطبيقه على التعليمات البرمجية الخاصة بي، قد يكون الجهاز () هو الرمز الذي يستدعي القراءة، ثم في المحاولات في الصيد للاتصال GetHRForexception (). gethrforexception هو الأسلوب (). يتم تقييم LinkDemand عند وجود منهج () Jit'd. (فشل هذا LinkDemand في سيناريو ASP.NET متوسطة المستوى). إذا قمت بنقل GetHRForexception إلى طريقة جديدة، فإن Methodc ()، والاتصال الموثوقة المشروطي () فقط بعد إذن ضروري. تنجح من الناحية النظرية، من الناحية النظرية، يجب أن أكون قادرا على تجنب SecurityException في وقت JIT، لأن المنهجية () ستكون Jit'd فقط بعد إذن.Demain () ينجح.

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

المحلول

الطريقة المطلوبة هي securitypermission.sunrestrised (). وبعد إرجاع حقيقي أو خطأ يشير إلى ما إذا كان الإذن مسموح به أم لا. لم يحدث ذلك الطلب إذن، كما يفعل securitypermission.demand (). وبعد أستخدم iSunresticted مع SecurityPermissionFlag.unagedCode لمعرفة ما إذا كان الجمعية مسموحا باسم Code غير المدارة، ثم استدعاء التعليمات البرمجية غير المدارة فقط إذا سمح.

هناك تطور إضافي واحد. التحويل البرمجي JIT، عند تجميع طريقة، يتحقق من LinkDemands LinkDemands على أي طريقة تسمى طريقة تجميعها. marshal.gethrforexception () ملحوظ مع LinkDemand. وبالتالي، فإن طريقتي التي تستدعي marshal.gethrforexception () ستقوم بإلقاء أمن غير قابل للتنفيذ في وقت تجميع جيت، عند تشغيله في بيئة محظورة، مثل ASP.NET مع الثقة المتوسطة. لذلك، يجب ألا نكتشف الطريقة التي تستدعي marshal.gethrforexception () في هذه الحالة، مما يعني أنني بحاجة إلى اختراق marshal.gethrforexception () في طريقة منفصلة في التعليمات البرمجية التي يطلق عليها (وبالتالي الجوف) فقط عند تشغيله غير مقيد.

إليك بعض الرمز المثال:

internal void DoTheThing()
{
    try
    {
        DoSomethingThatMayCauseAnException();
    }
    catch (System.IO.IOException ioexc1)
    {
        // Check if we can call GetHRForException, 
        // which makes unmanaged code calls.
        var p = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
        if (p.IsUnrestricted())
        {
            uint hresult = _HRForException(ioexc1);
            if (hresult == 0x80070021)  // ERROR_LOCK_VIOLATION
                TakeActionOnLockViolation();  // maybe notify the user
            else
                throw new Exception("Cannot handle", ioexc1);
        }
        else
        {
            // The permission is restricted. Therefore, we cannot call
            // GetHRForException, and cannot do the subtle handling of
            // ERROR_LOCK_VIOLATION.  Just bail.
            throw new Exception("Cannot handle", ioexc1);
        }
    }
}

// This method must remain separate, and must not be marked with a LinkDemand for
// UnmanagedCode.
//
// Marshal.GetHRForException() is needed to do special exception handling for
// the read.  But, that method requires UnmanagedCode permissions, and is marked
// with LinkDemand for UnmanagedCode.  In an ASP.NET medium trust environment,
// where UnmanagedCode is restricted, will generate a SecurityException at the
// time of JIT of the method that calls a method that is marked with LinkDemand
// for UnmanagedCode. The SecurityException, if it is restricted, will occur
// when this method is JITed.
//
// The Marshal.GetHRForException() is factored out of DoTheThing in order to
// avoid the SecurityException at JIT compile time. Because _HRForException is
// called only when the UnmanagedCode is allowed, .NET never
// JIT-compiles this method when UnmanagedCode is disallowed, and thus never
// generates the JIT-compile time exception.
//
private static uint _HRForException(System.Exception ex1)
{
    return unchecked((uint)System.Runtime.InteropServices.Marshal.GetHRForException(ex1));
}

نصائح أخرى

  1. نعم - لن تسمح الثقة المتوسطة بالمكالمات إلى رمز غير مدار. مستوى الثقة الوحيد الذي يسمح له ثقة كاملة.
  2. هذا يعتمد. يمكن أن تتم مطالب CAS في وقت التشغيل، لكن بيئة الاستضافة يمكن أن تذهب أيضا إلى وجول وتبحث عن الأشياء التي لا تستطيع القيام بها.
  3. يمكنك اختبار لمعرفة ما إذا كان يمكنك إجراء مكالمة إلى التعليمات البرمجية غير المدارة باستخدام الطلب CAS مع مثيل securitypermission..

الرمز لجعل الطلب CAS يشبه هذا

SecurityPermission permission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
try
{
  permission.Demand();
  // Got it, away we go
}
catch (SecurityException)
{
  // Could not get permission to make unmanaged code calls
  // React accordingly.
}

هل system.runtime.interopservices.marshal.gethrforexception () احصل على أي شيء لا يمكنك الحصول عليه عن طريق التحقق من نوع الاستثناء؟ يبدو أنه يستخدم رسم خرائط ثابتة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top