動作中ロックファイルをつくるNo.13644
じぇいじぇい さん 03/07/07 16:46
 
こんにちは。じぇいじぇいです。

ちらほら見かける例ですが、私もファイルサーバに「ホームディ
レクトリ」を置いて、ほかのパソコンから鶴亀で参照させていま
す。ただ、同時に別々のマシンから鶴亀で参照するとホームディ
レクトリの内容に不具合が出てしまう可能性があるので、下記の
ようなスクリプトをWSH(VBS)で書いて使っています。

やっているのはホームディレクトリにlock.txtというロックファ
イルを作ってから鶴亀を起動し、鶴亀が終了したらロックファイ
ルを消すというだけの処理です。鶴亀を起動する際にロックファ
イルがあるのを見つけると(=ほかのパソコンで鶴亀が立ち上がっ
ているということなので)「強制的に起動するかどうか」聞いて
きます。ロックファイルの中に書いたマシン名と起動時間も表示
してくれるので、遠隔操作で対処するときもやりやすいです。

まあ、こんな感じのことをやっているのですが、こんな適当な処
理でもかまわないので…鶴亀側で実装されることは検討できない
でしょうか。あと「このスクリプトはここを直せばもっとのびる」
というようなお話があればお聞かせいただけると幸いです。VBS
でスクリプトを書くのは初めてなので。

ちなみに、このやり方だと休止状態のときには別途「鶴亀を終了
させて休止状態に入る」スクリプトを書かなければならなかった
りしますが…。鶴亀本体が対応してくれたら「休止状態のときに
はホームディレクトリの占有状況を解除する(現状をすべて書き
出す。復帰時には再読み込みする)」ようなこともできるんじゃ
ないかと淡い期待をもっていたります。

========= ロックファイルを作って鶴亀起動する.vbs
Option Explicit

Dim WShell, FS, oEnv,_
sProg, sArgs, sDocDir, sDocOpt, sMacName,_
iRet,_
fsDocDir, fsLock, tsLock, sCont,_
exeTurukame
Set WShell = WScript.CreateObject( "WScript.Shell" )
Set FS = WScript.CreateObject( "Scripting.FileSystemObject" )

' ----- 鶴亀のパスを取得する(半自動)
Set oEnv = WShell.Environment( "process" )
sProg = oEnv.Item( "PROGRAMFILES" )  + "\turukame\turukame.exe"
'Windows 9x系で動作するかどうかは不明
sMacName = oEnv.Item( "COMPUTERNAME" )

' ----- 引数
Set sArgs = WScript.Arguments
sDocDir = ""
sDocOpt = ""
if sArgs.Count > 0 then
sDocDir = sArgs( 0 )
sDocOpt = " /d """ +_
sDocDir +_
""""
If not FS.FolderExists( sDocDir ) then
MsgBox "指定フォルダ: " + sDocDir + "がありません"
WScript.Quit 1
End If
If FS.FileExists( sDocDir + "\lock.txt" ) then
Set fsLock = FS.GetFile( sDocDir + "\lock.txt" )
Set tsLock = fsLock.OpenAsTextStream( 1 )
On Error Resume Next
sCont = tsLock.ReadLine + vbcrlf
On Error Resume Next
sCont = sCont + tsLock.ReadLine
tsLock.Close
iRet = MsgBox( _
"すでに鶴亀が起動しています。" + vbcrlf +_
"強制起動しますか?" + vbcrlf +_
sCont,_
vbYesNo + vbExclamation _
)
If iRet = vbNo Then
WScript.Quit 1
Else
On Error Resume Next
FS.DeleteFile sDocDir + "\lock.txt"
End If
End If
Set fsLock = FS.CreateTextFile( sDocDir + "\lock.txt" )
fsLock.WriteLine sMacName
fsLock.WriteLine Now
fsLock.Close
End If

' ----- アプリケーションを起動
'終了まで待機
Set exeTurukame = WShell.Exec( """" + sProg + """" + sDocOpt )
While exeTurukame.Status = 0
WScript.Sleep 100
Wend

' ----- ロックファイル削除
On Error Resume Next
FS.DeleteFile sDocDir + "\lock.txt"
If Err Then
MsgBox "ロックファイルが削除できませんでした"
End If



========= 鶴亀を終了させて休止状態へ.vbs
Dim WShell
Set WShell = WScript.CreateObject("WScript.Shell")

' ----- アプリケーションを終了
WShell.AppActivate("鶴亀メール")
WShell.Sendkeys("%{F4}")

' ----- 休止状態
WShell.RegWrite _
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shutdown Setting", _
64 ,"REG_DWORD"
'            一部環境でうまく動かず
WShell.SendKeys "^{ESC}U{ENTER}"

[ ]
RE:13644 動作中ロックファイルをつくるNo.13654
秀まるお2 さん 03/07/08 16:09
 
 アイデア提供ありがとうございます。たしかにlock.txtのようなファイルを使
って共有違反を見つけるしかなさそうです。

 標準装備するためにはもうちょっと仕様検討なり矛盾の発見なりをしないとい
けないと思うので、しばらく保留させていただきます。

[ ]
RE:13644 動作中ロックファイルをつくるNo.13669
アルビレオ さん 03/07/09 07:08
 
アルビレオです。

>ちらほら見かける例ですが、私もファイルサーバに「ホームディ
>レクトリ」を置いて、ほかのパソコンから鶴亀で参照させていま
>す。ただ、同時に別々のマシンから鶴亀で参照するとホームディ
>レクトリの内容に不具合が出てしまう可能性があるので、下記の
>ようなスクリプトをWSH(VBS)で書いて使っています。

すばらしい!
ただひとつ気になる点があります。
自分では考えつかなかったアイディアに対して重箱の隅をつつくような指摘で申
し訳ないですが、より安全な方法を提案するということで。

<略>
If FS.FileExists( sDocDir + "\lock.txt" ) then
 <ロックされていた場合の処理>
End If
Set fsLock = FS.CreateTextFile( sDocDir + "\lock.txt" )
<略>

このようにロックされているかのチェックと実際のロック操作が分かれていると、
チェックしたときは lock.txt が存在しなかったのに、その後ファイルを作成し
ようとするとすでに別のプロセスによって lock.txt が作成された後だったとい
うことが起こる可能性があります。

幸い CreateTextFile を overwrite 引数なしで実行するとファイルが存在した
らエラーを返すようなので、いきなり CreateTextFile を実行してエラーとなっ
た場合に「ロックされていた」とみなして処理を行なった方がいいでしょう。
VBS についてはよくわかっていないので具体的なコードは省略します。

鶴亀で排他制御を行なう場合も「存在チェックしてからロックファイル作成」で
はなく「ロックファイルを作成しようとしたらすでに存在していた」場合に他の
鶴亀で使用中だと判断するようにした方がよいと考えます。

[ ]
RE:13654 動作中ロックファイルをつくるNo.13670
アルビレオ さん 03/07/09 07:08
 
アルビレオです。

> 標準装備するためにはもうちょっと仕様検討なり矛盾の発見なりをしないとい
>けないと思うので、しばらく保留させていただきます。

これを実現するならちょうどいい機会なので「閲覧モード」を作ることを提案し
ます。
メールの送信/受信/移動/削除/改変などができないようにして、ホームディレク
トリに対する変更を一切禁止するモードです。

・他の鶴亀で使用中のディレクトリでも閲覧だけは可能にできる。
他の鶴亀でメールを移動/削除したときなどに矛盾が出る恐れがありま
すが、通常モード側の鶴亀で状態変化が発生したらロックファイルに書
き込みを行なうようにすれば、ロックファイルのタイムスタンプを調べ
ることで以前のタイムスタンプと比較して更新を検出できると思います。
マシンによっては時刻がずれている可能性があるので現在時刻との比較
で判定しない方が安全です。
・共有フォルダがリードオンリーでも閲覧だけは可能になる。
・CD-ROM などにバックアップしたメールデータの閲覧もできる。

という具合にいろいろと有用な機能だと思うのですが。

あくまで排他制御を実装するのついで、あるいは排他制御を実現するためのワン
ステップとして先に実装するという提案で、個人的にはぜひとも実現して欲しい
というわけでもありませんが、ネットワーク越しにホームディレクトリの共有を
可能にする比較的簡単な手法ではないかと思います。

[ ]
RE:13669 動作中ロックファイルをつくるNo.13672
秀まるお2 さん 03/07/09 09:29
 
 もうちょっと考えたら、別にlock.txtのファイル有無で排他制御するよりも、
いわゆる「ファイルのオープンしっぱなしによる排他制御」の方が確実なようで
す。別にネットワーク経由であってもその程度の排他制御は効きますので。

 あと、しいてやるなら「閲覧モード」のような形は必要というか、つまりは閲
覧モードにするかどうかのために排他制御をするってことになるとは思います。

 閲覧モードであっても、閲覧モードじゃない方の鶴亀がファイルを書き換えた
らそれを閲覧モード側の鶴亀が感知しないといけないです。そのような処理はか
なり面倒です。

 となると、やはり実現は容易でないです。当分保留させていただきます。

[ ]
RE:13672 動作中ロックファイルをつくるNo.13713
じぇいじぇい さん 03/07/09 22:16
 
じぇいじぇいです。

アルビレオさん。こんにちは。
>このようにロックされているかのチェックと実際のロック操作が分かれ
>ていると、チェックしたときは lock.txt が存在しなかったのに、その
>後ファイルを作成しようとするとすでに別のプロセスによって lock.txt
>が作成された後だったということが起こる可能性があります。

するどい突っ込みありがとうございます。
直しました。最後につけておきます。
vbsのCreateTextFileはoverwriteありがdefaultみたいだったので
ちょっと悩みましたが…。

とはいいつつ、厳密に考えると「CreateTextFileはatomicなのか」
とかいうあたりも気になるのかもしれない…。そこまで保証できな
いスクリプトということで_o_

ちなみに、lock.txtの内容を数ミリ秒おきに見に行って、ほかのマ
シンから「おまえは終了しろ」という要求が書き込まれていたら鶴
亀を強制終了するという機能を追加しようかと考えていますが、そ
こまでして果たして意味があるのかというとちょっと疑問が残りま
すね(笑)。


秀まるおさん、こんばんは。
>もうちょっと考えたら、別にlock.txtのファイル有無で排他制御する
>よりも、いわゆる「ファイルのオープンしっぱなしによる排他制御」
>の方が確実なようです。別にネットワーク経由であってもその程度の
>排他制御は効きますので。

鶴亀本体で対応される場合はそのほうがよいでしょうね。

閲覧モードというのは、たとえばCD-ROM上に鶴亀のメールボックスを
置いて閲覧するなどの目的に使えておもしろそうですが、実現は難し
いんじゃないですかね。

> 閲覧モードであっても、閲覧モードじゃない方の鶴亀がファイルを
>書き換えたらそれを閲覧モード側の鶴亀が感知しないといけないです。
>そのような処理はかなり面倒です。
>
>となると、やはり実現は容易でないです。当分保留させていただきます。

ひーん。閲覧モードは要らないから実現できるとよいなあ…。
起動警告ができるだけでずいぶん使い道が広がると思いますよ。
まあ、保留でも記憶にとどめておいていただければ。

========= ロックファイルを作って鶴亀起動する・改.vbs
Option Explicit

Dim WShell, FS, oEnv,_
sProg, sArgs, sDocDir, sDocOpt, sMacName,_
iRet,_
fsDocDir, fsLock, tsLock, sCont,_
exeTurukame
Set WShell = WScript.CreateObject( "WScript.Shell" )
Set FS = WScript.CreateObject( "Scripting.FileSystemObject" )

' ----- 鶴亀のパスを取得する(半自動)
Set oEnv = WShell.Environment( "process" )
sProg = oEnv.Item( "PROGRAMFILES" )  + "\turukame\turukame.exe"
'Windows 9x系で動作するかどうかは不明
sMacName = oEnv.Item( "COMPUTERNAME" )

' ----- 引数
Set sArgs = WScript.Arguments
sDocDir = ""
sDocOpt = ""
if sArgs.Count > 0 then
sDocDir = sArgs( 0 )
sDocOpt = " /d """ +_
sDocDir +_
""""
If not FS.FolderExists( sDocDir ) then
MsgBox "指定フォルダ: " + sDocDir + "がありません"
WScript.Quit 1
End If
On Error Resume Next
Set fsLock = FS.CreateTextFile( sDocDir + "\lock.txt", False )
If Err.Number <> 0 then
Set fsLock = FS.GetFile( sDocDir + "\lock.txt" )
Set tsLock = fsLock.OpenAsTextStream( 1 )
On Error Resume Next
sCont = tsLock.ReadLine + vbcrlf
On Error Resume Next
sCont = sCont + tsLock.ReadLine
tsLock.Close
iRet = MsgBox( _
"すでに鶴亀が起動しています。" + vbcrlf +_
"強制起動しますか?" + vbcrlf +_
sCont,_
vbYesNo + vbExclamation _
)
If iRet = vbNo Then
WScript.Quit 1
Else
On Error Resume Next
FS.DeleteFile sDocDir + "\lock.txt"
End If
Else
fsLock.WriteLine sMacName
fsLock.WriteLine Now
fsLock.Close
End If
End If

' ----- アプリケーションを起動
'終了まで待機
Set exeTurukame = WShell.Exec( """" + sProg + """" + sDocOpt )
While exeTurukame.Status = 0
WScript.Sleep 100
Wend

' ----- ロックファイル削除
On Error Resume Next
FS.DeleteFile sDocDir + "\lock.txt"
If Err Then
MsgBox "ロックファイルが削除できませんでした"
End If

[ ]