【问题标题】:Finding the storage card path on WM6在WM6上查找存储卡路径
【发布时间】:2010-09-07 14:29:40
【问题描述】:

有没有一种简单的方法可以在 Windows Mobile 设备上找到存储卡的路径 什么时候有存储卡和蓝牙ftp连接?

【问题讨论】:

    标签: windows-mobile


    【解决方案1】:

    在 Windows CE 5(Windows Mobile 6 的基础)上,存储卡以“Storage Card\”、“Storage Card2\”等形式安装在根文件系统中。

    要确定它是否已挂载,调用 GetFileAttributes(或我相信的远程版本 CeGetFileAttributes)传入完整路径(“\Storage Card\”)。如果它返回 INVALID_FILE_ATTRIBUTES 那么它没有被挂载,否则在返回 true 之前检查它以确保它是一个目录。

    【讨论】:

    • 硬编码 \Storage Card 路径是不安全的。请参阅我的答案以了解如何获取任何已安装卡的路径。
    【解决方案2】:

    挂载点通常是“\Storage Card”,但可以本地化为其他语言或由 OEM 修改(有些设备使用“\SD Card”或其他挂载点,有些设备支持挂载多个存储介质)。枚举可用卡片的最佳方法是使用 FindFirstFlashCard 和 FindNextFlashCard。

    这两个函数都填充了一个 WIN32_FIND_DATA 结构。最重要的字段是 cFileName,它将包含卡挂载点的路径(例如“\Storage Card”)。

    请注意,这些函数也会枚举设备的内部存储器。如果您只关心外部卷,请忽略 cFileName 为空字符串 ("") 的情况。

    使用这些函数需要您#include 并与 note_prj.lib 链接。两者都包含在 WM 2000 及更高版本的 Windows Mobile SDK 中。

    【讨论】:

    • 好答案,最适合这个问题恕我直言。
    【解决方案3】:

    请记住,“\Storage Card”是面向英文的。为不同地区制造的设备可能具有不同的名称。我设备上存储卡路径的名称因我使用设备的方式而异。

    前段时间,我在 MSDN 表单中回答了几个问题,关于如何检测文件系统中的存储卡以及如何获取存储卡的容量。我写了以下可能是对这些问题的回应,并认为分享会有所帮助。存储卡在文件系统中显示为临时目录。该程序检查设备根目录中的对象,任何具有 temp 属性的文件夹都被认为是正匹配

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
    namespace StorageCardInfo
    {
        class Program
        {
            const ulong Megabyte = 1048576;
            const ulong Gigabyte = 1073741824;
    
            [DllImport("CoreDLL")]
            static extern int GetDiskFreeSpaceEx(
            string DirectoryName,
            out ulong lpFreeBytesAvailableToCaller,
            out ulong lpTotalNumberOfBytes,
            out ulong lpTotalNumberOfFreeBytes 
        );
    
        static void Main(string[] args)
        {
            DirectoryInfo root = new DirectoryInfo("\\");
            DirectoryInfo[] directoryList = root.GetDirectories();
            ulong FreeBytesAvailable;
            ulong TotalCapacity;
            ulong TotalFreeBytes;
    
            for (int i = 0; i < directoryList.Length; ++i)
            {
                if ((directoryList.Attributes & FileAttributes.Temporary) != 0)
                {
                    GetDiskFreeSpaceEx(directoryList.FullName, out FreeBytesAvailable, out TotalCapacity, out TotalFreeBytes);
                    Console.Out.WriteLine("Storage card name: {0}", directoryList.FullName);
                    Console.Out.WriteLine("Available Bytes : {0}", FreeBytesAvailable);
                    Console.Out.WriteLine("Total Capacity : {0}", TotalCapacity);
                    Console.Out.WriteLine("Total Free Bytes : {0}", TotalFreeBytes);
                }
            }
        }
    }
    

    【讨论】:

    • 存储卡以外的文件夹可能会显示为临时文件夹,因此这不是非常可靠。如果你真的想知道,那么 P/Invoking FindFirstFlashCard (msdn.microsoft.com/en-us/library/ms840697.aspx) 是可靠的。从设备管理器中寻找设备挂载事件也是如此。
    • 上面使用的代码是我最终在我的程序中使用的。我在 channel9 上找到了一些关于存储卡的资源,他们也使用了这些资源。
    • FindFirstFlashCard 也不可靠。我有一个设备(Handheld Nautiz X5),它的根目录中有另一个名为“ProgramStore”的文件夹。如果我使用 FindFirstFlashCard,我会得到 ProgramStore 而不是“存储卡”。
    【解决方案4】:

    我发现使用 FindFirstFlashCard/FindNextFlashCard API 比枚举目录和检查临时标志(例如,它将返回蓝牙共享文件夹)更可靠。

    以下示例应用程序演示了如何使用它们以及所需的 P/Invoke 语句。

    using System;
    using System.Runtime.InteropServices;
    
    namespace RemovableStorageTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                string removableDirectory = GetRemovableStorageDirectory();
                if (removableDirectory != null)
                {
                    Console.WriteLine(removableDirectory);
                }
                else
                {
                    Console.WriteLine("No removable drive found");
                }
            }
    
            public static string GetRemovableStorageDirectory()
            {
                string removableStorageDirectory = null;
    
                WIN32_FIND_DATA findData = new WIN32_FIND_DATA();
                IntPtr handle = IntPtr.Zero;
    
                handle = FindFirstFlashCard(ref findData);
    
                if (handle != INVALID_HANDLE_VALUE)
                {
                    do
                    {
                        if (!string.IsNullOrEmpty(findData.cFileName))
                        {
                            removableStorageDirectory = findData.cFileName;
                            break;
                        }
                    }
                    while (FindNextFlashCard(handle, ref findData));
                    FindClose(handle);
                }
    
                return removableStorageDirectory;
            }
    
            public static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
    
            // The CharSet must match the CharSet of the corresponding PInvoke signature
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct WIN32_FIND_DATA
            {
                public int dwFileAttributes;
                public FILETIME ftCreationTime;
                public FILETIME ftLastAccessTime;
                public FILETIME ftLastWriteTime;
                public int nFileSizeHigh;
                public int nFileSizeLow;
                public int dwOID;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
                public string cFileName;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
                public string cAlternateFileName;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct FILETIME
            {
                public int dwLowDateTime;
                public int dwHighDateTime;
            };
    
            [DllImport("note_prj", EntryPoint = "FindFirstFlashCard")]
            public extern static IntPtr FindFirstFlashCard(ref WIN32_FIND_DATA findData);
    
            [DllImport("note_prj", EntryPoint = "FindNextFlashCard")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public extern static bool FindNextFlashCard(IntPtr hFlashCard, ref WIN32_FIND_DATA findData);
    
            [DllImport("coredll")]
            public static extern bool FindClose(IntPtr hFindFile);
        }
    }
    

    【讨论】:

    • FindFirstFlashCard 也不可靠。我有一个设备(Handheld Nautiz X5),它的根目录中有另一个名为“ProgramStore”的文件夹。如果我使用 FindFirstFlashCard,我会得到 ProgramStore 而不是“存储卡”。
    【解决方案5】:

    有一种纯 C# 方法可以在没有本地调用的情况下执行此操作。

    取自here

    //codesnippet:06EE3DE0-D469-44DD-A15F-D8AF629E4E03
    public string GetStorageCardFolder()
    {
       string storageCardFolder = string.Empty;
       foreach (string directory in Directory.GetDirectories("\\"))
       {
           DirectoryInfo dirInfo = new DirectoryInfo(directory);
    
           //Storage cards have temporary attributes do a bitwise check.
            //http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=612136&SiteID=1
            if ((dirInfo.Attributes & FileAttributes.Temporary) == FileAttributes.Temporary)
                storageCardFolder = directory;
        }
    
        return storageCardFolder;
    }
    

    【讨论】:

    • 这不保证能找到存储卡 - 许多设备以相同的方式安装内置闪存,它也会显示在此列表中。
    • 这对我来说在 HTC 和 Psion 设备上运行良好。您知道哪些设备无法使用?如果有另一个属性可以打折内置闪存,那将是值得一看的。
    【解决方案6】:

    无法在下面的 TreeUK 和 ctacke 讨论中添加评论:

    这不保证能找到 存储卡 - 许多设备安装 以同样的方式内置闪光灯,它 也会出现在这个列表中。 – ctacke 5 月 8 日 18:23
    这有 在 HTC 和 Psion 上对我来说效果很好 设备。您知道哪些设备 这不起作用?值得 看看有没有别的属性 你可以打折内置闪存 内存与。 – TreeUK 5 月 9 日 22:29

    为了给出关于摩托罗拉 MC75(以前是 SymboL)的想法,我使用了这段(原生)代码:

        WIN32_FIND_DATA cardinfo;
    HANDLE  card = FindFirstFlashCard(&cardinfo);
    if (card != INVALID_HANDLE_VALUE)
    {
        TCHAR existFile[MAX_PATH];
    
        wprintf(_T("found : %s\n"), cardinfo.cFileName);
    
        while(FindNextFlashCard(card, &cardinfo))
        {
            wprintf(_T("found : %s\n"), cardinfo.cFileName);
        }
    }
    FindClose(card);
    

    调试输出:

    cardinfo.dwFileAttributes   0x00000110  unsigned long int
    cardinfo.cFileName          "Application"   wchar_t[260]
    
    cardinfo.dwFileAttributes   0x00000110  unsigned long int
    cardinfo.cFileName          "Cache Disk"    wchar_t[260]
    
    cardinfo.dwFileAttributes   0x00000110  unsigned long int
    cardinfo.cFileName          "Storage Card"  wchar_t[260]
    

    “应用程序”和“缓存磁盘”是内部闪存驱动器。 “存储卡”是可移动的 SD 卡。所有都标记为闪存驱动器(它们是),但只有“存储卡”是可移动的。

    【讨论】:

      【解决方案7】:

      我在这里发布了我用来获取存储卡安装目录的代码。 我获取闪存卡路径的部分是从 Sibly 的帖子中复制的,并进行了一些更改。

      主要区别在于我搜索所有闪存卡的安装目录,并保留与我从 Windows 注册表读取的默认存储卡名称匹配的目录。

      它解决了在摩托罗拉智能设备上存在多张闪存卡且只有一个 sd 读卡器的问题,其安装目录的名称可以通过数字后缀从默认值更改(即在英文 WM 系统中:'Storage Card ' 、 '存储卡 2' 等)。 我在一些带有 WM 6.5 英语的摩托罗拉型号(MC75、MC75A、MC90、MC65)上对其进行了测试。

      这个解决方案应该适用于不同的 windows mobile 语言,但我不知道它是否可以处理那些改变 存储卡的默认名称。 这完全取决于设备制造商是否使用 new 默认名称更新 Windows 注册表。

      如果您可以在不同的 WM 或设备上进行测试,那就太好了。 欢迎反馈。

         //
         // the storage card is a flash drive mounted as a directory in the root folder 
         // of the smart device
         //
         // on english windows mobile systems the storage card is mounted in the directory "/Storage Card", 
         // if that directory already exists then it's mounted in "/Storage Card2" and so on
         //
         // the regional name of the mount base dir of the storage card can be found in
         // the registry at [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\Folder]
         //  
         // in order to find the path of the storage card we look for the flash drive that starts 
         // with the base name
         //
      
         public class StorageCard
         {
            private StorageCard()
            {
            }
      
            public static List<string> GetMountDirs()
            {
               string key = @"HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory";
               string storageCardBaseName = Registry.GetValue(key, "Folder", "Storage Card") as String;
               List<string> storageCards = new List<string>();
               foreach (string flashCard in GetFlashCardMountDirs())
               {
                  string path = flashCard.Trim();
                  if (path.StartsWith(storageCardBaseName))
                  {
                     storageCards.Add(path);
                  }
               }
               return storageCards;
            }
      
            private static List<string> GetFlashCardMountDirs()
            {
               List<string> storages = new List<string>();
      
               WIN32_FIND_DATA findData = new WIN32_FIND_DATA();
               IntPtr handle = IntPtr.Zero;
      
               handle = FindFirstFlashCard(ref findData);
      
               if (handle != INVALID_HANDLE_VALUE)
               {
                  do
                  {
                     if (!string.IsNullOrEmpty(findData.cFileName))
                     {
                        storages.Add(findData.cFileName);
                        storages.Add(findData.cAlternateFileName);
                     }
                  }
                  while (FindNextFlashCard(handle, ref findData));
                  FindClose(handle);
               }
      
               return storages;
            }
      
            private static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);    
      
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            private struct WIN32_FIND_DATA
            {
               public int dwFileAttributes;
               public FILETIME ftCreationTime;
               public FILETIME ftLastAccessTime;
               public FILETIME ftLastWriteTime;
               public int nFileSizeHigh;
               public int nFileSizeLow;
               public int dwOID;
               [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
               public string cFileName;
               [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
               public string cAlternateFileName;
            }
      
            [StructLayout(LayoutKind.Sequential)]
            private struct FILETIME
            {
               public int dwLowDateTime;
               public int dwHighDateTime;
            };
      
            [DllImport("note_prj", EntryPoint = "FindFirstFlashCard")]
            private extern static IntPtr FindFirstFlashCard(ref WIN32_FIND_DATA findData);
      
            [DllImport("note_prj", EntryPoint = "FindNextFlashCard")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private extern static bool FindNextFlashCard(IntPtr hFlashCard, ref WIN32_FIND_DATA findData);
      
            [DllImport("coredll")]
            private static extern bool FindClose(IntPtr hFindFile);
         }
      

      【讨论】:

      • 我尝试了这段代码,看看我是否能找到我应该“调用”我的“内部闪存驱动器”的东西,我猜它们被称为 IOW 如何指向我的手持设备上的特定文件,但我得到,“System.DllNotFoundException 未处理 HResult=-2146233052 消息=无法加载 DLL 'note_prj':找不到指定的模块。” note_prj?
      【解决方案8】:

      我结合了上面的一些解决方案,尤其是 qwlice 的代码,以在一系列设备上查找 SD 卡。此解决方案仅查找 SD 卡(因此不包括某些设备具有的所有内部“存储卡”),而不使用本机 dll 调用。

      代码在 HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\ 键中搜索包含“SD”的键,因为某些设备上的名称略有不同,找到默认安装目录,然后查找以此开头的临时目录。这意味着它将找到\StorageCard2、\StorageCard3等。

      我一直在一系列 Intermec 和 Motorola/Symbol 设备上使用它,并且没有遇到任何问题。下面是代码:

      public class StorageCardFinder
      {
          public static List<string> GetMountDirs()
          {
              //get default sd card folder name
              string key = @"HKEY_LOCAL_MACHINE\System\StorageManager\Profiles";
              RegistryKey profiles = Registry.LocalMachine.OpenSubKey(@"System\StorageManager\Profiles");
              string sdprofilename = profiles.GetSubKeyNames().FirstOrDefault(k => k.Contains("SD"));
              if (sdprofilename == null)
                  return new List<string>();
      
              key += "\\" + sdprofilename;
              string storageCardBaseName = Registry.GetValue(key, "Folder", "Storage Card") as String;
              if (storageCardBaseName == null)
                  return new List<string>();
      
              //find storage card
              List<string> cardDirectories = GetFlashCardMountDirs();
      
              List<string> storageCards = new List<string>();
              foreach (string flashCard in GetFlashCardMountDirs())
              {
                  string path = flashCard.Trim();
                  if (path.StartsWith(storageCardBaseName))
                  {
                      storageCards.Add("\\" + path);
                  }
              }
              return storageCards;
          }
      
          private static List<string> GetFlashCardMountDirs()
          {
              DirectoryInfo root = new DirectoryInfo("\\");
              return root.GetDirectories().Where(d => (d.Attributes & FileAttributes.Temporary) != 0)
                                          .Select(d => d.Name).ToList();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-09-24
        • 2016-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-06
        • 2013-04-15
        相关资源
        最近更新 更多