ヘッダー
C# サンプル集
 

ファイルを1つ移動する

2020/8/30

→ Visual Basic のサンプルに切り替える

 

ファイルを単純に移動する

この例は C:\FileTest\FolderA\test.txt を C:\FileTest\FolderB\test.txt に移動します。


System.IO.File.Move(@"C:\FileTest\FolderA\test.txt", @"C:\FileTest\FolderB\test.txt");

  • 移動先のファイルが既に存在する場合、エラーにします。

 

これでもできます。

var file = new System.IO.FileInfo(@"C:\FileTest\FolderA\test.txt");
file.MoveTo(@"C:\FileTest\FolderB\test.txt");
  • 移動先のファイルが既に存在する場合、エラーにします。

 

 

ファイルを上書き移動する

この例は C:\FileTest\FolderA\test.txt を C:\FileTest\FolderB\test.txt に上書き移動します。


System.IO.File.Move(@"C:\FileTest\FolderA\test.txt", @"C:\FileTest\FolderB\test.txt", true);

  • 移動先のファイルが既に存在する場合、上書きします。

 

これでもできます。

var file = new System.IO.FileInfo(@"C:\FileTest\FolderA\test.txt");
file.MoveTo(@"C:\FileTest\FolderB\test.txt", true);
  • 移動先のファイルが既に存在する場合、上書きします。

 

 

移動先のフォルダーがない場合作成して、ファイルを上書き移動する

string fileFrom = @"C:\FileTest\FolderA\test.txt";
string fileTo = @"C:\FileTest\FolderB\test.txt";

//移動先のフォルダーが存在するか確認し、なければ作成します。
string targetFolder = System.IO.Path.GetDirectoryName(fileTo);
if (System.IO.Directory.Exists(targetFolder) == false)
{
    System.IO.Directory.CreateDirectory(targetFolder);
}

System.IO.File.Move(fileFrom, fileTo, true);
  • コピー先のファイルが既に存在する場合、上書きします。

 

 

ダイアログを表示して移動する

この例は時間がかかる移動の状況を表示するダイアログや、上書きの確認ダイアログなどを表示します。

何事もなくすぐに移動が終わる場合はダイアログが表示されません。

この例を実行するには、Microsoft.VisualBasic.dllをNuGetから取得し(.NET Frameworkの場合は、NuGetから取得するのではなく参照設定します。)、ファイルの先頭の方に using Microsoft.VisualBasic.FileIO; を記述します。


FileSystem.MoveFile(@"C:\FileTest\FolderA\test.txt", @"C:\FileTest\FolderB\test.txt", UIOption.AllDialogs, UICancelOption.DoNothing);

  • 移動に時間がかかる場合、進捗状況のダイアログを表示します。(この画像は移動ではなくコピーの画像を流用しています。)

ファイルコピーのダイアログ

  • 移動先のファイルが既に存在する場合、どのように処理するかユーザーに確認します。(この画像は移動ではなくコピーの画像を流用しています。)

Windows7の上書き確認ダイアログ

  • 何かエラーが発生した場合、エラーを表示します。
  • Linuxでは実行できません。X Window使用時でもSystem.PlatformNotSupportedExceptionとなります。macOSでは試していません。

 

次の例でも時間がかかる移動の状況を表示するダイアログや、上書きの確認ダイアログなどを表示します。

何事もなくすぐに移動が終わる場合はダイアログが表示されません。

この例ではMicrosoft.VisualBasic.dllは不要です。

この例を実行するにはファイルの先頭の方に using System.Runtime.InteropServices; が必要です。

public void CopyTest()
{
    var sf = new NativeMethods.SHFILEOPSTRUCT();

    sf.wFunc = NativeMethods.FileFuncFlags.FO_MOVE; //移動を指示します。
    sf.pFrom = @"C:\FileTest\FolderA\test.txt" + "\0";
    sf.pTo = @"C:\FileTest\FolderB\test.txt" + "\0";

    int result;
    result = NativeMethods.SHFileOperation(ref sf);

    if (result == 0)
    {
        System.Diagnostics.Debug.WriteLine("成功");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("失敗。" + result);
    }
}

public class NativeMethods
{
    /// <summary>
    /// ファイルをコピー・移動・削除・名前変更します。
    /// </summary>
    /// <param name="lpFileOp"></param>
    /// <returns>正常時0。異常時の値の意味は https://docs.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shfileoperationa を参照。</returns>
    [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)] public FileFuncFlags wFunc;
        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)] public string pTo;
        [MarshalAs(UnmanagedType.U2)] public FILEOP_FLAGS fFlags;
        [MarshalAs(UnmanagedType.Bool)] public bool ffAnyOperationsAborted;
        public IntPtr hNameMappings; //FOF_WANTMAPPINGHANDLEフラグとともに使用します。
        [MarshalAs(UnmanagedType.LPWStr)] public string lplpszProgressTitle; //FOF_SIMPLEPROGRESSフラグとともに使用します。
    }


    public enum FileFuncFlags
    {
        /// <summary>pFrom から pTo にファイルを移動します。</summary>
        FO_MOVE = 0x1,
        /// <summary>pFrom から pTo にファイルをコピーします。</summary>
        FO_COPY = 0x2,
        /// <summary>pFrom からファイルを削除します。</summary>
        FO_DELETE = 0x3,
        /// <summary>pFrom のファイルの名前を変更します。複数ファイルを対象とする場合は FO_MOVE を使用します。</summary>
        FO_RENAME = 0x4
    }

    [Flags]
    public enum FILEOP_FLAGS : short
    {
        /// <summary>pToにはpFromに1対1で対応する複数のコピー先を指定します。</summary>
        FOF_MULTIDESTFILES = 0x1,
        /// <summary>このフラグは使用しません。</summary>
        FOF_CONFIRMMOUSE = 0x2,
        /// <summary>進捗状況のダイアログを表示しません。</summary>
        FOF_SILENT = 0x4,
        /// <summary>同名のファイルが既に存在する場合、新しい名前を付けます。</summary>
        FOF_RENAMEONCOLLISION = 0x8,
        /// <summary>確認ダイアログを表示せず、すべて「はい」を選択したものとします。</summary>
        FOF_NOCONFIRMATION = 0x10,
        /// <summary>FOF_RENAMEONCOLLISIONフラグによるファイル名の衝突回避が発生した場合、SHFILEOPSTRUCT.hNameMappingsに新旧ファイル名の情報を格納します。この情報はSHFreeNameMappingsを使って開放する必要があります。</summary>
        FOF_WANTMAPPINGHANDLE = 0x20,
        /// <summary>可能であれば、操作を元に戻せるようにします。</summary>
        FOF_ALLOWUNDO = 0x40,
        /// <summary>ワイルドカードが使用された場合、ファイルのみを対象とします。</summary>
        FOF_FILESONLY = 0x80,
        /// <summary>進捗状況のダイアログを表示しますが、個々のファイル名は表示しません。</summary>
        FOF_SIMPLEPROGRESS = 0x100,
        /// <summary>新しいフォルダーの作成する前にユーザーに確認しません。</summary>
        FOF_NOCONFIRMMKDIR = 0x200,
        /// <summary>エラーが発生してもダイアログを表示しません。</summary>
        FOF_NOERRORUI = 0x400,
        /// <summary>ファイルのセキュリティ属性はコピーしません。コピー後のファイルはコピー先のフォルダーのセキュリティ属性を引き継ぎます。</summary>
        FOF_NOCOPYSECURITYATTRIBS = 0x800,
        /// <summary>サブディレクトリーを再帰的に処理しません。これは既定の動作です。</summary>
        FOF_NORECURSION = 0x1000,
        /// <summary>グループとして連結しているファイルは移動しません。指定されたファイルだけを移動します。</summary>
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,
        /// <summary>ファイルが恒久的に削除される場合、警告を表示します。このフラグはFOF_NOCONFIRMATIONより優先されます。 </summary>
        FOF_WANTNUKEWARNING = 0x4000,
        /// <summary>UIを表示しません。</summary>
        FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR
   }

}
  • 移動に時間がかかる場合、進捗状況のダイアログを表示します。
  • 移動先のファイルが既に存在する場合、どのように処理するかユーザーに確認します。
  • 何かエラーが発生した場合、エラーを表示します。
  • Windowsでのみ実行できます。(.NET Framework , .NET Core, .Net 5以降すべてで実行できます。)
  • このサンプルで使用している NativeMethods クラスは他のサンプルで使用しているものと完全に同じです。

 

 

 

「元に戻す」操作ができるようにファイルを移動する

この例を実行するにはファイルの先頭の方に using System.Runtime.InteropServices;が必要です。

public void CopyTest()
{
    var sf = new NativeMethods.SHFILEOPSTRUCT();

    sf.wFunc = NativeMethods.FileFuncFlags.FO_MOVE; //移動を指示します。
    sf.fFlags = NativeMethods.FILEOP_FLAGS.FOF_ALLOWUNDO; //「元に戻す」を有効にします。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOERRORUI; //エラー画面を表示しません。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_SILENT; //進捗ダイアログを表示しません。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMATION; //上書き確認ダイアログを表示しません。
   
sf.pFrom = @"C:\FileTest\FolderA\test.txt" + "\0";
    sf.pTo = @"C:\FileTest\FolderB\test.txt" + "\0";

    int result;
    result = NativeMethods.SHFileOperation(ref sf);

    if (result == 0)
    {
        System.Diagnostics.Debug.WriteLine("成功");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("失敗。" + result);
    }
}

public class NativeMethods
{
    /// <summary>
    /// ファイルをコピー・移動・削除・名前変更します。
    /// </summary>
    /// <param name="lpFileOp"></param>
    /// <returns>正常時0。異常時の値の意味は https://docs.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shfileoperationa を参照。</returns>
    [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)] public FileFuncFlags wFunc;
        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)] public string pTo;
        [MarshalAs(UnmanagedType.U2)] public FILEOP_FLAGS fFlags;
        [MarshalAs(UnmanagedType.Bool)] public bool ffAnyOperationsAborted;
        public IntPtr hNameMappings; //FOF_WANTMAPPINGHANDLEフラグとともに使用します。
        [MarshalAs(UnmanagedType.LPWStr)] public string lplpszProgressTitle; //FOF_SIMPLEPROGRESSフラグとともに使用します。
    }


    public enum FileFuncFlags
    {
        /// <summary>pFrom から pTo にファイルを移動します。</summary>
        FO_MOVE = 0x1,
        /// <summary>pFrom から pTo にファイルをコピーします。</summary>
        FO_COPY = 0x2,
        /// <summary>pFrom からファイルを削除します。</summary>
        FO_DELETE = 0x3,
        /// <summary>pFrom のファイルの名前を変更します。複数ファイルを対象とする場合は FO_MOVE を使用します。</summary>
        FO_RENAME = 0x4
    }

    [Flags]
    public enum FILEOP_FLAGS : short
    {
        /// <summary>pToにはpFromに1対1で対応する複数のコピー先を指定します。</summary>
        FOF_MULTIDESTFILES = 0x1,
        /// <summary>このフラグは使用しません。</summary>
        FOF_CONFIRMMOUSE = 0x2,
        /// <summary>進捗状況のダイアログを表示しません。</summary>
        FOF_SILENT = 0x4,
        /// <summary>同名のファイルが既に存在する場合、新しい名前を付けます。</summary>
        FOF_RENAMEONCOLLISION = 0x8,
        /// <summary>確認ダイアログを表示せず、すべて「はい」を選択したものとします。</summary>
        FOF_NOCONFIRMATION = 0x10,
        /// <summary>FOF_RENAMEONCOLLISIONフラグによるファイル名の衝突回避が発生した場合、SHFILEOPSTRUCT.hNameMappingsに新旧ファイル名の情報を格納します。この情報はSHFreeNameMappingsを使って開放する必要があります。</summary>
        FOF_WANTMAPPINGHANDLE = 0x20,
        /// <summary>可能であれば、操作を元に戻せるようにします。</summary>
        FOF_ALLOWUNDO = 0x40,
        /// <summary>ワイルドカードが使用された場合、ファイルのみを対象とします。</summary>
        FOF_FILESONLY = 0x80,
        /// <summary>進捗状況のダイアログを表示しますが、個々のファイル名は表示しません。</summary>
        FOF_SIMPLEPROGRESS = 0x100,
        /// <summary>新しいフォルダーの作成する前にユーザーに確認しません。</summary>
        FOF_NOCONFIRMMKDIR = 0x200,
        /// <summary>エラーが発生してもダイアログを表示しません。</summary>
        FOF_NOERRORUI = 0x400,
        /// <summary>ファイルのセキュリティ属性はコピーしません。コピー後のファイルはコピー先のフォルダーのセキュリティ属性を引き継ぎます。</summary>
        FOF_NOCOPYSECURITYATTRIBS = 0x800,
        /// <summary>サブディレクトリーを再帰的に処理しません。これは既定の動作です。</summary>
        FOF_NORECURSION = 0x1000,
        /// <summary>グループとして連結しているファイルは移動しません。指定されたファイルだけを移動します。</summary>
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,
        /// <summary>ファイルが恒久的に削除される場合、警告を表示します。このフラグはFOF_NOCONFIRMATIONより優先されます。 </summary>
        FOF_WANTNUKEWARNING = 0x4000,
        /// <summary>UIを表示しません。</summary>
        FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR
   }

}
  • 移動後にエクスプローラーを右クリックして、「元に戻す」操作ができます。この「元に戻す」はエクスプローラーの機能であり、完全に移動前の状態に戻るわけではありません。たとえば、上書きを元に戻しても、上書き前のファイルに戻るわけではありません。(下記画像は移動ではなくコピーの画像を流用しています。)
コピーを元に戻す
  • Windowsでのみ実行できます。(.NET Framework , .NET Core, .Net 5以降すべてで実行できます。)
  • このサンプルで使用している NativeMethods クラスは他のサンプルで使用しているものと完全に同じです。

 

 

移動先に同名のファイルがある場合、ファイル名に「 - コピー」、「 - コピー(2)」などを付けてファイルを移動する

この例を実行するにはファイルの先頭の方に using System.Runtime.InteropServices; が必要です。

※ごめんなさい。このサンプルの動作は少し怪しいです。 「- コピー」が存在する場合は、本体のファイルの方が上書きされてしまいました。採用する場合は検証してください。

public void CopyTest()
{
    var sf = new NativeMethods.SHFILEOPSTRUCT();

    sf.wFunc = NativeMethods.FileFuncFlags.FO_MOVE; //移動を指示します。
    sf.fFlags = NativeMethods.FILEOP_FLAGS.FOF_ALLOWUNDO; //「元に戻す」を有効にします。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOERRORUI; //エラー画面を表示しません。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_SILENT; //進捗ダイアログを表示しません。
    sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMATION; //上書き確認ダイアログを表示しません。
   
sf.fFlags = sf.fFlags | NativeMethods.FILEOP_FLAGS.FOF_RENAMEONCOLLISION; //同名のファイルがある場合自動的に名前を変えてコピーします。 
    sf.pFrom = @"C:\FileTest\FolderA\test.txt" + "\0";
    sf.pTo = @"C:\FileTest\FolderB\test.txt" + "\0";

    int result;
    result = NativeMethods.SHFileOperation(ref sf);

    if (result == 0)
    {
        System.Diagnostics.Debug.WriteLine("成功");
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("失敗。" + result);
    }
}

public class NativeMethods
{
    /// <summary>
    /// ファイルをコピー・移動・削除・名前変更します。
    /// </summary>
    /// <param name="lpFileOp"></param>
    /// <returns>正常時0。異常時の値の意味は https://docs.microsoft.com/ja-jp/windows/win32/api/shellapi/nf-shellapi-shfileoperationa を参照。</returns>
    [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)] public FileFuncFlags wFunc;
        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)] public string pTo;
        [MarshalAs(UnmanagedType.U2)] public FILEOP_FLAGS fFlags;
        [MarshalAs(UnmanagedType.Bool)] public bool ffAnyOperationsAborted;
        public IntPtr hNameMappings; //FOF_WANTMAPPINGHANDLEフラグとともに使用します。
        [MarshalAs(UnmanagedType.LPWStr)] public string lplpszProgressTitle; //FOF_SIMPLEPROGRESSフラグとともに使用します。
    }


    public enum FileFuncFlags
    {
        /// <summary>pFrom から pTo にファイルを移動します。</summary>
        FO_MOVE = 0x1,
        /// <summary>pFrom から pTo にファイルをコピーします。</summary>
        FO_COPY = 0x2,
        /// <summary>pFrom からファイルを削除します。</summary>
        FO_DELETE = 0x3,
        /// <summary>pFrom のファイルの名前を変更します。複数ファイルを対象とする場合は FO_MOVE を使用します。</summary>
        FO_RENAME = 0x4
    }

    [Flags]
    public enum FILEOP_FLAGS : short
    {
        /// <summary>pToにはpFromに1対1で対応する複数のコピー先を指定します。</summary>
        FOF_MULTIDESTFILES = 0x1,
        /// <summary>このフラグは使用しません。</summary>
        FOF_CONFIRMMOUSE = 0x2,
        /// <summary>進捗状況のダイアログを表示しません。</summary>
        FOF_SILENT = 0x4,
        /// <summary>同名のファイルが既に存在する場合、新しい名前を付けます。</summary>
        FOF_RENAMEONCOLLISION = 0x8,
        /// <summary>確認ダイアログを表示せず、すべて「はい」を選択したものとします。</summary>
        FOF_NOCONFIRMATION = 0x10,
        /// <summary>FOF_RENAMEONCOLLISIONフラグによるファイル名の衝突回避が発生した場合、SHFILEOPSTRUCT.hNameMappingsに新旧ファイル名の情報を格納します。この情報はSHFreeNameMappingsを使って開放する必要があります。</summary>
        FOF_WANTMAPPINGHANDLE = 0x20,
        /// <summary>可能であれば、操作を元に戻せるようにします。</summary>
        FOF_ALLOWUNDO = 0x40,
        /// <summary>ワイルドカードが使用された場合、ファイルのみを対象とします。</summary>
        FOF_FILESONLY = 0x80,
        /// <summary>進捗状況のダイアログを表示しますが、個々のファイル名は表示しません。</summary>
        FOF_SIMPLEPROGRESS = 0x100,
        /// <summary>新しいフォルダーの作成する前にユーザーに確認しません。</summary>
        FOF_NOCONFIRMMKDIR = 0x200,
        /// <summary>エラーが発生してもダイアログを表示しません。</summary>
        FOF_NOERRORUI = 0x400,
        /// <summary>ファイルのセキュリティ属性はコピーしません。コピー後のファイルはコピー先のフォルダーのセキュリティ属性を引き継ぎます。</summary>
        FOF_NOCOPYSECURITYATTRIBS = 0x800,
        /// <summary>サブディレクトリーを再帰的に処理しません。これは既定の動作です。</summary>
        FOF_NORECURSION = 0x1000,
        /// <summary>グループとして連結しているファイルは移動しません。指定されたファイルだけを移動します。</summary>
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,
        /// <summary>ファイルが恒久的に削除される場合、警告を表示します。このフラグはFOF_NOCONFIRMATIONより優先されます。 </summary>
        FOF_WANTNUKEWARNING = 0x4000,
        /// <summary>UIを表示しません。</summary>
        FOF_NO_UI = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR
   }

}
  • Windowsでのみ実行できます。(.NET Framework , .NET Core, .Net 5以降すべてで実行できます。)
  • このサンプルで使用している NativeMethods クラスは他のサンプルで使用しているものと完全に同じです。