ページ 11

他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 13:11
by どぶろく
Win32APIプログラムでの質問です。
ファイルをオープンする時、他のソフトがすでにそのファイルをオープンしている場合、警告のメッセージを出したいのですが、どうすれば良いのでしょうか?
他のソフトが共有を許している場合も警告のメッセージを出したいのですが。
簡単に言えば、ファイルがすでにオープンされているかどうかが分かればいいのですが。
よろしくお願いします。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 13:28
by h2so5
http://stackoverflow.com/questions/1951 ... ocess-in-c

ファイルをを排他モードでオープンできるかどうかで検証する方法が紹介されています。
試してないですけど、 MSDNを見る限りだと _fsopen( "outfile", "r+", _SH_DENYRW ); でチェックできそうです。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 13:48
by Tatu
「C ファイルがオープンされているかを調べる」で検索してみたところ

[SDK32]既にファイルがオープンされているかの確認方法
http://support.microsoft.com/kb/172240/ja
というページがありました。

ここに書かれていることを試してみてはどうでしょうか?

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 19:43
by どぶろく
h2so5様、Tatu様、解答ありがとうございます。
お二人のやり方を試したところ最初は成功しませんでした。掲載サイトを見ると間違いのない説明なので何で成功しないのか悩んでしまいました。
そして考えてみたらファイルって普通オープンにしたままにしないのではないか!ということでした。
試しにファイルをオープンにしたままのプログラムを作ったところ、お二人のやり方で成功しました。
しかし困ってしまいました。ファイルを使っているかどうか調べる手だてが無くなってしまいました。
何か方法はあるのでしょうか?

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 19:50
by h2so5
普通はファイルをオープンしていないということは使用していないことと同義だと思うのです。
そうでないならば、「ファイルを使っている」という状態の定義を説明してください。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 20:33
by どぶろく
具体的な使用状況は、テキストエディタでファイルを開いている時、そのファイルを別のソフトで加工できないようにしたいわけです。現状ではテキストエディタが開いて編集しているファイルを簡単に加工出来てしまいます。
別のソフトというのは、大したことないのですが、タブをスペースに変えて、ブランクスペースも削除するというものです。
このソフトを良くテキストエディタで編集しているファイルに対して実行してしまうので、警告を出したいわけです。
「ファイルを使っている」というのは「テキストエディタで編集している」ということです。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 22:13
by h2so5
その場合は逆に排他的にファイルをオープンできるテキストエディタを使うようにしたほうが良いと思います。

特定のエディタに限定するなら、なんとかしてアプリケーションの状態から判断することもできなくはないとは思いますが、
一般的に「テキストエディタで編集している」かどうかは作業している人間にしか分かりません。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 23:32
by softya(ソフト屋)
ファイルをオープンしたままにしないエディタを検出することは不可能だと思います。
リソースを使っていないのでOSでも検出できません。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月09日(金) 23:42
by みけCAT
あえてやるなら、ウィンドウのタイトルを見ていって、対象のファイル名が含まれているかで判定、でしょうか?
別ディレクトリのファイルなどの誤検知が起こりそうですが。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月10日(土) 00:19
by softya(ソフト屋)
検知できないと言う前提に立って考えると、自分の管理しているファイルは正副の2つを作って整合性が取れなかったら問い合わせると言う手もありますね。【修正】

【追記】
あと、マクロが使えるエディタならマーキングテンポラリファイルを作るという手もあります。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月10日(土) 01:47
by y_wing
私の考えでは
ファイルをオープンする時、まず0.txt(任意のファイル,0.TXTは一例です)を検出する。
0.txtがないならファイルのフォルダに0.txtをつくります。
0.txtがあるならすでにこのファイルが開いているを示します。
ファイルを閉じる時、0.txtを削除すること。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月10日(土) 07:26
by どぶろく
皆さま、解答ありがとうございます。どうやら難しいようですね。
softya 様、お久しゅうございます。さっそく、正副の2つのファイルを作るというのが分かりません。
y_wing 様の考えはエディタ側でそのファイルを作るということでしょうか。

エディタはフリーの VxEdtor を使っています。プログラムの作成ではなく文書作成に使っています。
このエディタは編集中のファイルを監視していてファイルが変更されると「再読み込みしますか」とメッセージを出します。これはかなり安全な仕様ですが、それでも編集中のファイルをまだ保存してないときなどパニクってしまいます。

プログラムは、VC++2008 も使いますが、ほとんど、BCC Developer で行なっています、BCC Developer はファイルを変更されても何のメッセージも出さないので困りものです。


■マクロ機能について

BCC Developer では DMonkey 0.3.5 を使用しています。

VxEdtorも DMonkey です。

これを使えばマーキングテンポラリファイルなるものが作れるのでしょうか?


◆VxEdtorでの説明、柔軟なスクリプト言語

JavaScriptとほぼ互換のインタプリタを搭載し、標準にない機能を容易につけ加えることができます。
スクリプト言語は JavaScript とほぼ互換の DMonkey を搭載しています。
Irvine(ダウンロードソフト)に搭載されているものと同じものです。
標準仕様はそちらのドキュメントや、参考書などを見てもらうとして、VxEditorで追加された機能を説明します。VxEditorでは2つのオブジェクトが追加されています。

◆Editorオブジェクト

・WindowNo ウィンドウ番号の取得/設定
・Row 行位置の取得/設定
・Col 桁位置の取得/設定
・TopRow 画面の一番上の行位置の取得/設定
・TopCol 画面の一番左の桁位置の取得/設定
・Text 編集テキストの取得/設定

以下追加機能の羅列なので省略

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月10日(土) 10:43
by softya(ソフト屋)
やっと全容が分かった訳ですが、そもそも外部ツールでタブ→空白変換しているのが敗因と思えて来ました。VxEdtor でタブ→空白変換出来なんでしょうか?
それか別フォルダにタブ→空白変換したファイルを転送するかです。同時に同じファイルを変更するという可能性を無くせば問題も解決します。
同時更新は、例えばプログラムの設計でも危険度が高い設計なので避けれるなら避けるのが普通選ぶべき道です。

【補足】
言うなれば同じ場所のメモリを同時更新するメインとサブスレッドの様なものです。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月10日(土) 18:09
by どぶろく
自分で作成するファイルはエディタでタブ→空白変換の設定をしているので問題ないのですが、
他人のソースファイルを見たり利用するときタブ→空白変換のツールを使います。
他人の作ったファイルにはタブやブランクスペースがいっぱいあるのでこのツールを実行すると気持ちがいいのです(タブの数や、削除したスペースの数が表示されるので)。

なるほど、別フォルダに保存するか、名前を少し変えて保存したりすればいいんですね。
今のままでは危険すぎることがよくわかりました。まずは専用ホルダに保存するようにしてみます。
ありがとうございました。勉強になりました。

Re: 他でファイルがすでにオープンされているかどうか

Posted: 2013年8月11日(日) 02:43
by y_wing
実はFindWindow関数が一番楽だと思います。