ストレージカードとBluetoothFTP接続がある場合、Windows Mobileデバイスでストレージカードのパスを見つける簡単な方法はありますか?
8 に答える
マウント ポイントは通常 "\Storage Card" ですが、他の言語にローカライズしたり、OEM によって変更したりできます (一部のデバイスは "\SD カード" または他のマウント ポイントを使用し、一部のデバイスは複数のストレージ メディアのマウントをサポートしています)。利用可能なカードを列挙する最良の方法は、FindFirstFlashCard と FindNextFlashCard を使用することです。
どちらの関数も WIN32_FIND_DATA 構造体に入力します。最も重要なフィールドは cFileName で、これにはカードのマウント ポイントへのパスが含まれます (例: "\Storage Card")。
デバイスの内部メモリもこれらの関数によって列挙されることに注意してください。外部ボリュームのみを気にする場合は、cFileName が空の文字列 ("") であるケースを無視してください。
これらの関数を使用するには、#include <projects.h> と note_prj.lib とのリンクが必要です。どちらも WM 2000 以降の Windows Mobile SDK に含まれています。
「\StorageCard」は英語指向であることに注意してください。別の地域向けに作成されたデバイスは、別の名前を持つ場合があります。デバイスのストレージカードパスの名前は、デバイスの使用方法によって異なります。
少し前に、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);
}
}
}
}
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);
}
}
上記の多くのソリューション、特に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();
}
}
ネイティブ呼び出しなしでこれを行うための純粋な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 としてマークされています (それらはそうです) が、「ストレージ カード」のみが取り外し可能です。
Windows CE 5(Windows Mobile 6のベース)では、ストレージカードは「ストレージカード」、「ストレージカード2」などとしてルートファイルシステムにマウントされます。
マウントされているかどうかを確認するには、GetFileAttributes(または私が信じているリモートバージョンのCeGetFileAttributes)を呼び出して、フルパス( "\ Storage Card \")を渡します。INVALID_FILE_ATTRIBUTESを返す場合はマウントされていません。それ以外の場合は、trueを返す前にディレクトリであることを確認してください。