• 締切済み

ソフトウェアからオープンされているファイルの確認

たとえば、メモ帳でもいいのですが、【test.txt】がオープンされているとします。プログラムから【test.txt】が現在オープンされているか確認をしたのですが、そのようなAPIはありますか? MSDNで_lopenで確認するサンプルはありましたが、16bit版なので使えません。 CreateFileの引数等でわかるものなのでしょうか?

みんなの回答

  • macchun
  • ベストアンサー率50% (3/6)
回答No.7

#6 の補足です。 変更検出を行うフォルダについて書き忘れました。 たとえば、共有フォルダ内のファイル3個 ・\\server\share\foo1\bar1.txt ・\\server\share\foo1\bar2.txt ・\\server\share\foo2\bar3.txt の変更検出を行う場合には、 ・\\server\share\foo1 ・\\server\share\foo2 の2フォルダについて、変更検出処理を行う必要があります。

すると、全ての回答が全文表示されます。
  • macchun
  • ベストアンサー率50% (3/6)
回答No.6

LAN環境内でサーバの共有フォルダにあるファイルの新規・変更・削除・更新をリアルタイムに取得するとなりますと、フォルダの変更通知APIを使用したほうが良いと思います。 サンプルは下記のとおりです(注意:エラー処理は省いています)。 HANDLE folderHandle = CreateFile( "\\server\share", // ファイル名へのポインタ FILE_LIST_DIRECTORY, // アクセス( 読み書き)モード FILE_SHARE_READ|FILE_SHARE_DELETE, // 共有モード NULL, // セキュリティ記述子 OPEN_EXISTING, // 作成方法 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // ファイル属性 NULL // コピーするファイルと属性 ); bufferSize = 1024; FILE_NOTIFY_INFORMATION* buffer= malloc(bufferSize); while(1) { BOOL fResult; OVERLAPPED overlapped; overlapped.hEvent=CreateEvent(...); fResult = ReadDirectoryChangesW( folderHandle, // 監視するディレクトリのハンドル buffer, // 読み取った結果を受け取るバッファへのポインタ bufferSize, // buffer の長さ FALSE, // ディレクトリまたはディレクトリツリーを監視するためのフラグ(TRUEでも可) FILE_NOTIFY_CHANGE_FILE_NAME | ... , // 監視に使うフィルタ条件 NULL, // 返されたバイト数 &overlapped, // 重複 I/O 操作に必要な構造体へのポインタ NULL // 完了ルーチンへのポインタ ); if(FALSE == fResult) {/* エラー処理 */ break; } WaitForSingleObject(overlapped.hEvent, ...); DWORD resultSize; GetOverlappedResult(folderHandle, &overlapped, &resultSize, FALSE); // buffer に変更されたファイル名と変更内容が記録されています // 変更検出後の処理をここに記述します } ただ、共有フォルダを対象としたときに変更が検出されるケースとされないケースがあるようです(エクスプローラで共有フォルダの変更が検出できる場合にはこの方法で機能しますが、どのような条件で変更検出が機能しないかはわかりませんでした・・・)。 また、リアルタイム性もそれほど高くありません(変更後数秒かかる場合もあります)。 もし、より正確でリアルタイム性を求めるのでしたら 1. 上記変更検出ルーチンをファイル共有サーバに導入する 2. サーバが変更を検出したらクライアントにデータグラムパケットを送出し、変更検出を通知する。 方法もございます(ここで書いておいて難ですが私はあまり推奨しません・・・) 以上です。 ※ #4 で一点間違えがありました、ごめんなさい!この場で修正させてください。 1. の ZwQueryInformationFile() は ZwQueryObject() の間違いでした(ZwQueryInformationFile() ではドライブ名に該当する部分が取得できません)。 プロトタイプは ypedef enum _OBJECT_INFORMATION_CLASS{ ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectAllInformation, ObjectDataInformation } OBJECT_INFORMATION_CLASS; typedef struct _OBJECT_NAME_INFORMATION { UNICODE_STRING ObjectName; } OBJECT_NAME_INFORMATION; NTSYSAPI NTSTATUS NTAPI ZwQueryObject( IN HANDLE ObjectHandle OPTIONAL, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG Length, OUT PULONG ResultLength ); で、 OBJECT_NAME_INFORMATION* NameInfo; ULONG ResultLength; NTSTATUS status = ZwQueryObject(FileHandle, ObjectNameInformation, NameInfo, NameInfoSize, &ResultLength); のように使います。

参考URL:
http://www.microsoft.com/japan/msdn/library/ja/jpfileio/html/_win32_ReadDirectoryChangesW.asp
すると、全ての回答が全文表示されます。
  • macchun
  • ベストアンサー率50% (3/6)
回答No.5

プログラムから特定のファイルが現在オープンされているか確認するには、非公開 API を使用しなければなりません(openfiles.exe も非公開 API を使用しているようです)。そのため、以下の実装方法については、参考意見として呼んでいただけるようお願いいたします。 あと、長文になることもご了承願います。 1. 特定のファイルを開き、デバイスパス名(フルパスではありません)を取得します。 HANDLE FileHandle = CreateFile(...); DWORD NameInfoSize = 1024; FILE_NAME_INFORMATION* NameInfo; NameInfo = (FILE_NAME_INFORMATION*)malloc(NameInfoSize); IO_STATUS_BLOCK IoStatus; if(NULL == NameInfo) { /*エラー処理*/ } NTSTATUS status = ZwQueryInformationFile(FileHandle, &IoStatus, FileNameInformation, NameInfoSize, NameInfo); if(status < 0) { if(0xC0000004L) { /*NameInfoSizeを大きくして再試行 */ } else { /*エラー処理*/ } } ※ 関数名、構造体にの詳細は検索していただけるようお願います。 2. システム全体で開いているすべてのハンドル情報を取得します。 詳細は参考URLの「ステップ2 ZwQuerySystemInformationによるシステムハンドルの取得」を参照願います。 3. (必要があれば)2. で取得したハンドル情報の一覧から対象プログラムのプロセスIDと同一のもの以外を一覧から削除します。 4. 3. で取得したハンドル情報のデバイスパス名を取得します。そのために、現在のプロセス上でアクセスするためにハンドルを複製します。 詳細は参考URLの「ステップ5 TDI Drivers用...」の下にある「カレントプロセスでのハンドルオープン」を参照願います。 5. 4. で作成したハンドルからデバイスパス名を取得します。やり方は 1. と同様です。 6. 1. で取得した名前と 5. で取得した名前とが同一のものがあるかを確認します。もしあれば、そのファイルは現在オープンされています。 実装方法は以上です。 ただ、実際に上記の内容を実装するのは結構大変だと思いますので、正直 _popen() などで openfiles.exe の出力をパイプで受け取る方法のほうがいいかもしれませんが・・・

参考URL:
http://codezine.jp/a/article.aspx?aid=101
BonRouge
質問者

お礼

回答ありがとうございます。参考にします。 LAN環境(Windowsのワークグループ環境)内でサーバの共有フォルダにあるファイル の新規・変更・削除・更新をリアルタイムに取得できないか?考えていました。 まず、サーバ管理者がサーバ上にあるファイルを操作した場合の情報取得をどうすれば? これはmacchunさんから回答していただいたAPIを参考にテストしてみます。 問題はクライアントからサーバ上の共有フォルダにあるファイルを新規・変更・削除・更新 を行った場合の情報をリアルタイムに取得できないかを今でも考えています。 Windowsネットワーク関係のAPIを使ってテストをしてみましたが、リアルタイムに情報を 取得できませんでした。NetSessionEnum、NetFileEnumなど(Net系のAPI)リアルタイム には使えないAPIでした。Winsock2で対応できるかなと?調べましたがダメでした。 できないはずはないのでこれからも調べてみます。 macchunさん、アドバイスありがとうございます。

すると、全ての回答が全文表示されます。
回答No.4

 API ではないのですが、Windows XP pro には openfiles というコマンドがあって、オープンしているファイルが調べられます。  このコマンドがどの API を使っているのか、Microsoft のサイトで検索してみたのですが、それらしいページを見つけられませんでした。VC++ がインストールされていれば、dumpbin /import コマンドか Dependency walker で openfiles.exe が call している関数を列挙して、それらしいものを探すとか…。  最悪、ランタイム関数の _popen で openfiles.exe の出力をパイプで受け取って処理する、などという手もあるかも知れません。

参考URL:
http://www.atmarkit.co.jp/fwin2k/win2ktips/306openfiles/openfiles.html
BonRouge
質問者

お礼

コマンドで確認ができるのであれば、APIがあっていいはずですよね!? CreateFileの引数をいろいろ試してみましたがダメでした。 なにかAPI(関数)があるのだろうなぁ~ と思います。 MSDNやMicrosoftWebの技術情報を見ても16bit版の情報しかないです。 返答ありがとうございます。

すると、全ての回答が全文表示されます。
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.3

すみません、下記のNo.2を「回答」としてしまいましたが「補足要求」の間違いです。

すると、全ての回答が全文表示されます。
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.2

Win16レベルで、_lopenで確認できるのであれば、それは「排他的利用モードでオープンできるか否か」という方法しかないと思うのですが。 そうではないのであれば、その「MSDNで_lopenで確認するサンプル」ではどのような方法で確認していたのか、補足願います。

すると、全ての回答が全文表示されます。
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.1

「排他的利用モードでオープンできるか否か」という方法で判断するのであれば、CreateFileのdwShareMode引数で共有モード指定を行わないことで排他モード指定とし、エラー発生時にLastError()の内容を確認することで判断できます。

BonRouge
質問者

補足

回答ありがとうございます。 でも、ちょっと意味がちがいます。 他のソフトウェアでオープンされているいるのかのファイルの確認をしたいのです。

すると、全ての回答が全文表示されます。

関連するQ&A