1. オンラインのみのファイルの判別
Windows 8.1ではOneDrive中のファイルを「オフラインで利用可能」か「オンラインのみ」に設定できるが、「オンラインのみ」にした場合、これをデスクトップアプリのSystem.IO.FileStreamで開こうとすると、例外(System.IO.IOException)が飛ぶ。
例えば、以下のうち下の利用可能性を「オンラインのみ」にしたファイルがそれに当たる。

同じフォルダをコマンドプロンプトから「dir /a」で表示させたもの。「オンラインのみ」のファイルはサイズが括弧で囲まれている。

「オンラインのみ」のファイルはファイルエントリだけがローカルにあって、データ本体はクラウド上にあるものが必要に応じて流れてくるものなので、その状態では開けないのは別に不思議ではない。
問題はそれを事前にどうやって判別するかで、WinRTではStorageFile.IsAvailableかStorageFile.AttributesのLocallyIncompleteを見ればいい。一方、デスクトップアプリではそのものずばりの情報が出てこなくて時間を取られたが、答えは簡単だった。
このファイル属性のうち、Oのオフライン属性がそれで、OneDriveで「オンラインのみ」のファイルにはこれが付く。System.IO.FileAttributesのOfflineの項を見ると、"The file is offline. The data of the file is not immediately available."とあるので(OneDriveとは一言も出てこないが)、これらしい。
ということで、以下はテストコードとその結果。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
private class OneDriveFile | |
{ | |
public static void CheckFileIsAvailable(string filePath) | |
{ | |
var fileAttribute = File.GetAttributes(filePath); | |
Console.WriteLine("Attributes: {0}", fileAttribute); | |
var isAvailable = !fileAttribute.HasFlag(FileAttributes.Offline); | |
Console.WriteLine("Available: {0}", isAvailable); | |
try | |
{ | |
new FileStream(filePath, FileMode.Open, FileAccess.Read).Close(); | |
Console.WriteLine("CAN read."); | |
} | |
catch (IOException) | |
{ | |
Console.WriteLine("CANNOT read."); | |
} | |
} | |
public void CheckFiles() | |
{ | |
var folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "SkyDrive", "Reference"); | |
CheckFileIsAvailable(Path.Combine(folderPath, "容量計算.xlsx")); | |
// Attributes: Archive | |
// Available: True | |
// CAN read. | |
CheckFileIsAvailable(Path.Combine(folderPath, "暗号技術.pdf")); | |
// Attributes: Hidden, System, Archive, SparseFile, ReparsePoint, Offline | |
// Available: False | |
// CANNOT read. | |
Console.ReadLine(); | |
} | |
} |
2. オンラインのみのファイルへのアクセス
オーソドックスにはOneDriveのAPIを使えばいい話だが、MSDNに以下のエントリがあった。
このサンプルコードをふむふむと読み始めて、途中で意味が呑み込めてきて……驚愕。
デスクトップアプリからWinRTのAPIを使うお約束をすっ飛ばし、デスクトップアプリでも使えるとされていないStorageFileクラスを、WinRTのアセンブリを動的ロードしてリフレクションして実行するラッパー、とは!
いや、Microsoftの人が書いているのだからできるのだろうが、何という力業。積極的に使いたいかは別にして、そういうのもあるのか……と。
3. Windows 10での変更
Windows 10ではまたOneDriveに変更があるらしく、現在のInsider Previewでは「オンラインのみ」の設定はなくなり、すべて「オフラインで利用可能」と同じく、データ本体がローカルにコピーされるようになっている。したがって、「オンラインのみ」のファイルを扱う方法はWindows 8.1で最後になるらしい。いい加減安定させた方がいいと思うが。