Обнаружение функции при вызове P / в C # и .NET

Я пытаюсь найти хороший способ определить, существует ли функция до P / Invoking. Например, вызов встроенной функции StrCmpLogicalW :

[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
   [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
   public static extern int StrCmpLogicalW(string psz1, string psz2);
}

приведет к сбою в некоторых системах, в которых нет этой функции.

Я не хочу выполнять проверку версии , так как это плохая практика, а иногда может просто ошибаться (например, когда функциональность переносится обратно или когда функциональность может быть удалена).

Правильный способ - проверить наличие экспорта из shlwapi.dll :

private static _StrCmpLogicalW: function(String psz1, String psz2): Integer;
private Boolean _StrCmpLogicalWInitialized;

public int StrCmpLogicalW(String psz1, psz2)
{
    if (!_StrCmpLogialInitialized)
    {
        _StrCmpLogicalW = GetProcedure("shlwapi.dll", "StrCmpLogicalW");
        _StrCmpLogicalWInitialized = true;
    }

    if (_StrCmpLogicalW)
       return _StrCmpLogicalW(psz1, psz2)
    else
       return String.Compare(psz1, psz2, StringComparison.CurrentCultureIgnoreCase);
}

Проблема, конечно же, в том, что C # не поддерживает функцию указатели, например:

_StrCmpLogicalW = GetProcedure("shlwapi.dll", "StrCmpLogicalW");

не могут быть выполнены.

Итак, я пытаюсь найти альтернативный синтаксис для выполнения той же логики в .NET. Пока у меня есть следующий псевдокод, но я в тупик:

[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
   private Boolean IsSupported = false;
   private Boolean IsInitialized = false;

   [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, Export="StrCmpLogicalW", CaseSensitivie=false, SetsLastError=true, IsNative=false, SupportsPeanutMandMs=true)]
   private static extern int UnsafeStrCmpLogicalW(string psz1, string psz2);

   public int StrCmpLogicalW(string s1, string s2)
   {
       if (!IsInitialized) 
       {
          //todo: figure out how to loadLibrary in .net
          //todo: figure out how to getProcedureAddress in .net
          IsSupported = (result from getProcedureAddress is not null);
          IsInitialized = true;
       }

       if (IsSupported) 
          return UnsafeStrCmpLogicalW(s1, s2);
       else
          return String.Compare(s1, s2, StringComparison.CurrentCultureIgnoreCase);
   }
}

и мне нужна помощь.


Другой пример некоторых экспортов, наличие которых я хочу обнаружить:

  • dwmapi.dll :: DwmIsCompositionEnabled
  • dwmapi.dll :: DwmExtendFrameIntoClientArea
  • dwmapi.dll :: DwmGetColorizationColor
  • dwmapi. dll :: DwmGetColorizationParameters (недокументированный 1 , еще не экспортированный по имени, порядковый номер 127)
  • dwmapi.dll :: 127 (недокументированный 1 , DwmGetColorizationParameters)

1 для Windows 7 SP1

В .NET уже должен быть шаблон проектирования для проверки наличия функций ОС. Может ли кто-нибудь указать мне на пример предпочтительного способа обнаружения функций в .NET?

13
задан Ian Boyd 9 January 2012 в 20:47
поделиться