Как мне справиться с неудачным DllImport? - PullRequest
4 голосов
/ 09 июня 2009

Я пытаюсь написать управляемый класс C #, чтобы обернуть SHGetKnownFolderPath, пока он работает в Vista, но падает на XP из-за отсутствия надлежащей функции в shell32.dll, как ожидалось.

Я хочу, чтобы он был установлен, чтобы я мог использовать альтернативное (по общему признанию хакерское) решение с использованием System.Environment.GetFolderPath при использовании XP. (Или даже лучше, если он не может найти функцию в shell32.)

Есть ли способ сделать это иначе, чем условная компиляция?

Мой текущий код выглядит так:

public abstract class KnownFolders
    {
        [DllImport("shell32.dll")]
        private static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);

        // Trim properties to get various Guids.

        public static string GetKnownFolderPath(Guid guid)
        {
            IntPtr pPath;
            int result = SHGetKnownFolderPath(guid, 0, IntPtr.Zero, out pPath);
            if (result == 0)
            {
                string s = Marshal.PtrToStringUni(pPath);
                Marshal.FreeCoTaskMem(pPath);
                return s;
            }
            else
                throw new System.ComponentModel.Win32Exception(result);
        }
    }

Ответы [ 2 ]

9 голосов
/ 09 июня 2009

Оберните ваш вызов в SHGetKnownFolderPath в блоке try-catch. Поймайте System.EntryPointNotFoundException и попробуйте альтернативное решение:

public static string GetKnownFolderPath(Guid guid)
{
  try
  {
    IntPtr pPath;
    int result = SHGetKnownFolderPath(guid, 0, IntPtr.Zero, out pPath);
    if (result == 0)
    {
        string s = Marshal.PtrToStringUni(pPath);
        Marshal.FreeCoTaskMem(pPath);
        return s;
    }
    else
        throw new System.ComponentModel.Win32Exception(result);
  }
  catch(EntryPointNotFoundException ex)
  {
    DoAlternativeSolution();
  }
}
3 голосов
/ 09 июня 2009

Вы можете проверить версию ОС, используя свойство Environment.OSVersion . Я верю, если вы делаете

int osVersion = Environment.OSVersion.Version.Major

на XP это будет 5, а на Vista это будет 6. Так что оттуда просто к простой проверке.

if(osVersion == 5)
{
   //do XP way
}
else if(osVersion == 6)
{
   //P/Invoke it
}
...