前提・実現したいこと
WPFでフォルダのコピーを行いたいと思っています。
コピー時に、進捗確認を行いつつ、上書きがある場合はすべてTRUEにしたいと思っています。
しかし、下記のメソッドではUI表示はできても上書きができず、もう1つは上書きはできてもUI表示ができません。
この2つを同時に行う方法はありますでしょうか?
進捗確認
C#
1Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(srcPath, desPath, UIOption.AllDialogs);
同一ファイルがある場合はすべて上書き
C#
1Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(srcPath, desPath, true);
補足情報(FW/ツールのバージョンなど)
Windows10 Pro
.NetframeWork 4
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/09/20 02:15
2019/09/20 02:19 編集
2019/09/20 02:23 編集
退会済みユーザー
2019/10/16 06:16 編集
2019/10/16 06:46
回答2件
0
SHFileOperation を使ってみてはどうでしょう。
API の宣言
C#
1 static class NativeMethods 2 { 3 public enum FileFuncFlags : uint 4 { 5 FO_MOVE = 0x1, 6 FO_COPY = 0x2, 7 FO_DELETE = 0x3, 8 FO_RENAME = 0x4 9 } 10 11 [Flags] 12 public enum FILEOP_FLAGS : ushort 13 { 14 FOF_MULTIDESTFILES = 0x1, 15 FOF_CONFIRMMOUSE = 0x2, 16 FOF_SILENT = 0x4, 17 FOF_RENAMEONCOLLISION = 0x8, 18 FOF_NOCONFIRMATION = 0x10, 19 FOF_WANTMAPPINGHANDLE = 0x20, 20 FOF_ALLOWUNDO = 0x40, 21 FOF_FILESONLY = 0x80, 22 FOF_SIMPLEPROGRESS = 0x100, 23 FOF_NOCONFIRMMKDIR = 0x200, 24 FOF_NOERRORUI = 0x400, 25 FOF_NOCOPYSECURITYATTRIBS = 0x800, 26 FOF_NORECURSION = 0x1000, 27 FOF_NO_CONNECTED_ELEMENTS = 0x2000, 28 FOF_WANTNUKEWARNING = 0x4000, 29 FOF_NORECURSEREPARSE = 0x8000 30 } 31 32 [StructLayout(LayoutKind.Sequential, Pack=1, CharSet = CharSet.Auto)] 33 public struct SHFILEOPSTRUCT 34 { 35 public IntPtr hwnd; 36 public FileFuncFlags wFunc; 37 [MarshalAs(UnmanagedType.LPTStr)] 38 public string pFrom; 39 [MarshalAs(UnmanagedType.LPTStr)] 40 public string pTo; 41 public FILEOP_FLAGS fFlags; 42 [MarshalAs(UnmanagedType.Bool)] 43 public bool fAnyOperationsAborted; 44 public IntPtr hNameMappings; 45 [MarshalAs(UnmanagedType.LPTStr)] 46 public string lpszProgressTitle; 47 } 48 49 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 50 struct SHFILEOPSTRUCT64 51 { 52 public IntPtr hwnd; 53 public FileFuncFlags wFunc; 54 [MarshalAs(UnmanagedType.LPTStr)] 55 public string pFrom; 56 [MarshalAs(UnmanagedType.LPTStr)] 57 public string pTo; 58 public FILEOP_FLAGS fFlags; 59 [MarshalAs(UnmanagedType.Bool)] 60 public bool fAnyOperationsAborted; 61 public IntPtr hNameMappings; 62 [MarshalAs(UnmanagedType.LPTStr)] 63 public string lpszProgressTitle; 64 } 65 66 [DllImport("shell32.dll", CharSet = CharSet.Auto, EntryPoint = "SHFileOperation")] 67 static extern int SHFileOperation32(ref SHFILEOPSTRUCT lpFileOp); 68 69 [DllImport("shell32.dll", CharSet = CharSet.Auto, EntryPoint = "SHFileOperation")] 70 static extern int SHFileOperation64(ref SHFILEOPSTRUCT64 lpFileOp); 71 72 public static int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp) { 73 if (IntPtr.Size == 4) { 74 return SHFileOperation32(ref lpFileOp); 75 } else { 76 var lpFileOp64 = new SHFILEOPSTRUCT64(); 77 lpFileOp64.hwnd = lpFileOp.hwnd; 78 lpFileOp64.wFunc = lpFileOp.wFunc; 79 lpFileOp64.pFrom = lpFileOp.pFrom; 80 lpFileOp64.pTo = lpFileOp.pTo; 81 lpFileOp64.fFlags = lpFileOp.fFlags; 82 lpFileOp64.fAnyOperationsAborted = lpFileOp.fAnyOperationsAborted; 83 lpFileOp64.hNameMappings = lpFileOp.hNameMappings; 84 lpFileOp64.lpszProgressTitle = lpFileOp.lpszProgressTitle; 85 86 int result = SHFileOperation64(ref lpFileOp64); 87 88 lpFileOp.fAnyOperationsAborted = lpFileOp64.fAnyOperationsAborted; 89 return result; 90 } 91 } 92 } 93
実行
C#
1 static class Program 2 { 3 [STAThread] 4 static void Main() { 5 var fileOp = new NativeMethods.SHFILEOPSTRUCT(); 6 fileOp.wFunc = NativeMethods.FileFuncFlags.FO_COPY; 7 fileOp.pFrom = "C:\work\*.*\0\0"; 8 fileOp.pTo = "C:\Work2\0\0"; 9 fileOp.fFlags = NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMATION | NativeMethods.FILEOP_FLAGS.FOF_NOCONFIRMMKDIR; 10 fileOp.fAnyOperationsAborted = true; 11 fileOp.hNameMappings = IntPtr.Zero; 12 fileOp.lpszProgressTitle = "コピー中・・・"; 13 NativeMethods.SHFileOperation(ref fileOp); 14 } 15 }
投稿2019/09/20 03:04
総合スコア2707
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
Zuishin様の意見を参考に作成しました。ありがとうございました。
C#
1private void Button_Click_Start(object sender, RoutedEventArgs e) 2{ 3 4 //プログレスバーの設定変更 5 prog.IsIndeterminate = false; 6 prog.Maximum = _srcData.Count(); 7 prog.Minimum = 0; 8 prog.Value = 0; 9 prog.Visibility = Visibility.Visible; 10 11 this.startBtn.IsEnabled = false; 12 13 //非同期処理 14 if (_tokenSource == null) _tokenSource = new CancellationTokenSource(); 15 var token = _tokenSource.Token; 16 17 Task task = Task.Factory.StartNew(() => MyAction(), _tokenSource.Token); 18 19 task.ContinueWith((t) => 20 Finishing(true), 21 new CancellationToken(), 22 TaskContinuationOptions.OnlyOnRanToCompletion, 23 _uiSyncContext 24 ); 25 task.ContinueWith((t) => 26 Finishing(false), 27 new CancellationToken(), 28 TaskContinuationOptions.OnlyOnCanceled, 29 _uiSyncContext 30 ); 31 32} 33 34private void MyAction() 35{ 36 DateTime startDt = DateTime.Now; 37 long currentSize = 0; 38 39 for (int i = 0; i < _srcData.Count(); i++) 40 { 41 string lfileName = _srcData[i].PathName.Remove(0, _srcPath.Length); 42 string lfilePath = _desPath + lfileName; 43 44 //対象ファイル先のフォルダがない場合は作成 45 SafeCreateDirectory(System.IO.Path.GetDirectoryName(lfilePath)); 46 //ファイルのコピー 47 System.IO.File.Copy(_srcData[i].PathName, lfilePath, true); 48 49 //進捗画面の更新 50 currentSize += _srcData[i].FileSize; 51 copyDataProc(_srcData[i], i, startDt, currentSize); 52 53 //プログレスバーの更新 54 var progresstask = new Task(() => this.prog.Value = i); 55 progresstask.Start(_uiSyncContext); 56 _tokenSource.Token.ThrowIfCancellationRequested(); 57 58 } 59} 60 61/// <summary> 62/// 進捗情報の変数更新 63/// </summary> 64/// /// <param name="fi"></param> 65/// /// <param name="cnt"></param> 66/// /// <param name="startDt"></param> 67/// /// <param name="currentSize"></param> 68private void copyDataProc(FileInfo fi, int cnt, DateTime startDt, long currentSize) 69{ 70 71 //処理中のファイル名 72 _viewModel.fileName = System.IO.Path.GetFileName(fi.PathName); 73 //残り時間 74 DateTime endDt = DateTime.Now; 75 TimeSpan ts = endDt - startDt; 76 double d = ts.TotalSeconds; 77 double KBs = (currentSize / 1024) / d; 78 double timeAns = ((_copySize - currentSize) / 1024) / KBs; 79 _viewModel.Remaining_time = timeAns.ToString("F1") + " [s]"; 80 //残り項目 81 string dispCurr = String.Format("{0:#,0}", currentSize / 1024); 82 string dispSum = String.Format("{0:#,0}", _copySize / 1024); 83 string reItems = (cnt + 1).ToString() + " / " + _srcData.Count() 84 + " (" + dispCurr + " / " + dispSum + " KByte)"; 85 _viewModel.Remaining_items = reItems; 86 //スピード 87 _viewModel.Speed = ((int)KBs).ToString() + " [KByte/s]"; 88} 89 90/// <summary> 91/// 非同期処理中の完了、未完了後の処理 92/// </summary> 93/// <param name="flg"></param> 94private void Finishing(bool flg) 95{ 96 if (flg) 97 { 98 MessageBox.Show("completed."); 99 } 100 else 101 { 102 Directory.Delete(_desPath, true); 103 //none 104 } 105 this.Close(); 106} 107 108/// <summary> 109/// フォルダが存在しない場合は作成する 110/// </summary> 111/// <param name="path"></param> 112private DirectoryInfo SafeCreateDirectory(string path) 113{ 114 if (Directory.Exists(path)) 115 { 116 return null; 117 } 118 return Directory.CreateDirectory(path); 119} 120 121/// <summary> 122/// データコピーのキャンセル 123/// </summary> 124/// <param name="sender"></param> 125/// <param name="e"></param> 126private void Button_Click_Cancel(object sender, RoutedEventArgs e) 127{ 128 if (_tokenSource != null) _tokenSource.Cancel(); 129 this.IsCancel = true; 130 this.Close(); 131}
投稿2019/10/16 05:42
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。