|
|
|
ファイルを削除してゴミ箱に入れたいと言う質問があったので、まとめました。 |
|
(1) MSDN(US)
SHFileOperation
(2) Code
Project |
|
ファイルを削除するには、普通 System.IO.File.Delete(ファイル名) です。
ですが、この場合ファイルはゴミ箱には入らず、削除されてしまいます。
また、System.IO.File.Delete のオプションを指定することにより、ゴミ箱にいれるようなこともできません。
これは、ゴミ箱のようなプラットフォームに依存したフレームワークは提供しないと言うポリシーなのかもしれません。
では、どうすればファイルを削除したときにゴミ箱に行くのかと言うと、ゴミ箱がどのようなメカニズムで提供されているのか
を考えれば想像がつきます。
OS 自体は、そんなゴミ箱の面倒なんか見てくれません。
Windows シェルがゴミ箱の面倒を見てくれています。
ということで、Windows シェルを提供しているベースの ”シェルAPI” が思い当たると思います。
関連するシェルAPIには次のものがあります。
Shell API | 説明 |
SHFileOperation() | ファイルシステムオブジェクトのコピー、移動、リネーム、削除。 |
SHQueryRecycleBin() | 指定ドライブのゴミ箱のサイズ、アイテムの数の取得.
|
SHEmptyRecycleBin() | 指定ドライブのゴミ箱を空にする。. |
ということで、SHFileOperation を使えば、ファイルを削除してゴミ箱に入れることができます。
でも、これらを使うには、プラットフォーム呼び出しをしなければなりません。
|
|
必要となる定数、構造体、メソッドは次のとおりです。
定数 |
public enum FOFunc : uint
{
FO_MOVE = 0x0001,
FO_COPY = 0x0002,
FO_DELETE = 0x0003,
FO_RENAME = 0x0004
}
public enum FOFlags : ushort
{
FOF_MULTIDESTFILES = 0x0001,
FOF_CONFIRMMOUSE = 0x0002,
FOF_SILENT = 0x0004, // don't create progress/report
FOF_RENAMEONCOLLISION = 0x0008,
FOF_NOCONFIRMATION = 0x0010, // Don't prompt the user.
FOF_WANTMAPPINGHANDLE = 0x0020, // Fill in SHFILEOPSTRUCT.hNameMappings
// Must be freed using SHFreeNameMappings
FOF_ALLOWUNDO = 0x0040,
FOF_FILESONLY = 0x0080, // on *.*, do only files
FOF_SIMPLEPROGRESS = 0x0100, // means don't show names of files
FOF_NOCONFIRMMKDIR = 0x0200, // don't confirm making any needed dirs
FOF_NOERRORUI = 0x0400, // don't put up error UI
FOF_NOCOPYSECURITYATTRIBS = 0x0800, // dont copy NT file Security Attributes
FOF_NORECURSION = 0x1000, // don't recurse into directories.
FOF_NO_CONNECTED_ELEMENTS = 0x2000, // don't operate on connected elements.
FOF_WANTNUKEWARNING = 0x4000, // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
FOF_NORECURSEREPARSE = 0x8000 // treat reparse points as objects, not containers
}
|
構造体 |
// typedef struct _SHFILEOPSTRUCT
// {
// HWND hwnd;
// UINT wFunc;
// LPCTSTR pFrom;
// LPCTSTR pTo;
// FILEOP_FLAGS fFlags;
// BOOL fAnyOperationsAborted;
// LPVOID hNameMappings;
// LPCTSTR lpszProgressTitle;
// } SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public FOFunc wFunc;
[MarshalAs(UnmanagedType.LPWStr)]
public string pFrom;
[MarshalAs(UnmanagedType.LPWStr)]
public string pTo;
public FOFlags fFlags;
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszProgressTitle;
}
|
プロトタイプ宣言 |
// int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp
// );
// Unicode を明示的に指定する必要があります。
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHFileOperation(
ref SHFILEOPSTRUCT lpFileOp
);
|
|
|
これらをクラスにまとめたのが次のソースコードです。
using System;
using System.Runtime.InteropServices;
namespace Uchukamen.util
{
/// <summary>
/// Shell の概要の説明です。
/// </summary>
public class Shell
{
public Shell()
{
}
public enum FOFunc : uint
{
FO_MOVE = 0x0001,
FO_COPY = 0x0002,
FO_DELETE = 0x0003,
FO_RENAME = 0x0004
}
public enum FOFlags : ushort
{
FOF_MULTIDESTFILES = 0x0001,
FOF_CONFIRMMOUSE = 0x0002,
FOF_SILENT = 0x0004, // don't create progress/report
FOF_RENAMEONCOLLISION = 0x0008,
FOF_NOCONFIRMATION = 0x0010, // Don't prompt the user.
FOF_WANTMAPPINGHANDLE = 0x0020, // Fill in SHFILEOPSTRUCT.hNameMappings
// Must be freed using SHFreeNameMappings
FOF_ALLOWUNDO = 0x0040,
FOF_FILESONLY = 0x0080, // on *.*, do only files
FOF_SIMPLEPROGRESS = 0x0100, // means don't show names of files
FOF_NOCONFIRMMKDIR = 0x0200, // don't confirm making any needed dirs
FOF_NOERRORUI = 0x0400, // don't put up error UI
FOF_NOCOPYSECURITYATTRIBS = 0x0800, // dont copy NT file Security Attributes
FOF_NORECURSION = 0x1000, // don't recurse into directories.
FOF_NO_CONNECTED_ELEMENTS = 0x2000, // don't operate on connected elements.
FOF_WANTNUKEWARNING = 0x4000, // during delete operation, warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
FOF_NORECURSEREPARSE = 0x8000 // treat reparse points as objects, not containers
}
// typedef struct _SHFILEOPSTRUCT
// {
// HWND hwnd;
// UINT wFunc;
// LPCTSTR pFrom;
// LPCTSTR pTo;
// FILEOP_FLAGS fFlags;
// BOOL fAnyOperationsAborted;
// LPVOID hNameMappings;
// LPCTSTR lpszProgressTitle;
// } SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public FOFunc wFunc;
[MarshalAs(UnmanagedType.LPWStr)]
public string pFrom;
[MarshalAs(UnmanagedType.LPWStr)]
public string pTo;
public FOFlags fFlags;
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszProgressTitle;
}
// int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp
// );
// Unicode を明示的に指定する必要があります。
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHFileOperation(
ref SHFILEOPSTRUCT lpFileOp
);
}
}
|
|
上記クラスを使って、ファイルを削除してゴミ箱に入れるには、例えば次のように呼び出します。
ファイルを削除してゴミ箱に入れるコード。 |
using Uchukamen.util;
....
Shell.SHFILEOPSTRUCT sh = new Shell.SHFILEOPSTRUCT();
sh.hwnd = this.Handle;
sh.wFunc = Shell.FOFunc.FO_DELETE;
sh.pFrom = ファイルパス + '\0' + '\0';
sh.pTo = null;
sh.fFlags = Shell.FOFlags.FOF_ALLOWUNDO;
sh.fAnyOperationsAborted = false;
sh.hNameMappings = IntPtr.Zero;
sh.lpszProgressTitle = "Hello";
int result = Shell.SHFileOperation(ref sh);
|
sh.wFunc では、FO_DELETE で削除を指定します。
sh.fFlags では、FOF_ALLOWUNDO でアンドゥできるようにします。
このときのパラメータを変更することにより、ダイアログを出す、出さないなどを設定できます。
注意: ファイル名の指定方法 |
それから、ちょっとトリッキーなのが、ファイル名の指定方法です。
MSDN のヘルプには次のように記載されています。 "Each file name must be terminated by a single NULL character. An additional NULL character
must be appended to the end of the final name to indicate the end of pFrom. "
ということで、ヌル文字がファイル名とファイル名のターミネータとして使われ、
さらにpForm の最後をあらわすためにもう1つヌル文字を追加する必要があります。
例:
sh.pFrom = ファイルパス + '\0' + '\0';
sh.pFrom = @"c:\temp\test" + '\0' + @"c:\temp\test\test.txt" + '\0' + '\0';
|
これで、実行すると、次のようなダイアログが出て、ゴミ箱行きになります。
|
|
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Uchukamen.util;
namespace Uchukamen
{
/// <summary>
/// Form1 の概要の説明です。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows フォーム デザイナ サポートに必要です。
//
InitializeComponent();
//
// TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
//
}
/// <summary>
/// 使用されているリソースに後処理を実行します。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows フォーム デザイナで生成されたコード
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(160, 128);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "ゴミ箱へ";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
if (DialogResult.OK == this.openFileDialog1.ShowDialog())
{
// System.IO.File.Delete(this.openFileDialog1.FileName);
Shell.SHFILEOPSTRUCT sh = new Shell.SHFILEOPSTRUCT();
sh.hwnd = this.Handle;
sh.wFunc = Shell.FOFunc.FO_DELETE;
sh.pFrom = this.openFileDialog1.FileName + '\0' + '\0';
sh.pTo = null;
sh.fFlags = Shell.FOFlags.FOF_ALLOWUNDO;
sh.fAnyOperationsAborted = false;
sh.hNameMappings = IntPtr.Zero;
sh.lpszProgressTitle = "Hello";
int result = Shell.SHFileOperation(ref sh);
}
}
}
}
|
|
2003/6/25 新規作成 |