6

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

4

8 回答 8

10

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

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

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

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

于 2008-09-07T13:31:41.067 回答
5

请记住,“\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);
            }
        }
    }
}
于 2009-03-19T05:13:54.187 回答
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);
    }
}
于 2009-03-30T16:55:45.180 回答
3

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

取自这里

//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;
}
于 2009-05-08T15:32:46.077 回答
3

无法在下面的 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 卡。所有都标记为闪存驱动器(它们是),但只有“存储卡”是可移动的。

于 2010-01-08T11:33:38.537 回答
3

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

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

它解决了一个在摩托罗拉的智能设备上有多个闪存卡和只有一个 sd 读卡器的问题,其安装目录的名称可以通过数字后缀从默认值更改(即在英文 WM 系统中:'Storage Card','存储卡 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);
   }
于 2011-09-01T15:26:33.397 回答
3

我结合了上面的一些解决方案,特别是 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();
    }
}
于 2012-09-13T06:26:37.967 回答
1

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

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

于 2008-09-03T08:28:40.487 回答