C# でディレクトリがごみ箱であることを確認するにはどうすればよいですか?
-
22-09-2019 - |
質問
フォルダーがある場合、それがごみ箱であることをどうやって判断できるのでしょうか?見つけました 答え C++ ではありますが、C# ではありません。
私の最初のアイデアは、FileAttributes.System をチェックすることでした (私の場合、これは許容可能な近似値です) が、実際には、そのフラグは recycle フォルダーでクリアされています。
ハードコードされたフォルダー名を使用する粗雑なソリューションは問題外です (何と言っても、私たちは 2009 年ですから)。
解決
ここで少し問題があります。Windows のごみ箱は仮想フォルダーであり、実際には存在しません。表示されているファイルは、実際にはそのフォルダー内にあるのではなく、ディスク上の既存のファイルが特別な名前に変更されたものであり、物理的なファイル システムではなく、表示されているファイル システムから「削除」されます。
win32 API を使用してフォルダーの場所を要求することで、これを自分で「証明」できます。戻ってきます E_FAIL
ごみ箱には適用されますが、他のフォルダには適用されません(「 pinvoke.net の SHGetKnownFolderPath (そしてMSDNでも) 使用できるすべての定数と、このコードの実行に必要な宣言については、次のようになります。
IntPtr ptrRecycleBinPath;
// try it with KnownFolder.QuickLaunch to see it working:
HRESULT hr = (HRESULT) SHGetKnownFolderPath(
KnownFolder.RecycleBinFolder,
0,
IntPtr.Zero,
out ptrRecycleBinPath);
if (hr == HRESULT.E_FAIL)
{
Console.WriteLine("No folder avaialable, virtual folder");
}
else if (hr == HRESULT.S_OK)
{
string RecycleBinPath = Marshal.PtrToStringUni(ptrRecycleBinPath);
Marshal.FreeCoTaskMem(ptrRecycleBinPath);
Console.WriteLine("path: " + RecycleBinPath);
}
// for convenience, you can use the code above
// directly if you paste the follow declarations in your class:
// get a "known path"
[DllImport("shell32.dll")]
static extern long SHGetKnownFolderPath(
[MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
uint dwFlags,
IntPtr hToken,
out IntPtr pszPath);
// known folder GUID declarations
public static class KnownFolder
{
// many more entries exist, left out for clarity here
public static readonly Guid RecycleBinFolder =
new Guid("B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC");
public static readonly Guid QuickLaunch =
new Guid("52a4f021-7b75-48a9-9f6b-4b87a210bc8f");
//....
}
// results of COM invocations:
enum HRESULT : uint
{
S_FALSE = 0x0001,
S_OK = 0x0000,
E_FAIL = 0x80004005,
E_INVALIDARG = 0x80070057,
E_OUTOFMEMORY = 0x8007000E
}
偽のフォルダー名 「$Recycle.bin」 ドライブごとに繰り返されます。非表示の名前はレジストリに保存されず、API からアクセスすることはできません。以前に提案された KnownFolderHelper もこの情報を取得しません (同じライブラリには、ごみ箱を取得するための名前付きメソッドがあり、 GetPath
, 、空になります)。
しかし、すべてが失われたわけではありません。この偽の存在しない「ファイル名」または「フォルダー名」には、次のような隠しファイルが含まれています。 「S-1-5-21-2703390745-3900912742-210389625-1000」 (あなたのものは違うでしょう)。これは、特定のファイル名が実際にごみ箱の仮想ディレクトリであるかどうかを確認する 2 つの「信頼できる」方法のうちの 1 つです (もう 1 つは次の方法です)。ファイルを削除する SHFileOperation
, ここで説明されています, を選択し、それが自分のフォルダーに表示されるかどうかを確認します)。
string [] entries = Directory.GetFileSystemEntries(@"c:\$Recycle.bin", "?-?-?-??*");
if(entries.Length > 0)
// we have a winner
else
// no, not the recycle bin
注記:他の win32 バージョンの隠しフォルダーが何であるかはわかりません。少し試してみる必要があります。これらはすべてシステムと隠しフラグが設定されており、壊れた GUID のように見えます。
API ドキュメントではこれについてあまり明確ではありませんが、確認が必要な場合は、 このページでは説明しています 実際には取得できるパスが存在しないこと ( 古い CSIDL 関連ページ それについてはあまり明確ではありません)。
アップデート: 代替アプローチ SHGetSpecialFolderPath
, SHGetSpecialFolderLocation
, ShellAPI.SHGetFolderLocation
そして SHGetPathFromIDList
すべて同じように失敗します:空の結果またはエラーのいずれかです。ごみ箱と AppData の両方のすべての関数をテストしました (正しいパラメーターを使用していることを確認するため)。
のドキュメントのみ ShGetPathFromIDListEx
はっきりとそう言った、引用: 「UNC プリンター名を除き、pidl パラメーターで指定された場所がファイル システムの一部ではない場合、この関数は失敗します。」.
他のヒント
Microsoftのこの機能が含まれていのWindowsのAPIコードパックます。
ごみ箱のフォルダを取得するには、使用
Microsoft.WindowsAPICodePack.Shell.KnownFolderHelper.FromPath("::{645FF040-5081-101B-9F08-00AA002F954E}");
私は何をその文字列手段さっぱりだが、それはごみ箱への参照として、ドキュメントに含まれていた。
希望このことができます:)
ごみ箱に関連するメソッドのほとんどはC ++で書かれています。あなたはマネージ拡張を使用して、アプリケーションにラッパークラスを作成することができますC ++ のに、あなたはこのようにDLLIMPORTを使用する必要があります。
using System;
using System.Runtime.InteropServices;
class MainApp
{
[DllImport("user32.dll", EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String
strCaption, uint uiType);
public static void Main()
{
MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 );
}
}
C#で、この他の方法を行うそこの記事は、それらのほとんどは、それの名前でリサイクル$を持つフォルダ上のPInvokeを使用するか、依存している、もあります。私は、この主題のために発見したいくつかのリンクは次のとおり。
http://www.codeproject.com/KB/shell/recyclebin.aspx の
http://www.pinvoke.net/default.aspx/shell32.SHFileOperation の