在WM6上查找存储卡路径

时间:2008-09-02 18:44:59

标签: windows-mobile

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

8 个答案:

答案 0 :(得分:10)

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

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

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

使用这些功能需要#include< projects.h>并与note_prj.lib链接。两者都包含在WM 2000及更高版本的Windows Mobile SDK中。

答案 1 :(得分:5)

请记住,“\存储卡”是面向英语的。为不同区域制作的设备可以具有不同的名称。我的设备上存储卡路径的名称因我使用设备的方式而异。

前一段时间,在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);
            }
        }
    }
}

答案 2 :(得分:5)

我发现使用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);
    }
}

答案 3 :(得分:3)

有一种纯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;
}

答案 4 :(得分:3)

无法在下面的TreeUK和ctacke discusion上添加评论:

  

这不能保证找到一个   存储卡 - 许多设备安装   同样的内置闪光灯,它   也将出现在此列表中。 -   ctacke 5月8日18:23
  这有   在HTC和Psion上为我工作得很好   设备。你知道什么设备   这不起作用?值得的   看看是否有另一个属性   你可以在flash中打折   记忆。 - 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卡。所有都被标记为FlashDrive(它们是),但只有“存储卡”是可移动的。

答案 5 :(得分:3)

我在这里发布了用于获取存储卡的挂载的代码。 我获得闪存卡路径的部分是从Sibly的帖子中复制的,只有一些更改。

主要区别在于我搜索所有闪存卡的挂载,并保留与我从Windows注册表中读取的默认存储卡名称匹配的那个。

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

这个解决方案应该适用于不同的windows mobile语言,但我不知道它是否可以处理那些改变它们的语言 存储卡的默认名称。 这完全取决于设备的制造商是否使用默认名称更新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);
   }

答案 6 :(得分:3)

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

代码在HKEY_LOCAL_MACHINE \ System \ StorageManager \ Profiles \键中搜索包含“SD”的键,因为某些设备上的名称略有不同,找到默认的mount dir,然后查找以此开头的临时目录。这意味着它将找到\ 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();
    }
}

答案 7 :(得分:1)

在Windows CE 5(Windows Mobile 6的基础)上,存储卡作为“存储卡”,“存储卡2”等安装在根文件系统中。

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