Следующий код существует в LogEntry.cs в блоке приложения ведения журналов в Enterprise Library:
private bool UnmanagedCodePermissionAvailable
{
get
{
if (!unmanagedCodePermissionAvailableInitialized)
{
// check whether the unmanaged code permission is available to avoid three potential stack walks
bool internalUnmanagedCodePermissionAvailable = false;
SecurityPermission unmanagedCodePermission =
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
// avoid a stack walk by checking for the permission on the current assembly. this is safe because there are no
// stack walk modifiers before the call.
if (SecurityManager.IsGranted(unmanagedCodePermission))
{
try
{
unmanagedCodePermission.Demand();
internalUnmanagedCodePermissionAvailable = true;
}
catch (SecurityException)
{ }
}
this.UnmanagedCodePermissionAvailable =
internalUnmanagedCodePermissionAvailable;
}
return this.unmanagedCodePermissionAvailable;
}
set
{
this.unmanagedCodePermissionAvailable = value;
unmanagedCodePermissionAvailableInitialized = true;
}
}
Функция вызывается перед выполнением любого из нескольких вызовов P / Invoke для получения различной информации, чтобы помочь заполнитьструктура LogEntry.Если «UnmanagedCodePermission» недоступен, то соответствующему свойству LogEntry присваивается строка, обозначающая это («XXX не доступен»).
Например, LogEntry хочет получить идентификатор потока Win32 и используетФункция Win32, GetCurrentThreadId, вызывается P / Invoke для ее получения.Перед вызовом GetCurrentThreadId он проверяет, доступно ли «разрешение не измененного кода».Если это так, он делает вызов, если нет, то нет.Примерно так:
private void InitializeWin32ThreadId()
{
if (this.UnmanagedCodePermissionAvailable)
{
try
{
this.Win32ThreadId = LogEntryContext.GetCurrentThreadId();
}
catch (Exception e)
{
this.Win32ThreadId = string.Format(
CultureInfo.CurrentCulture,
Properties.Resources.IntrinsicPropertyError,
e.Message);
}
}
else
{
this.Win32ThreadId = string.Format(CultureInfo.CurrentCulture,
Properties.Resources.IntrinsicPropertyError,
Properties.Resources.
LogEntryIntrinsicPropertyNoUnmanagedCodePermissionError);
}
}
Из того, что я понимаю, что, по общему признанию, не так много, выполнение вызовов неуправляемого кода (например, P / Invoke) не всегда возможно из-за безопасности / разрешений / доверия.С помощью этой проверки, чтобы увидеть, возможны ли неуправляемые вызовы кода, можно единообразно защитить все неуправляемые вызовы.
Когда я компилирую этот код, я получаю предупреждение в этой строке:
if (SecurityManager.IsGranted(unmanagedCodePermission))
Вот предупреждение:
System.Security.SecurityManager.IsGranted (System.Security.IPermission) 'устарело: «IsGranted устарело и будет удалено в будущем выпуске.NET Framework.Пожалуйста, используйте вместо этого свойство PermissionSet для AppDomain или Assembly.
(обратите внимание, что я строю это на .Net 4.0 с использованием VS2010).
Итак, похоже, IsGranted устарел.Я посмотрел на свойство PermissionSet для AppDomain и Assembly, и было неясно, как именно выполнить одну и ту же проверку.
В случае LogEntry, похоже, эта информация не критична, поэтому она не являетсясчитается критической ошибкой, если неуправляемое разрешение недоступно.Рассмотрим следующие вопросы с той же точки зрения.То есть, если разрешение неуправляемого кода недоступно, это не так уж сложно, я могу жить без информации.
Наконец, пара вопросов:
Является ли хорошей идеей попытаться защитить вызовы от неуправляемого кода (например, P / Invoke)?Иногда, всегда, никогда?
Если это хорошая идея для защиты этих вызовов, является ли это разумным шаблоном для этого?Есть ли лучший способ?
Каков будет правильный (то есть не устаревший) способ сделать эквивалентную проверку в .Net 4.0?