コード
win11 C# visual Studio Community 2022
コード
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ConsoleApplication1
{
//呼び出し方法
//exePath mode 元フォルダ 先フォルダ
// procCMDR.exe "COPY" "C:\1\testFolder" "C:\2\testFolder"
// procCMDR.exe "MOVE" "C:\1\testFolder" "C:\2\testFolder"
// procCMDR.exe "RENAME" "C:\1\testFolder" "C:\1\testFolder_Rename"
//ゴミ箱へ移動するTRUE 移動しない FALSE 但しエクスプローラーの設定により、ゴミ箱へ移動しない場合もある
// procCMDR.exe "DELETE" "C:\1\testFolder" "TRUR or FALSE"
//コード例
//string exeName = "c:\test\procCMDR.exe";
//string cmdStr = "COPY C:\1\testFolder C:\2\testFolder";
//System.Diagnostics.Process.Start(exeName, cmdStr);
class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] // CharSet.Unicode が重要
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public FO wFunc;
[MarshalAs(UnmanagedType.LPWStr)] // LPTSTR の代わりに LPWStr を使用
public string pFrom;
[MarshalAs(UnmanagedType.LPWStr)] // LPTSTR の代わりに LPWStr を使用
public string pTo;
public FOF fFlags;
[MarshalAs(UnmanagedType.Bool)]
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)] // LPTSTR の代わりに LPWStr を使用
public string lpszProgressTitle;
}
public enum FO : uint
{
MOVE = 0x0001,
COPY = 0x0002,
DELETE = 0x0003,
RENAME = 0x0004,
}
[Flags]
public enum FOF : ushort
{
SILENT = 0x0004, // Progress UIを表示しない
NOCONFIRMATION = 0x0010, // 確認ダイアログを表示しない (上書き確認など)
MULTIPLEFILES = 0x0040, // pFrom, pTo が複数ファイルを指す場合
ALLOWUNDO = 0x0040, // 削除操作をUNDO可能にする (ごみ箱へ移動)
FILESONLY = 0x0080, // ワイルドカード指定時、ファイルのみを対象とする
SIMPLEPROGRESS = 0x0100, // 簡単なプログレスUIを表示する
NOCONFIRMMKDIR = 0x0200, // 新規ディレクトリ作成時の確認ダイアログを表示しない
NOERRORUI = 0x0400, // エラー発生時のUIを表示しない
NORECURSION = 0x0800, // サブディレクトリを再帰的に処理しない
NO_CONNECTED_ELEMENTS = 0x2000, // ネットワーク共有要素を処理しない
//WANTMAPPINGHANDLE = 0x20000, // hNameMappings を使用する
//ALLOWCACREAD = 0x200000, // キャッシュされたアクセス制御リスト (ACL) の作成を許可
NO_UI = NOERRORUI | SILENT | NOCONFIRMATION | NOCONFIRMMKDIR // UIを一切表示しない
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);
public static void CopyFile(string source, string destination, bool showUI = true, bool allowUndo = false)
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
fileOp.wFunc = FO.COPY;
fileOp.pFrom = source + '\0' + '\0';
fileOp.pTo = destination + '\0' + '\0'; // コピー先がディレクトリの場合、その中にコピーされる
fileOp.fFlags = FOF.MULTIPLEFILES | (showUI ? 0 : FOF.NO_UI);
if (!showUI) fileOp.fFlags |= FOF.NOCONFIRMATION; // UI非表示なら確認もしないことが多い
if (allowUndo) fileOp.fFlags |= FOF.ALLOWUNDO; // コピー操作では通常あまり使われないが、一応
int result = SHFileOperation(ref fileOp);
}
public static void MoveFile(string source, string destination, bool showUI = true, bool allowUndo = false)
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
fileOp.wFunc = FO.MOVE;
fileOp.pFrom = source + '\0' + '\0';
fileOp.pTo = destination + '\0' + '\0';
fileOp.fFlags = FOF.MULTIPLEFILES | (showUI ? 0 : FOF.NO_UI);
if (!showUI) fileOp.fFlags |= FOF.NOCONFIRMATION;
if (allowUndo) fileOp.fFlags |= FOF.ALLOWUNDO;
int result = SHFileOperation(ref fileOp);
}
public static void DeleteFile(string path, bool moveToRecycleBin = true, bool showUI = true)
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
fileOp.wFunc = FO.DELETE;
fileOp.pFrom = path + '\0' + '\0';
fileOp.pTo = null; // 削除操作では pTo は使用しない
fileOp.fFlags = FOF.MULTIPLEFILES | (showUI ? 0 : FOF.NO_UI);
if (!showUI) fileOp.fFlags |= FOF.NOCONFIRMATION;
if (moveToRecycleBin)
{
fileOp.fFlags |= FOF.ALLOWUNDO;
}
// ALLOWUNDO を指定しない場合、完全に削除される(ごみ箱に入らない)
int result = SHFileOperation(ref fileOp);
}
public static void RenameFile(string oldPath, string newPath, bool showUI = true)
{
SHFILEOPSTRUCT fileOp = new SHFILEOPSTRUCT();
fileOp.wFunc = FO.RENAME;
fileOp.pFrom = oldPath + '\0' + '\0';
fileOp.pTo = newPath + '\0' + '\0'; // リネームの場合、pTo は新しいフルパスまたは新しいファイル名を指定
fileOp.fFlags = FOF.MULTIPLEFILES | (showUI ? 0 : FOF.NO_UI);
if (!showUI) fileOp.fFlags |= FOF.NOCONFIRMATION;
int result = SHFileOperation(ref fileOp);
}
static void Main(string[] args)
{
string cmdLine = System.Environment.CommandLine;
// 引数確認用メッセージボックスを表示
DialogResult result = MessageBox.Show(cmdLine,//"表示メッセージ",
"引数確認",
MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1);
//return;
//コマンドライン引数を配列で取得する
string[] cmds = System.Environment.GetCommandLineArgs();
string source = cmds[2]; //コピー元
string dest = cmds[3]; //コピー先
bool showUI = true;//UIを表示するかどうか
bool allowUndo = false;//ごみ箱に移動するかどうか
if (cmds[1] == "COPY")
{
CopyFile(source, dest, showUI, allowUndo);
}
else if (cmds[1] == "MOVE")
{
MoveFile(source, dest, showUI, allowUndo);
}
else if (cmds[1] == "RENAME")
{
RenameFile(source, dest, showUI);
}
else if (cmds[1] == "DELETE")
{
source = cmds[2];//削除オブジェクト
string str = cmds[3];//ごみ箱へ移動
if (str == "TRUE")
{
allowUndo = true;
}
else if (str == "FALSE")
{
allowUndo = false;
}
else
{
//メッセージボックスを表示する
MessageBox.Show("ごみ箱へ移動 モード不明\n"+ str,
"エラー",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
DeleteFile(source, allowUndo, showUI);
}
else
{
//メッセージボックスを表示する
MessageBox.Show("操作モード不明",
"エラー",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
}
}