none
MoveFileW で MAX_PATH文字以上のファイルをリネームしたい RRS feed

  • 質問

  • MoveFileW で MAX_PATH文字以上のファイルをリネームしたいのですが、エラーコード3(ERROR_PATH_NOT_FOUND/指定されたパスが見つかりません。)となります。

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa365239(v=vs.85).aspx

    上のページに、パスの頭に「\\?\」を付ける必要があるとの記述があったので、以下の様にしたのですが、エラーコード3のままでした。短いパス名でもエラーコード3となるので、パスの頭の「\\?\」の付け方が良くない様な気がするのですが、原因が分かりません。 解決法をご存じの方はお教えください。

        wchar_t from[32000] = L"";
        wchar_t to[32000] = L"";
        wcscat(from, L"\\\\?\\");
        wcscat(from, (長いファイル名));
        wcscat(to, L"\\\\?\\");
        wcscat(to, (長いファイル名));
        MoveFile(from, to);

    2013年5月16日 6:37

回答

  • 仲澤@失業者さんの挙げている「4 完全パス」は本当に大丈夫でしょうか?

    \\?\C:\Windows\notepad.exe

    のようにドライブ名から始まっていますか? もしくはファイル共有の場合

    \\?\UNC\server\share

    とする必要があります。サーバ名の手前のバックスラッシュは1つです。

    C:/Windows/notepad.exe

    のようにスラッシュを使用することができますが、\\?\を付けた場合はバックスラッシュの必要があります。

    Maximum Path Length Limitationを再度確認することをお勧めします。

    • 回答としてマーク HiroXXX 2013年5月17日 4:38
    2013年5月17日 1:46

すべての返信

  • コードに問題はなさそうです。
    短いパスでも ERROR_PATH_NOT_FOUND = 3 が戻るとすると、
    その「(長いファイル名)」に問題があると考えられます。

     1.提示のコードでは、「from」「to」は同一のファイルパス
      になりますが、実際のコードでは異なるパスにしてありますよね(確認)。

     2.MoveFile( from, to)でブレークして、両者をウォッチして見ましょう。
      ウォッチに from to を追加して、その行を選択しておき、Ctrl+C で
      クリップボードにコピーし、メモ帳などに貼り付けて確認しましょう。

     3.コピーと異なりMoveFile()が、成功すると from側のファイルは
       無くなる点に注意しましょう。つまり、毎回from側を用意する必要があります。

     4.from to 共、ドライブを含む完全パスでやりましょう。

    2013年5月16日 7:45
  • ご回答ありがとうございます。 ご指摘の1~4は問題ありません。

    今までアプリケーションで実行していたのですが、今回はMoveFileだけの小さなプログラムで実験しました。

    短いファイル名でMoveFileが正常にリネームされることを確認後、fromとtoの頭に L"\\\\?\\" を付けたところ、エラーコード2(指定されたファイルが見つかりません)となりました。

    未だ原因がつかめない状況です。

    2013年5月17日 1:12
  • 安直に以下のコードを書いた場合、問題なく完了しました。
    from や to のパスの書き方か、OS の違いかな??
    ※Windows 8 Pro (x64) にて実施。

    DWORD dwResult = ::MoveFileW(
     L"\\\\?\\F:\\tmp\\MoveFile\\src\\1234567890123456789012345678901234567890.txt",
     L"\\\\?\\F:\\tmp\\MoveFile\\dst\\LONGPATHLONGPATHLONGPATHLONGPATHLONGPATH"
     L"LONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATH"
     L"LONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATHLONGPATH"
     L"LONGPATHLONGPATHLONGPATHLONGPATHLONGPATH\\"
     L"1234567890123456789012345678901234567890.txt");

    2013年5月17日 1:39
    モデレータ
  • 仲澤@失業者さんの挙げている「4 完全パス」は本当に大丈夫でしょうか?

    \\?\C:\Windows\notepad.exe

    のようにドライブ名から始まっていますか? もしくはファイル共有の場合

    \\?\UNC\server\share

    とする必要があります。サーバ名の手前のバックスラッシュは1つです。

    C:/Windows/notepad.exe

    のようにスラッシュを使用することができますが、\\?\を付けた場合はバックスラッシュの必要があります。

    Maximum Path Length Limitationを再度確認することをお勧めします。

    • 回答としてマーク HiroXXX 2013年5月17日 4:38
    2013年5月17日 1:46
  • ですか。
    次のコードをコピペして試してみてはどうでしょう。
    c:\Temp\Test.txtは、テストをはじめる前に用意しておいてください。

    wchar_t from[32000] = L"";
    wchar_t to[32000] = L"";
    wcscat(from, L"\\\\?\\");
    wcscat(from, L"C:\\Temp\\Test.txt");
    wcscat(to, L"\\\\?\\");
    wcscat(to, L"C:\\Temp\\Test.xxx");
    MoveFileW(from, to);

    これは、自分の環境では正常に動作するコードです。
    このコードの実行に、

     1.成功した場合
      ->やはり(長いファイル名)部分に問題がある。

     2.失敗した場合
      ->前提としている環境に問題がある。

    と考えられます。

    2013年5月17日 1:51
  • 皆様、いろいろ情報提供ありがとうございました。

    パスを「スラッシュ区切り」で記述していたのが原因でした。「バックスラッシュ」区切りで記述したところ正常にリネームできました。 確認不足で申し訳ございません。

    2013年5月17日 4:46