質問
ストレージカードとBluetooth FTP接続があるときに、Windowsモバイルデバイスにストレージカードのパスを見つける簡単な方法はありますか?
解決
「\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);
}
}
}
}
他のヒント
マウント ポイントは通常「\Storage Card」ですが、他の言語にローカライズしたり、OEM によって変更したりすることができます (一部のデバイスは「\SD Card」または他のマウント ポイントを使用し、一部のデバイスは複数のストレージ メディアのマウントをサポートしています)。使用可能なカードを列挙する最良の方法は、FindFirstFlashCard と FindNextFlashCard を使用することです。
どちらの関数も WIN32_FIND_DATA 構造体に書き込みます。最も重要なフィールドは cFileName で、これにはカードのマウント ポイントへのパスが含まれます (例:"\ストレージカード")。
デバイスの内部メモリもこれらの関数によって列挙されることに注意してください。外部ボリュームのみを考慮する場合は、cFileName が空の文字列 ("") である場合は無視してください。
これらの関数を使用するには、#include <projects.h> と note_prj.lib とリンクする必要があります。どちらも、WM 2000 以降の Windows Mobile SDK に含まれています。
FindFirstFlashCard/FindNextFlashCard API を使用する方が、ディレクトリを列挙して一時フラグをチェックするよりも信頼性が高いことがわかりました (たとえば、Bluetooth 共有フォルダーが返されます)。
次のサンプル アプリケーションは、それらの使用方法と必要な 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);
}
}
ネイティブ呼び出しを行わずにこれを行う純粋な 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;
}
以下の TreeUK と ctacke のディスカッションにはコメントを追加できません。
これはストレージカードを見つけることは保証されていません - 多くのデバイスは、同じようにビルトインフラッシュをマウントし、このリストにも表示されます。- Ctacke 5月8日18:23
これは、HTCおよびPSIONデバイスで私にとってうまくいきました。これが機能しないデバイスは何ですか?フラッシュメモリのビルドを割引できる別の属性があるかどうかを確認する価値があります。– TreeUK 5月9日 22:29
Motorola 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 としてマークされていますが (そのとおりです)、「ストレージ カード」のみが取り外し可能です。
上記のいくつかのソリューション、特に qwlice のコードを組み合わせて、さまざまなデバイス上の SD カードを検索しました。このソリューションは、ネイティブ DLL 呼び出しを使用せずに、SD カードのみを検索します (したがって、一部のデバイスが備えている内部「ストレージ カード」はすべて除外されます)。
このコードは、デバイスによっては名前が若干異なるため、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();
}
}
ストレージ カードのマウント ディレクトリを取得するために使用するコードをここに投稿します。フラッシュ カードのパスを取得する部分は、Sibly の投稿からいくつかの変更を加えてコピーしたものです。
主な違いは、すべてのフラッシュ カードのマウント ディレクトリを検索し、Windows のレジストリから読み取ったデフォルトのストレージ カード名と一致するものを保持することです。
これは、複数のフラッシュ カードと 1 つの SD カード リーダーのみがあり、そのマウント ディレクトリ名が数値接尾辞によってデフォルトから変更される可能性がある Motorola のスマート デバイスで発生する問題を解決します。英語の WM システム:「ストレージ カード」、「ストレージ カード 2」など)。WM 6.5 英語を搭載した一部の Motorola モデル (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);
}
Windows CE 5 (Windows Mobile 6 のベース) では、ストレージ カードはルート ファイル システムに「Storage Card\」、「Storage Card2\」などとしてマウントされます。
マウントされているかどうかを確認するには、フル パス (「\Storage Card\」) を渡して GetFileAttributes (またはリモート バージョンの CeGetFileAttributes) を呼び出します。INVALID_FILE_ATTRIBUTES を返す場合はマウントされていません。それ以外の場合は、true を返す前にディレクトリであることを確認します。