[BlueLeaf1336]> PROGRAM>

ゴミフォルダ

historyTOP

2005/06/19:作成

overviewTOP

Windows2000を使っていますが、時々掃除してやるとすっきりするフォルダがあります。たとえばWindows標準の一時フォルダとか。実際は、「コピーしたんなら後始末しとけよ」と自分が使うときには気にもしないくせに、人には厳しく突っ込んでしまうわけですが。

このページでは、そんな風な中身をズバッと消しても問題ないはずのフォルダのパスを取得する方法を試します。実際にそのフォルダの中身を消すかどうかは、また、消してもよいかどうかは知りません。将来自分で消したくなったときのために、パスの取得方法だけでも書き留めておこうと思うわけです。

特殊フォルダの取得TOP

まず、そういったフォルダはほとんどが特殊フォルダとしてWindowsも特別扱いしています。ですので、それなりに取得する方法があります。現在は閉鎖されきってますが、「Delphi壁の穴」というサイトで紹介されていた関数を(自分なりに整形した記憶がないのでおそらくそのまま)紹介します。この関数を使うとほとんど今回のページで紹介しようとしているゴミフォルダを網羅してしまうんですが...

ちなみに、コメント内のURLはリンク切れです。

uses
  Windows, Forms, ShlObj;

//-----------------------------------------------------------------------------
//  特殊フォルダ
//  http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#ishelllink
function GetSpecialFolderPath(const Folder: integer): string;
var
    pidlPath: PItemIDList;
    SpecialPath: array[0..MAX_PATH] of Char;
begin
    SHGetSpecialFolderLocation(Application.Handle, Folder, pidlPath);
    SHGetPathFromIDList(pidlPath, Special);
    Result := Special;
end;

最近使ったファイルTOP

まず手始めに、「最近使ったファイル」です。2回目ですがWindows2000です。NTやXPでどうなるかは興味ありません。で、Windows2000ではユーザー別にそういうフォルダを管理しているので、Administratorで普段使っている今の環境では「C:¥Documents and Settings¥Administrator¥Recent」が戻ります。

procedure TForm1.Button1Click(Sender: TObject);
begin
    ShowMessage(GetSpecialFolderPath(CSIDL_RECENT));
end;

インターネットキャッシュTOP

次に「インターネットキャッシュ」フォルダです。通常は、なんかえらく深いところにありますが、気持悪いのでデスクトップのIEアイコンのプロパティで変更しています。当然ですが、ここではその変更後のフォルダパスを取得できます。

procedure TForm1.Button1Click(Sender: TObject);
begin
    ShowMessage(GetSpecialFolderPath(CSIDL_INTERNET_CACHE));
end;

クッキーTOP

次にクッキーです。またもやインターネット関係ですが、定義済みですので仕方がありません。前述の関数を使って取得できるゴミフォルダを列挙しているだけですので。

procedure TForm1.Button1Click(Sender: TObject);
begin
    ShowMessage(GetSpecialFolderPath(CSIDL_COOKIES));
end;

履歴TOP

またもやですが、次は履歴フォルダです。なんか、クッキーとか履歴とかキャッシュとか置き場所がバラバラで気持が悪いです。

procedure TForm1.Button1Click(Sender: TObject);
begin
    ShowMessage(GetSpecialFolderPath(CSIDL_HISTORY));
end;

ユーザー環境変数の取得TOP

さて、先ほどの便利関数のことは忘れて、次に進みます。今度は一時フォルダの取得に進みます。ところで、TEMPフォルダには(多分)2種類あって、一つはシステム全体のもの、もう一つはAdministratorなどのログオンユーザー用のものです。ここでは、ログオンユーザー用のものを取得します。

その前に、GetEnvironmentVariableという関数があることを確認しておきます。

//-----------------------------------------------------------------------------
//  環境変数の取得
//  http://dmj.psnet.ne.jp/mn/?NO=53
function GetEnvironmentVariable(const s: string): string;
const
    BUF_SIZE = 8192;
begin
    SetLength(Result, BUF_SIZE);
    SetLength(Result, Windows.GetEnvironmentVariable(PChar(s), PChar(Result), BUF_SIZE))
end;

これは、デスクトップのマイコンピュータのプロパティで確認できる環境変数を取得するための関数です。ただし、TEMPフォルダのようにログオンユーザーとシステム全体の両方でかぶっている環境変数名がある場合は、どうもログオンユーザーの値が優先されるような気がします。以降では、「ログオンユーザー用の」という意味で「ユーザー...」という言葉を使います。

ユーザー一時フォルダTOP

そのままです。ただし、パスが深すぎるのか省略した形でパスが戻されます。どこかに長いパスに変換する方法があったような気がします。また、「TEMP」も「TMP」も戻ってくる答えが同じ、つまり同じパスを指しているようなんですが念のため。

procedure TForm1.Button1Click(Sender: TObject);
begin
    ShowMessage(GetEnvironmentVariable('TEMP'));
    ShowMessage(GetEnvironmentVariable('TMP'));
end;

システム一時フォルダTOP

システム全体での一時フォルダ(たいていは「C:¥WINNT¥Temp」だと思います)のパスを取得します。今度は少しややこしくなります。というのは前述の環境変数取得関数を使うと、ユーザー一時フォルダが戻ってきてしまうからです。これはシステム環境変数でも同じように「TEMP」「TMP」という名称が使用されているからだと思いますが、そのために(多分)レジストリを読まなければならない羽目に。

ただ、レジストリを直接読むと、たとえば「TEMP」フォルダが「%SystemRoot%¥Temp」なんて感じで得られてしまいます。じゃぁ「%SystemRoot%」ってなんどい、という問題が出てきてそれを求めて...というのをやってる関数です。

uses
    Registry;

//-----------------------------------------------------------------------------
//  システム一時フォルダ取得
procedure GetSystemTempPath(var Temp, Tmp: string);
const
    SYS_ENV = '\SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
var
    Reg: TRegistry;
    SysRoot, WinDir: string;
begin
    WinDir := '';
    Temp   := '';
    Tmp    := '';

    //  システム環境設定を直接読み取る(実際のパスではない)
    Reg := nil;
    try
        try
            Reg := TRegistry.Create;
            Reg.RootKey := HKEY_LOCAL_MACHINE;
            if Reg.OpenKey(SYS_ENV, False) then
            begin
                //  システムディレクトリ(%SystemRoot%)
                WinDir := Reg.ReadString('windir');
                //  システムTEMPパス(%SystemRoot%...)
                Temp   := Reg.ReadString('Temp');
                //  システムTMPパス(%SystemRoot%...)
                Tmp    := Reg.ReadString('Tmp');
                Reg.CloseKey;
            end;
        finally
            FreeAndNil(Reg);
        end;
    except
        ;
    end;

    //  実際のシステムルートを取得して
    SysRoot := GetEnvironmentVariable('windir');

    //  パスを正しく置き換える
    Temp := StringReplace(Temp, WinDir, SysRoot, [rfIgnoreCase]);
    Tmp  := StringReplace(Tmp, WinDir, SysRoot, [rfIgnoreCase]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    Temp, Tmp: string;
begin
    GetSystemTempPath(Temp, Tmp);
    ShowMessage(Temp + #13#10 + Tmp);
end;

ワトソン博士の使うフォルダTOP

最後が、ワトソン博士の使うフォルダです。調子の悪いプログラムを使っていて何かのひょうしにワトソン博士が出現することがあります。このとき、素人には全くもって役に立たないログファイルとかダンプファイルを出力してくれます。根本的に個人ユースでは、そんなプログラムは使わないでいよう、とかOS入れなおそうかなんてことが比較的容易なため、ワトソン博士に教えてもらうことはありません、と信じています。ですので、ここではゴミフォルダの一つに認定しています。

ワトソン博士の使っているフォルダってどこよ? を調べてみるためにはワトソン博士の設定画面を見る必要があります。でもアクセサリにもいないようですので、「C:¥WINNT¥system32¥DRWTSN32.EXE」から直接起動してみることにします。

書いてありました。それにヘルプを確認してみると、既定値以外に設定した場合の記録場所(レジストリのパス)についても説明がありました。でもヘルプの既定値と実際の既定値が異なっているような気がしますが...

それからログについてはフォルダですが、ダンプについてはファイル名まで指定のような気がします。最近ダンプファイル吐かれてないし、設定したところでダンプファイルを任意のタイミングで吐くこともできないので未確認ですが。

//-----------------------------------------------------------------------------
//  ワトソン博士の使用するフォルダ取得
procedure GetWatsonPath(var Log, Dmp: string);
const
    DR_ENV = '\SOFTWARE\Microsoft\DrWatson';
    LOG_DEF = '\Documents and Settings\All Users\Documents\DrWatson';
    DMP_DEF = '\Documents and Settings\All Users\Documents\DrWatson\user.dmp';
var
    Reg: TRegistry;
    SysDrive: string;
begin
    Log := '';
    Dmp := '';

    //  ワトソン博士の設定を読み取る
    Reg := nil;
    try
        try
            Reg := TRegistry.Create;
            Reg.RootKey := HKEY_LOCAL_MACHINE;
            if Reg.OpenKey(DR_ENV, False) then
            begin
                Log := Reg.ReadString('LogFilePath');
                Dmp := Reg.ReadString('CrashDumpFile');
                Reg.CloseKey;
            end;
        finally
            FreeAndNil(Reg);
        end;
    except
        ;
    end;

    //  システムドライブ取得
    SysDrive := ExtractFileDrive(GetEnvironmentVariable('WINDIR'));

    //  既定値使用なら既定値で
    if Log = '' then Log := SysDrive + LOG_DEF;
    if Dmp = '' then Dmp := SysDrive + DMP_DEF;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    Log, Dmp: string;
begin
    GetWatsonPath(Log, Dmp);
    ShowMessage(Log + #13#10 + Dmp);
end;

ゴミ箱を空にするTOP

本当の最後が、ゴミ箱を空にする方法です。多分どこかに乗ってるんだと思いますが、ここでは「Delphi4 TECH200 Rev.2」に載っていた方法をとります。っていうか写します。

なんか、shell32.dllには存在しているAPIなのに、少なくともDelphi6までは宣言されていないようです。ですので、これを、implementationの上に書いておきます。

//-----------------------------------------------------------------------------
//  ゴミ箱を空にする
const
    SHERB_NOCONFIRMATION = $00000001;
    SHERB_NOPROGRESSUI   = $00000002;
    SHERB_NOSOUND        = $00000004;

function SHEmptyRecycleBin(Wnd: HWND; pszRootPath: PChar; dwFlags: DWORD): integer; stdcall;
                                        external 'shell32.dll' name 'SHEmptyRecycleBinA'; 

で、使います。ここでは、3つ目の引数に0を渡しているので「確認画面を表示して、プログレス画面を表示して、音を出す」ということになります。

//-----------------------------------------------------------------------------
//  ゴミ箱を空にする
procedure TMainForm.Button1Click(Sender: TObject);
begin
    SHEmptyRecycleBin(Handle, '', 0);
end;

あとがきTOP

そんなこんなで、以上をゴミフォルダと決めました。実際にはいつも使っているアプリケーションのログフォルダとかいろいろあるんでしょうが、Windows2000純正ということでこれだけとしておきます。こういうのを削除するプログラムを作ろうとして一撃必殺飽きてしまって忘れないうちにメモっておこうと思っただけです。

EOFTOP