質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

0回答

3063閲覧

SHFileOperationはネットワークパスを含んでいると失敗するのでしょうか?

dem0nmichik0

総合スコア37

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/07/08 06:59

編集2021/07/10 11:54

###実現したいこと
SHFileOperation()のWindowsAPIを使って「HUB経由で接続したPCの共有フォルダからフォルダコピー(フォルダ内のファイルも)」がしたいです。

###調査してわかったこと
1.SHFileOperation()は非推奨となっており、IFileOperation()に置換したほうが良い。
(SHFileOperationからIFileOperationへの移行事例参照)
2.28th Embarcadero Developer CampのP65によるとIFileOperationはコピー先フォルダがあると失敗することやSHFileOperation()が拡張プレフィックス(?)には対応していない
3.下記操作をすると,SHFileOperation()を使ったフォルダコピーが失敗する。
0. アプリを起動して,選択画面を表示する。
0. 選択画面で「ログ表示」ボタンをクリックしてTMemoコントロールにログを表示後,「戻る」ボタンをクリックして,選択画面に戻る。
0. 選択画面で「ログ取得」ボタンをクリックして,HUB経由のフォルダを共有したPCからログを取得後,「戻る」ボタンをクリックして,選択画面に戻る。→このときはログはフォルダごとコピー成功。
0. 選択画面で「ログ表示」ボタンをクリックしてTMemoコントロールにログを表示後,「戻る」ボタンをクリックして,選択画面に戻る。
0. 3で成功したログ取得をフォルダごと削除する。
0. 選択画面で「ログ取得」ボタンをクリックして,HUB経由のフォルダを共有したPCからログを取得後,「戻る」ボタンをクリックして,選択画面に戻る。→このときはログはフォルダは作成されるが,ファイルはコピーされない。

困っていること

業務アプリでSHFileOperation()の戻り値が~~87(DE_SRC_IS_DVD)~~0x57(10進数87)(ERROR_INVALID_PARAMETER)となって、「パラメータが間違っている」と分かったので,Using SHFileOperation: What errors are occuring - Stack ...を参考に下記2つの初期化方法を試しましたが,「フォルダコピー」が失敗します。
・ SHFILEOPSTRUCT tSHFile = { 0 };
・ZeroMemory(&tSHFile, sizeof(SHFILEOPSTRUCT ));
Windows10でSHFileOperation()は使用しないほうが良いのでしょうか?ご存じの方、ご教授お願いします。

###ソース
業務アプリのため、SHFileOperationの部分の機能を真似て模擬的にテストしているアプリです。実際に問題が起きているソースではありません。問題が起きている個所は「AccessDir」のSHFileOperation()です。define定義の「****」にはユーザ名が入ります。

C++

1「Unit1.cpp」 2//--------------------------------------------------------------------------- 3 4#include <vcl.h> 5#pragma hdrstop 6 7#include "Unit1.h" 8 9#define COPY (2) 10#define SRC "\\192.168.2.1\temp\Dir\20210706\" 11#define DST "C:\Users\****\Desktop\20210706\\0\0" 12#define DELDIR "C:\Users\****\Desktop\20210706\*.*" 13//--------------------------------------------------------------------------- 14#pragma package(smart_init) 15#pragma resource "*.dfm" 16TForm1 *Form1; 17//--------------------------------------------------------------------------- 18// コンストラクタ 19__fastcall TForm1::TForm1(TComponent* Owner) 20 : TForm(Owner) 21{ 22 this->AccessMode = 0; 23} 24//--------------------------------------------------------------------------- 25// ディレクトリアクセス 26int __fastcall TForm1::AccessDir(UnicodeString src, UnicodeString dst, int mode) 27{ 28 // 変数宣言 29 int rtn; // 当関数の戻り値 30 SHFILEOPSTRUCT fs; // ファイル操作情報 31 UnicodeString str; // メッセージ文字列 32 wchar_t* Src; 33 wchar_t* Dst; 34 int srcPathSize; 35 int dstPathSize; 36 37 // 変数初期化 38 rtn = 0; 39 ZeroMemory(&fs, sizeof(SHFILEOPSTRUCT)); 40 srcPathSize = src.Length() + 2; 41 dstPathSize = dst.Length() + 2; 42 Src = new wchar_t[srcPathSize]; 43 Dst = new wchar_t[dstPathSize]; 44 45 wcscpy(Src, src.c_str()); 46 Src[srcPathSize - 1] = 0; 47 wcscpy(Dst, dst.c_str()); 48 Dst[dstPathSize - 1] = 0; 49 50 fs.hwnd = Application->Handle; 51 fs.wFunc = mode; 52 fs.pFrom = Src; 53 fs.pTo = Dst; 54 fs.fFlags = FOF_FILESONLY | FOF_NOCONFIRMMKDIR | FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION; 55 56 rtn = SHFileOperation(&fs); 57 // ファイル操作失敗の場合 58 if( rtn != 0 ) 59 { 60 if(mode == COPY) 61 { 62 str = _T("コピー失敗"); 63 } 64 else 65 { 66 str = _T("削除失敗"); 67 } 68 } 69 // ファイル操作成功の場合 70 else 71 { 72 if(mode == COPY) 73 { 74 str = _T("コピー成功"); 75 } 76 else 77 { 78 str = _T("削除成功"); 79 } 80 } 81 ShowMessage(str); 82 83 return (rtn); 84} 85//--------------------------------------------------------------------------- 86// フォルダコピーイベントハンドラ 87void __fastcall TForm1::Button1Click(TObject *Sender) 88{ 89 UnicodeString src = SRC; 90 91 src += "*.*\0\0"; 92 // アクセスモードにコピーを設定 93 this->AccessMode = COPY; 94 // ディレクトリアクセス(コピーモード) 95 AccessDir(src, DST, this->AccessMode); 96} 97//--------------------------------------------------------------------------- 98// フォルダ削除イベントハンドラ 99void __fastcall TForm1::Button2Click(TObject *Sender) 100{ 101 // アクセスモードにコピーを設定 102 this->AccessMode = DELETE; 103 // ディレクトリアクセス(コピーモード) 104 AccessDir(DELDIR, NULL, this->AccessMode); 105} 106//--------------------------------------------------------------------------- 107// フォルダコピーイベントハンドラ 108void __fastcall TForm1::Button3Click(TObject *Sender) 109{ 110 bool brtn = false; 111 UnicodeString src = SRC; 112 113 // コピー元ディレクトリが存在するかチェック 114 brtn = TDirectory::Exists(SRC); 115 // 存在する場合 116 if( brtn == true ) 117 { 118 src += "*.*\0\0"; 119 // ディレクトリコピー 120 TDirectory::Copy(src, DST); 121 } 122} 123//--------------------------------------------------------------------------- 124// フォルダ削除イベントハンドラ 125void __fastcall TForm1::Button4Click(TObject *Sender) 126{ 127 TSearchRec detaFile; // ディレクトリサーチ結果 128 int result; // FindFirsr,FindNext戻り値 129 UnicodeString FrmFile; // ファイルパス変数 130 UnicodeString FrmDir; // ディレクトリパス変数 131 132 ZeroMemory(&detaFile, sizeof(detaFile)); 133 result = 0; 134 135 // 変数初期化:入力パラメータからローカル変数に格納 136 FrmDir = DST; 137 138 // 読込元ディレクトリに\*を付加 139 FrmDir += "\*"; 140 141 // 読込先ディレクトリ内のすべてのファイル取得 142 result = FindFirst( FrmDir, faAnyFile, detaFile ); 143 144 // 取得OKの時( FindFirst,FindNext ) 145 while( result == 0 ) 146 { 147 // 取得したファイルの属性チェック(すべてのファイル) 148 if ((detaFile.Attr & faAnyFile) == detaFile.Attr) 149 { 150 // 読込先、読込元のファイルパスを入力パラメータのディレクトリパスに指定 151 FrmFile = DST; 152 153 // ファイル名称取得 154 const UnicodeString name = detaFile.Name; 155 // 取得情報がディレクトリの時 156 if(( detaFile.Attr & Sysutils::faDirectory ) != 0 ) 157 { 158 // 名前は階層を示す値か? 159 if (name == "." || name == "..") 160 { 161 // 次のファイルをサーチ 162 result = FindNext( detaFile ); 163 } 164 } 165 // ファイル名の時 166 else 167 { 168 // ファイルパスに\と取得したnameを割当 169 FrmFile += name; 170 // ファイルを削除 171 TFile::Delete(FrmFile); 172 // 次のファイルをサーチ 173 result = FindNext( detaFile ); 174 } 175 } 176 } 177 // ファイルクローズ 178 FindClose( detaFile ); 179} 180//--------------------------------------------------------------------------- 181 182「Unit1.h」 183//--------------------------------------------------------------------------- 184 185#ifndef Unit1H 186#define Unit1H 187//--------------------------------------------------------------------------- 188#include <System.Classes.hpp> 189#include <Vcl.Controls.hpp> 190#include <Vcl.StdCtrls.hpp> 191#include <Vcl.Forms.hpp> 192#include <IOUtils.hpp> 193//--------------------------------------------------------------------------- 194class TForm1 : public TForm 195{ 196__published: // IDE で管理されるコンポーネント 197 TGroupBox *GroupBox1; 198 TButton *Button1; 199 TButton *Button2; 200 TGroupBox *GroupBox2; 201 TButton *Button3; 202 TButton *Button4; 203 void __fastcall Button1Click(TObject *Sender); 204 void __fastcall Button2Click(TObject *Sender); 205 void __fastcall Button3Click(TObject *Sender); 206 void __fastcall Button4Click(TObject *Sender); 207private: // ユーザー宣言 208public: // ユーザー宣言 209 // コンストラクタ 210 __fastcall TForm1(TComponent* Owner); 211 // ディレクトリアクセス 212 int __fastcall AccessDir(UnicodeString, UnicodeString, int); 213 214 int AccessMode; // アクセスモード 215}; 216//--------------------------------------------------------------------------- 217extern PACKAGE TForm1 *Form1; 218//--------------------------------------------------------------------------- 219#endif 220 221

###開発環境
OS:Windows64bit
IDE:embarcadero 10.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問