tagspaces tag files and windows-mobile

windows mobile - tag - Encontrar la ruta de la tarjeta de almacenamiento en WM6



tag folders (8)

¿Hay alguna manera fácil de encontrar la ruta de la tarjeta de almacenamiento en un dispositivo Windows Mobile cuando hay una tarjeta de almacenamiento y una conexión ftp bluetooth?


En Windows CE 5 (que es la base para Windows Mobile 6), las tarjetas de almacenamiento se montan en el sistema de archivos raíz como "Tarjeta de almacenamiento /", "Tarjeta de almacenamiento 2", etc.

Para averiguar si está montado, llame a GetFileAttributes (o a la versión remota CeGetFileAttributes, creo) pasando en la ruta completa ("/ Storage Card /"). Si devuelve INVALID_FILE_ATTRIBUTES, no está montado; de lo contrario, verifique que sea un directorio antes de que sea verdadero.


El punto de montaje suele ser "/ Storage Card" pero puede ser localizado en otros idiomas o modificado por OEM (algunos dispositivos usan "/ SD Card" u otros puntos de montaje, y algunos dispositivos admiten el montaje de varios medios de almacenamiento). La mejor manera de enumerar las tarjetas disponibles es usar FindFirstFlashCard y FindNextFlashCard.

Ambas funciones completan una estructura WIN32_FIND_DATA. El campo más importante es cFileName, que contendrá la ruta al punto de montaje de la tarjeta (por ejemplo, "/ Storage Card").

Tenga en cuenta que la memoria interna del dispositivo también será enumerada por estas funciones. Si solo le importan los volúmenes externos, ignore el caso en que cFileName es una cadena vacía ("").

El uso de estas funciones requiere que #incluya <projects.h> y enlace con note_prj.lib. Ambos están incluidos en los SDK de Windows Mobile para WM 2000 y versiones posteriores.


He descubierto que usar las API FindFirstFlashCard / FindNextFlashCard es más confiable que enumerar directorios y verificar el indicador temporal (que devolverá las carpetas compartidas de bluetooth, por ejemplo).

La siguiente aplicación de muestra demuestra cómo usarlos y las declaraciones P / Invoke requeridas.

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


Hay una forma pura de C # para hacer esto sin llamadas nativas.

Tomado de aquí .

//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; }


No se puede agregar un comentario sobre la discusión TreeUK y ctacke a continuación:

No está garantizado que se encuentre una tarjeta de almacenamiento; muchos dispositivos montan el flash incorporado de la misma manera, y aparecería en esta lista también. - ctacke 8 de mayo a las 18:23
Esto me ha funcionado bien en los dispositivos HTC y Psion. ¿Qué dispositivos sabes que esto no funciona? Merece la pena ver si hay otro atributo con el que puede descontar la construcción en la memoria flash. - TreeUK 9 de mayo a las 22:29

Para dar una idea sobre un Motorola MC75 (que solía ser SymboL), utilicé este código pieza (de origen):

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

Salida de depuración:

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]

La "Aplicación" y el "Disco de caché" son unidades flash internas. La "Tarjeta de almacenamiento" es una tarjeta SD extraíble. Todos están marcados como FlashDrive (que son), pero solo la "Tarjeta de almacenamiento" es extraíble.


Tenga en cuenta que "/ Storage Card" está orientado al inglés. Un dispositivo hecho para una región diferente puede tener un nombre diferente. El nombre de la ruta de la tarjeta de almacenamiento en mi dispositivo varía con la forma en que estoy usando el dispositivo.

Hace algún tiempo, en los formularios de MSDN, respondí algunas preguntas sobre cómo detectar las tarjetas de almacenamiento en el sistema de archivos y cómo se obtiene la capacidad de la tarjeta de almacenamiento. Escribí lo siguiente podría ser una respuesta a esas preguntas y pensé que sería útil compartir. Las tarjetas de almacenamiento aparecen en el sistema de archivos como directorios temporales. Este programa examina los objetos en la raíz del dispositivo y cualquier carpeta que tenga un atributo temporal se considera una coincidencia positiva

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


He combinado varias de las soluciones anteriores, particularmente el código de qwlice, para encontrar tarjetas SD en una variedad de dispositivos. Esta solución solo encuentra tarjetas SD (por lo que excluye todas las "tarjetas de almacenamiento" internas que tienen algunos dispositivos) sin utilizar llamadas dll nativas.

El código busca la clave HKEY_LOCAL_MACHINE / System / StorageManager / Profiles / para las claves que contienen "SD", ya que el nombre varía ligeramente en algunos dispositivos, busca el directorio de montaje predeterminado y luego busca los directorios temporales que comienzan con esto. Esto significa que encontrará / StorageCard2, / StorageCard3, etc.

He estado usando esto en una gama de dispositivos Intermec y Motorola / Symbol y no he tenido ningún problema. Aquí está el código a continuación:

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


Publiqué aquí el código que uso para obtener los directorios de montaje de las tarjetas de almacenamiento. La parte donde obtengo las rutas de las tarjetas flash se copia de la publicación de Sibly con algunos cambios.

La principal diferencia radica en que busco a través de los directorios de montaje de todas las tarjetas de memoria flash y guardo las que coinciden con el nombre de la tarjeta de almacenamiento predeterminada que leo en el registro de Windows.

Resuelve el problema que uno tiene en los dispositivos inteligentes de motorola donde hay varias tarjetas flash y solo un lector de tarjetas sd cuyo nombre de directorio de montaje puede cambiar del valor predeterminado por el sufijo numérico (es decir, en sistemas WM en inglés: ''Tarjeta de almacenamiento'', '' Storage Card2 ''y así sucesivamente). Lo probé en algunos modelos de motorola (MC75, MC75A, MC90, MC65) con WM 6.5 en inglés.

Esta solución debería funcionar bien con los diferentes idiomas de Windows Mobile, pero no sé si se puede tratar con aquellos que cambian el nombre predeterminado de las tarjetas de almacenamiento. Todo depende de si el fabricante del dispositivo actualiza el registro de Windows con el nuevo nombre predeterminado.

Sería genial si puedes probarlo en diferentes WM o dispositivos. Comentarios son bienvenidos.

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