メニュー

メニュー


TIPS

IncludeTrailingPathDelimiter(path);
C:\test → C:\test\
C:\test\ → C:\test\ //最初から区切り文字で終わっていたら何もしない

IdTCPClient1.IOHandler.WriteDirect(StrToBytes(str,1252));

ms:cardinal;

ms := GetTickCount;
何らかの処理
ShowMessage(IntToStr(GetTickCount - ms));

FormのCreateあたりに下記を追加
ReportMemoryLeaksOnShutdown := True

replacedValue := StringReplace(ragetValue, '/','-',[rfReplaceAll]); //'/'を'-'へ変換

Sl.Sorted := true;
  • >この後これを乱すような、挿入、移動操作がエラーにる。追加・削除は可能。
しかも追加の場合、ソートされて適切な位置に納まる。
Sl.Sorted=false の状態でも、項目を Sl.Sort;にできるが、この後追加しても
Sl1.Sorted=false なので追加項目は末端につく。

文字を16進数に変換
IntToHex(Ord(moji),2);

Delete(Src,7,5);
7文字目から5文字分削除する

Delete('ABCDEF',3,2) = 'ABEF' //3文字目から2文字消す

str := 'Hakata';
Delete(str,Length(str)-2,3);//後ろから3文字消す
=> 'Hak'

AnsiLeftStr(str,2); //左端から2文字抜き取る
AnsiRightStr(str,2);
AnsiMidStr(str,2);

AnsiPos('C','ABCDE'); -> 3
AnsiPos('DE','ABCDE'); -> 4
AnsiPos('SGU','ABCDE'); -> 0

AnsiReplace(str,before,after);

uses SysUtils
CreateDirectory //最下層のディレクトリのみ生成
ForceDirectory //必要に応じて親ディレクトリも生成
MkDir

ExtractFilePath(Application.ExeName) = C:\...\...\ 最後は\になる
ディレクトリが存在しない場合は作成する。すでに存在している場合にMkDirを実行するとエラーが発生する
If not DirectoryExists(ExtractFilePath(Application.ExeName) + 'NewFolder\' then //If文丈では最後に\をつける
MkDir('New Folder') // '\New Folder' でも 'New Folder\'でもない

AnsiCompareText(比較文字列A、比較文字列B) = +(A>B), 0(A=B), -(A<B);


文字をASCIIコードにする(10進数)
Byte(s);
Ord(s); <-> chr(c)
IntToHex(Ord(s),1);

IdUDPClient.BoundPort にて自分の送信元ポートを指定することができる。
デザイナ時のポート番号の指定は何を示しているのかは・・・??

フォルダ指定のダイアログボックスを表示する
procedure TForm1.Button3Click(Sender: TObject);
var
 RootFolder   : String;
 SelectFolder : String;
begin
RootFolder   := '';
SelectFolder := '';

if SelectDirectory('フォルダの指定',
                   RootFolder,
                   SelectFolder,
                   [sdNewUI, sdNewFolder, sdShowEdit],
                   Self) then begin
  MessageBox(Handle, PChar(SelectFolder), '選択フォルダ', MB_ICONINFORMATION);
end;
end;


FindFirstChangeNotification API関数は、指定したディレクトリまたは、その配下に対してファイルが作成・更新・削除されると、変更されたことを通知する。どのファイルが変更されたかは通知されない。

ただし、このAPIで通知されるのは「変更の有無」だけであり、どのファイルが変更されたかは通知されない。
変更されたファイルを知り、ファイルの変更をイベントとして扱えるようにするには、上記の変更通知だけでは対応できない。
また、変更通知は、変更があった時点で通知される。いつ、変更が完了したのかは通知からはわからない。
そのため、一定時間待って変化がなくなったときが完了したものとみなす、などの処置が必要になる。
(ログファイル等、ファイルによっては開かれっぱなしのものもあるであろうから、このあたりの判定方法はアプリケーション次第といえる。)

WindowsNT系且つUNICODEビルドである場合にのみ使える方法として、ReadDirectoryChangeW関数がある。
このAPIの利点としては、変更の有無だけでなく、変更されたファイルが通知される、という点にある。
ちょっと注意しなければならないかな、と思う点は、フォルダが削除された場合、当然、フォルダ削除は通知されるが、フォルダの中にいた子も削除されたことは通知されない、という点である。
フォルダが消された場合に、それが保持していた子供も消えたことを認識させるには、やはり事前に一度はスキャンしていなければならない、ということになるだろう。
変更があった時点で通知され、いつ変更が完了したかはわからない、というのはFindFirstChangeNotificationで説明したものと同じであり、検出方法も、同様な方法をとる必要があるものと思われる。
また、MacのSMB共有でファイル通知がうまくされないところをみても、やはりファイル監視系APIではネットワークでの監視、とくに非Windowsマシンへの監視は当てにはできなさそう、という点はFindFirstChangeNotificationのケースと同じであろうことが予想される。
結論として、ReadDirectoryChangeW関数を使ったとしてもFindFirstChangeNotificationを使った場合よりロジックが劇的に簡略化されることはなく、ほぼ同等な処理が必要であり、若干の最適化のメリットがある程度と考えられる。
(ただし監視ファイル数が多い場合は、この最適化が大きなパフォーマンス上の利点を生む可能性はある。)

セキュリティ面の強化を前提に、リムーバルドライブなどの外部装置へのファイル転送を監視したいと考えています。
プログラムは常駐型で、FPDドライブにアクセスがあった際、コピーや削除などの操作をログとして取得していきたいのですが、可能でしょうか?
システム操作なので、Delphiが機能的に一番サポート出来ているのでは?と思っています。
インターネットでも、該当するコーティング事例を探しましたが、見付けられませんでした。
スタテツ 2004/06/29(火) 21:40:00

概略ですが
1.WM_DEVICECHANGEでドライブの挿入検知
2.GetLogicalDrivesで使用可能なドライブを探す
3.FindFirstChangeNotificationでファイルの移動検知
でどうでしょうか?
全てサンプルはネットで入手可能かと思います。
とほほ 2004/07/01(木) 16:05:16

スタテツさん、ありがとうございます。
常駐型の大まかな雛形は出来上がったので、機能的なロジックを始めたのですが、WM_DEVICECHANGEでドライブの挿入検出を実施したところ、CD-ROMの検出は可能ですが、FPDドライブの検出確認は出来ませんでした。(エクスプローラでアクセスしても反応がありませんでした。)
PFDドライブのデバイスから発生するメッセージは、取得が出来ないのでしょうか?
スタテツ 2004/07/01(木) 18:14:26

PFDドライブってUSB接続のメモリースティック等ですよね?
私の方では検出します…
環境はWindowsXP sp1 + Delphi7pro up1です。

ソース
unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   ListBox1: TListBox;
 private
   { Private 宣言 }
 public
   { Public 宣言 }
   procedure WmDevChange(var Mess: TMessage); message WM_DEVICECHANGE;
 end;
var
 Form1: TForm1;

implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.WmDevChange(var Mess: TMessage);
begin
ListBox1.Items.Add(inttostr(Mess.WParam));
end;
end.
とほほ 2004/07/02(金) 10:42:39

すいません、FPDドライブのタイプミスでした。
CD-ROMデバイス、リムーバルデバイス(MO)は検出できたのですが、内蔵タイプのFPD(USB接続ではありません)はエクスプローラからのアクセスでは検出できませんでした。
環境はWindowsNT(WS) SP6a + Delphi6.0 up1(Personal版)です。
提供していただいたソースを実行してみましたが、結果は同じでした。

CD-ROMやMOなどは、媒体挿入時に読み込みされますが、FPDは挿入しただけでは読み込みされないため、そういった制御の違いから、WM_DEVICECHANGEでの検出はできないものなのかと手詰まりです。
スタテツ 2004/07/02(金) 12:17:36

お役に立てず申し訳ないです。
フロッピーディスクアクセスについて色々調べてみましたが、
解決策には至りませんでした。相当難しそうです。

回避としては
1.デバイスマネージャでFDのデバイスを使用不可にしてしまう
2.アプリケーション起動時にFDを挿入しておいてFindFirstChangeNotificationを実行してしまう。
両方穴はありますが…
とほほ 2004/07/02(金) 13:08:27

スタテツさん、色々ありがとうございました。
私も調べてみましたが、こんなに難しいとは思いませんでした。市販の監視ソフトで、FPD監視が出来ない旨がありましたので、それなら作ってやれ!と活き込んだまでは良かったのですが…。
FPDドライブが全く使えないとゆう利便が悪いのもネックになってしまうので…良い運用がないか検討してみます。
スタテツ 2004/07/02(金) 16:12:17

やっと分かりました。
以下のソースをタイマーとかスレッドでまわしてあげれば可能です。

フロッピーディスクが入っているかチェック
procedure TForm1.Button1Click(Sender: TObject);
var EMode: Word;
begin
EMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
  if DiskSize(Ord('A')-$40) <> -1 then
    ShowMessage('Disk in drive A: !')
  else
    ShowMessage('No disk in drive A: !');
finally
  SetErrorMode(EMode);
end;
end;

その他色々
http://delphi.about.com/library/weekly/aa070699.htm
とほほ 2004/07/02(金) 18:07:11

すごいですね、ありがとうございます。
SetErrorModeでFPDアクセス時のコントロールが取得出来れば、検出やアクセスタイミングが図れそうですね。試してみます。ご連絡まで。
PageTop



リンク





タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2016年04月15日 17:01