Finding a memory card path on WM6

Is there an easy way to find the path to the memory card on a Windows Mobile device when there is a memory card and a Bluetooth connection with ftp?

+6
windows mobile
source share
8 answers

Keep in mind that the "\ Storage Card" is English oriented. A device made for another region may have a different name. The path name of the memory card on my device depends on how I use the device.

Some time ago, in MSDN formats, I answered several questions about how to detect memory cards in the file system and how to get the capacity of a memory card. I wrote the following, this is the answer to these questions and thought it would be useful to share. Storage cards are displayed in the file system as temporary directories. This program checks objects in the root of the device, and any folders with the temp attribute are considered positive.

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); } } } } 
+5
source share

The mount point is usually "\ Storage Card", but can be localized to other languages ​​or modified by OEMs (some devices use a "\ SD card" or other mount points, and some devices support the installation of multiple media). The best way to list the available cards is to use FindFirstFlashCard and FindNextFlashCard.

Both functions populate the WIN32_FIND_DATA structure. The most important field is cFileName, which will contain the path to the connection point of the card (for example, "\ Storage Card").

Please note that the internal memory of the device will also be listed with these functions. If you only care about external volumes, ignore the case where cFileName is an empty string ("").

Using these functions, you must #include <projects.h> and a link with note_prj.lib. Both are included in the Windows Mobile SDK for WM 2000 and later.

+10
source share

I found using the FindFirstFlashCard / FindNextFlashCard API more reliable than listing directories and checking the temporary flag (which, for example, will return Bluetooth public folders).

The following application example shows how to use them and the required P / Invoke statements.

 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); } } 
+4
source share

Unable to add a comment to the TreeUK and ctacke dispute below:

This does not guarantee that you will find a memory card - many devices mount the built-in flash the same way, and it will also appear in this list. - ctacke May 8 at 18:23
This worked well for me on HTC and Psion devices. What devices do you know doesn't work? It would be useful to see if there is another attribute you can save on building in Flash memory with. - TreeUK May 9 at 10:29 p.m.

To give an idea about the Motorola MC75 (used for SymboL), I used this piece of (native) code:

  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); 

Debug output:

 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] 

"Application" and "Cache Drive" are internal flash drives. "Memory Card" is a removable SD card. All of them are marked as FlashDrive (they are), but only the "Memory Card" is removable.

+3
source share

I am posting here the code that I use to get memory card mount cards. The part where I get the flash drive tracks is copied from the Sible message with a few changes.

The main difference is that I look at the mount files of all flash cards, and I save one (s) that matches the default memory card name that I read from the Windows registry.

It solves the problem that arises on Motorola smart devices, where there are several flash cards, and only one SD card reader, whose name can be changed by default using a numerical suffix (for example, in the English WM systems: 'Memory card' , 'Storage Card2', etc.). I tested it on some motorola models (MC75, MC75A, MC90, MC65) with WM 6.5 English.

This solution should work well with different languages ​​of Windows mobile phones, but I don’t know if it can work with those that change the default name for memory cards. It all depends on whether the device manufacturer updates the Windows registry with the name new by default.

It would be great if you could test it on different WM devices or devices. Feedback is welcome.

  // // 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 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); } 
+3
source share

I have combined a number of solutions above, especially the Qwlice code, to find SD cards on a number of devices. This solution finds only SD cards (therefore, excludes all internal "memory cards" that some devices have), without using their own dll calls.

The code looks for the key HKEY_LOCAL_MACHINE \ System \ StorageManager \ Profiles \ for keys containing "SD", since the name changes slightly on some devices, finds the default mount dir and then looks for temporary directories starting with this. This means that it will find \ StorageCard2, \ StorageCard3, etc.

I use this on a number of Intermec and Motorola / Symbol devices and have not experienced any problems. Here is the code below:

 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(); } } 
+3
source share

There's a clean C # way to do this without your own calls.

Taken from 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; } 
+2
source share

In Windows CE 5 (which is the base for Windows Mobile 6), memory cards are installed in the root file system as "Memory Card", "Memory Card2", etc.

To find out if he is connected to a GetFileAttributes call (or, it seems to me, a remote version of CeGetFileAttributes) that goes through the full path ("\ Storage Card \"). If it returns INVALID_FILE_ATTRIBUTES, then it is not mounted, otherwise check that it is a directory before returning true.

+1
source share

All Articles