HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2012
0214
HK2existで使用中のファイルのサイズが調べられない仕様か否や12解決


HK2

リンク

2012/2/14(Tue) 18:47:01|NO.44868

ある、圧縮解凍ソフトでCドライブ以外のパーティションを保存先に設定すると
一時保存先から本命の保存先への移動に時間がかかり少し不便です

で、出力中のファイルのサイズを調べるためにexist命令を使用しようとしました

出力中も、エクスプローラーからは確認できるのですがexistは-1をかえします
これはエクスプローラーが特殊なのでしょうか
それともexist命令は更新の激しいファイルのサイズを調べることができない仕様なのでしょうか
もし後者ならそのようにしたのはなぜでしょうか



この記事に返信する


MillkeyWeler

リンク

2012/2/14(Tue) 21:27:40|NO.44873

エクスプローラーではなくて、ファイルAPI上の仕様です。
圧縮解凍ソフトが、操作中のファイルに対して、アクセス拒否(自身以外がアクセスするのを一切拒否)をしている為であるので
hsp の exist は -1 を返します。



HK2

リンク

2012/2/14(Tue) 23:58:22|NO.44875

ではなぜ、エクスプローラーはファイルのサイズを取得できるのでしょうか。
APIがエクスプローラーにだけ特別に取得できるようにしているからなのでしょうか。



MillkeyWeler

リンク

2012/2/15(Wed) 07:18:20|NO.44876

どーなんだろう。
排他制御されているファイルに対して、確実で取得できるAPIを知らないからなんともいえないけど。

うちが試したのは、Kernel32.dll 関数 FindFirstFile だから。
それでもファイルサイズの取得はできなくて、エクスプローラー上の表示はしっかりと出ていた・・・

質問者さんごめん。うちはギブアップだ。
WinAPI に詳しい人などがいれば、排他制御 されているファイルでも正しくサイズが取得できる方法を教えてくれるかも。



XBG|YAMANOTE231103(携帯端末)

リンク

2012/2/15(Wed) 23:39:10|NO.44895

マルチスレッド、というのが一番近い答えではないでしょうか。

http://msdn.microsoft.com/ja-jp/library/172d2hhw



check

リンク

2012/2/16(Thu) 00:00:39|NO.44896

なぜXBG氏が「マルチスレッド」という案を
MSDNのリンクとともに出したのかは意図が読みかねる。

ファイルロックをはずす方法ならいくつか検索して出てきたが、
最終的にはCloseHandleでハンドルを閉じてしまっていた。
これではプログラムが暴走しかねんな。



pizza

リンク

2012/2/16(Thu) 15:36:16|NO.44899

FileSystemObjectのFileオブジェクトは使えませんか?


path = "" //パス newcom fso, "Scripting.FileSystemObject" if varuse(fso) { file = fso("GetFile", path) if varuse(file) { mes file("Size") delcom file } delcom fso }



pizza

リンク

2012/2/17(Fri) 12:56:52|NO.44907

これも使えそう。


#include "kernel32.as" path = "" dim fad, 9 GetFileAttributesEx path, 0, varptr(fad) mes "nFileSizeHigh="+fad.7 mes "nFileSizeLow="+fad.8



shiva

リンク

2012/2/17(Fri) 19:25:01|NO.44911

そもそもWindowsの仕様としては、
 ・アクセス権を持っている
 ・適切な方法を使用する
の条件が揃えば、たとえファイルがロックされていても、メタ情報を取得できるようになっているようです。
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx の dwDesiredAccess の解説を参照)

以下は実装の話になります。
exist命令はdpmread.cppのdpm_exist関数で実装されていますが、この関数の何がよくないかというと、
 ・不要なアクセス権を要求している
 ・厳密にはC言語の規格に違反している(参考:http://www.jpcert.or.jp/sc-rules/c-fio19-c.html
という点です。
なので、これはランタイムを修正したほうがよさそうです。



check

リンク

2012/2/17(Fri) 19:54:35|NO.44912

そもそもファイルの有無を調べる関数で、
ファイルのサイズを取得するっていうのもおかしな実装だと俺は思うが。

exist関数の件はおにたま氏と相談して、適切なアクセス方法で
ファイルの情報を取得できるようにランタイムを修正してもらえればいいのでは。


ちなみに、shiva氏の提示した、fseekとftellでファイルサイズを取得する方法が
間違っているという事実は俺もC++をやり始めて3年以上してから始めて知った。

CRT自体も古いライブラリだから、いろいろと問題があったりとかするしな。



HK2

リンク

2012/2/17(Fri) 23:33:02|NO.44913

XBG|YAMANOTE231103(携帯端末)さん
私の理解力不足で、マルチスレッドからつながっていくものがありませんでした。
もう少し掘り進めて説明していただけますでしょうか。


pizzaさん
二つの例を挙げていただき、ありがとうございます。
どちらの方法も圧縮解凍ソフトが異なるパーティションへの移動処理をしている最中も
ファイルサイズを調べ続けることに成功しました。
リアルタイム性がよかったので、
GetFileAttributesExを使った方をそのまま使わせていただきました。


shivaさん
英語のリンク先を読ませていただきました。
そこで疑問に思ったのですが、リンク先では、
「GENERIC_READアクセス権の取得を拒否されても、ある種のメタ情報を照会できる」
とあるのですが、ある種のメタ情報にファイルサイズは含まれているのでしょうか。
それとも、私のこの解釈は間違っているのでしょうか。
もし、この解釈が正しく、ファイルサイズがある種のメタ情報に含まれるなら、
CreateFileが返した
GENERIC_READアクセス権やGENERIC_WRITEアクセス権を持たないハンドル
を用いてファイルサイズを取得する関数はどのようなものがあるのでしょうか。


shivaさんの
>厳密にはC言語の規格に違反している
と、checkさんの
>CRT自体も古いライブラリだから、いろいろと問題があったりとかするしな。
というところから思ったのですが、
exist命令の実行は安全なのでしょうか。



shiva

リンク

2012/2/20(Mon) 00:56:52|NO.44983

>HK2 さん
・「ある種のメタ情報」にファイルサイズは含まれるか
確信は持てませんが、

  前述の MSDN に "certain metadata such as file, directory, or device attributes" とある
 →ファイル属性を取得する GetFileAttributesEx で得られる情報=ある種のメタ情報
 →pizza さんのスクリプトにもあるように nFileSize(Low/High) がある

ということで、おそらく含まれているのだと思います。

・GENERIC_* アクセス権のないハンドルからファイルサイズを取得する関数
通常と同じはずです(つまり GetFileSize(Ex) や GetFileInformationByHandle など)。
しかし、GetFileSizeEx のドキュメントを見ると「GENERIC_READ か GENERIC_WRITE、あるいは同等のアクセス権」を
持ったハンドルが必要とも書いてあり、正確なところはわかりません。
手元 (XP SP3) で試すと dwDesiredAccess == 0 のハンドルでも問題なく取得できているのですが。

・exist 命令の安全性
今のままだと使用する CRT によりますが、公式配布の Windows 向けランタイムについていえば
問題は多分ないでしょう(今回の件を除く)。
このランタイムの CRT (VC++) は fseek で SetFilePointer を使用していますが、
この関数のリファレンスを見ると、ファイルサイズを調べるのに使えると書いてあるからです。
(余計なミスを防ぐため GetFileSize を使うように、ともありますが)

>check さん
後で報告を出しておこうと思います。
何も知らずに CRT でファイルサイズを調べようとすると、同じようなコードを書きたくなりますよね……。



HK2

リンク

2012/3/6(Tue) 19:05:16|NO.45248

CreateFileAでGENERIC_READ[WRITE]無しに開いたハンドルを
GetFileSize関数に渡してもファイルサイズを取得できるとは思いませんでしたので、
試していませんでした。
MSDNにGENERIC_READ[WRITE]権を持っている必要があると書いていたので、
できないものだと思っていました。


今回のスレッドの当初の質問の答えは次のように理解しました。
>これはエクスプローラーが特殊なのでしょうか
→そんなことはない。
>それともexist命令は更新の激しいファイルのサイズを調べることができない仕様なのでしょうか
→仕様ではなさそう。
>もし後者ならそのようにしたのはなぜでしょうか
→前の質問が偽なので、答え無し。


今回のスレッドを通して、exist命令のことよりも、
APIを使うときは英語の解説を読むとより良い情報がある、
解説と実際の場合では違うことがないではない、
ということの方を学ぶことができました。
今まではできるだけ避けてきましたが、
これからは英語でも読んでいきたいと思います。


回答してくださった皆さん、このスレッドを読んでいただいた皆さん、
書き込んではいないけど、このスレッドに関して考えていただいた皆さん。
ありがとうございました。

また、質問することがあるかもしれませんが、その時もよろしくお願いします。



ONION software Copyright 1997-2023(c) All rights reserved.