9

バックグラウンド

あるサーバーから別のサーバーにネットワーク経由でファイルを移行するには、最大で .NET バージョン 2.0 を使用するツールを作成する必要があります (このクライアントでは、政治的、商業的、および機密性/信頼上の理由から、市販のものを使用することはできません)。サーバーはローカル チーム用のファイル サーバーであり、再編成を容易にするために、特定のチーム フォルダーを他のサーバーに移行する必要があります。基本的な考え方は、各ファイルを読み取り、数時間のうちにネットワーク経由でストリーミングし、数日後にデータが移行されるというものです。ファイルのアクセス許可を保持する必要があります。これには数日かかるため (一部のチームでは最大で数ギガバイトのデータについて話している)、毎晩ファイルを繰り返し処理し、変更日を比較して、変更された日付を更新する必要があります。理論的には、最終的に新しいサーバーにはファイルの最新のコピーがあり、ユーザーは新しいサーバーに切り替えることができます。もちろん、これほど単純ではありませんが、機能すると思われる設計があります:)

問題

理論的には、ファイルを開いてネットワーク経由でストリーミングし、反対側で書き込むだけですよね? :)

残念ながら、サーバー自体では、ファイル共有は次のようなフォルダー パスに作成されました。

D:\Data\Team Shares\DIVISION\DEPARTMENT\NAME OF TEAM - かなり長い可能性があります\

ユーザーごとに、このパスはドライブにマップされます。たとえば、\\SERVER\TEAMNAME として共有され、T: ドライブにマップされます。

これにより、T: ドライブから表示されるファイルがMAX_PATH制限内にあるという状況が発生しましたが、サーバー自体でローカルに表示すると、制限をはるかに超えてしまいます。ネットワーク共有を使用してファイルにアクセスすることはできません。このツールは、何百ものこれらのサーバーで実行するために汎用的である必要があり、どのファイル共有が移動する必要があるか、そうでないかを判断する標準的な方法がないためです。命名規則標準すらありません。また、たまに他のシェアのサブシェアもあり、MAX_PATH制限を2倍オーバー!

「\\?\」プレフィックスを使用してパスを指定する回避策を認識しています。これにより、パスが UNC パスとして扱われ、理論上の最大文字数は 32k 文字になります。

この回避策は Win32 API レベルで実装されています。System.IO 名前空間は (ほとんどの場合) 基本的にネイティブの Win32 API 関数の薄いラッパーにすぎませんが、Microsoft は呼び出しを API に渡す前に追加の (間違った) 検証を「役立つように」実装しています。 . この場合、.NET Framework はパスを拒否しています。は無効なパス文字です。

だから私の質問は...私が考えていなかった方法で、System.IO名前空間のほぼ全体を完全に書き直し、P/Invoke呼び出しを大量に行うことなく、これを回避できる方法はありますか?この厄介な検証を削除しますか?

4

5 に答える 5

5

BCL チームは、これらの選択が行われた正確な理由と回避策について、3 部構成のシリーズを作成しました。まだ読んでいない場合は、このテーマに関する優れた情報源であるため、読むことをお勧めします

于 2009-07-27T21:12:14.523 に答える
4

役立つ可能性のあるサードパーティのソリューションであるAlphaFSに遭遇しました。

于 2009-08-25T23:34:10.030 に答える
1

ソフトウェアに必要なアクセス許可があると仮定すると、プラットフォームを少し呼び出すだけで、この制限を簡単に回避できます。

[DllImport("kernel32.dll", SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
  uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
  uint dwFlagsAndAttributes, IntPtr hTemplateFile);

// Must close/dispose handle separately from FileStream since it's not owned by
// that object when passed to constructor.
using (SafeFileHandle h = CreateFile(longUncPath, GENERIC_WRITE, 0, IntPtr.Zero, 
       OPEN_EXISTING, 0, IntPtr.Zero))
{
    using (var fs = new FileStream(h, FileAccess.Read))
    {
        // operations with FileStream object
    }
}
于 2009-07-27T21:17:12.377 に答える
0

subst.exe (または内部で使用する API) を使用して親ディレクトリをマッピングすることにより、パスを短くすることができます。

http://www.makeuseof.com/tag/how-to-map-a-local-windows-folder-to-a-drive-letter/

理想的には、パスからできるだけ離れてマップします。

于 2011-10-26T00:59:49.860 に答える