【问题标题】:How do I handle a failed DllImport?如何处理失败的 DllImport?
【发布时间】:2010-11-01 11:38:15
【问题描述】:

我正在尝试编写一个 C# 托管类来包装 SHGetKnownFolderPath,目前它可以在 Vista 上运行,但由于没有在 shell32.dll 中找到正确的函数,因此在 XP 上崩溃,正如预期的那样。

我想设置它,这样如果使用 XP,我可以使用 System.Environment.GetFolderPath 回退到一个(公认的 hacky)解决方案。 (或者,如果它在 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);
        }
    }

【问题讨论】:

    标签: c# windows-vista interop windows-xp dllimport


    【解决方案1】:

    将您对 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();
      }
    }
    

    【讨论】:

    • 好的,这行得通,但有一点小改动。我必须捕获一个 EntryPointNotFoundException,而不是一个 DllNotFoundException。由于该函数来自 shell32.dll,因此在功能强大的 Windows 平台上不太可能丢失。
    • 是的,没错,我会更新我的回复以反映实际的异常情况。
    【解决方案2】:

    您可以使用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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      相关资源
      最近更新 更多