Domanda

SFONDO

Ho bisogno di scrivere uno strumento utilizzando .NET versione 2.0 a più alto (usando qualcosa dallo scaffale non è un'opzione per questo client per motivi politici, commerciali, e la riservatezza / di fiducia) per migrare i file da un server ad un altro sopra la Rete. I server sono file server per le squadre locali, e alcune cartelle del team devono essere migrati ad altri server per facilitare una riorganizzazione. L'idea di base è che leggiamo ogni file e lo streaming attraverso la rete fuori orario e dopo pochi giorni i dati saranno migrati. I permessi dei file devono essere conservati. Come questo richiederà un paio di giorni (si parla fino a diversi gigabyte di dati, per alcune squadre), abbiamo bisogno di scorrere i file ogni sera e confrontare le date di modifica e aggiornare quelli modificati. La teoria è che alla fine il nuovo server avrà una copia aggiornata dei file e gli utenti possono passare al nuovo server. E ', naturalmente, non del tutto questo semplice, ma abbiamo un progetto che pensiamo dovrebbe funzionare:)

IL PROBLEMA

Quindi, in teoria abbiamo Basta aprire il file, lo streaming attraverso la rete, e scriverlo all'altra estremità, giusto? :)

Purtroppo, sui server stessi, le condivisioni di file sono stati creati in percorsi delle cartelle come ad esempio:

  

D: \ Azioni Data \ squadra \ DIVISIONE \ DIPARTIMENTO \ NOME DEL TEAM - potrebbe essere abbastanza lungo \

Per ciascun utente, questo percorso è mappato a un'unità, ad esempio sarebbe condivisa come \\ SERVER \ TeamName e mappato alla T:. Unità

Questo ha causato la situazione in cui i file come visibile dalla T: unità sono all'interno della limitazione MAX_PATH, tuttavia se visti in locale sul server stesso, vanno ben al di là di esso. Non possiamo accedere ai file utilizzando le condivisioni di rete come questo strumento deve essere generica, per funzionare su centinaia di questi server, e non c'è alcun modo standard per dire che le condivisioni di file sono quelli che dovremmo essere in movimento e quelle che non lo sono - non c'è non standard di denominazione convenzione ancora. Inoltre, di tanto in tanto ci sono sotto-azioni di altri azioni e così abbiamo superano il limite MAX_PATH due volte!

Sono consapevole della soluzione per specificare i percorsi che utilizzano il "\\? \" Prefisso, che tratta il percorso come un percorso UNC e consente un massimo teorico di 32 KB caratteri.

Questa soluzione viene implementata a livello di API Win32, lo spazio dei nomi System.IO è (soprattutto) fondamentalmente solo un sottile wrapper per funzioni API Win32 native, tuttavia Microsoft ha "utilmente" validazione implementato in più (errato) prima di consegnare la chiamata off alle API. In questo caso, il .NET Framework sta rifiutando il percorso, perché sostiene che '?' è un personaggio percorso non valido.

Quindi la mia domanda è ... c'è un modo che non ho pensato che mi permetterà di lavorare intorno a questo senza dover riscrivere completamente la quasi totalità dello spazio dei nomi System.IO, facendo un carico di P / Invoke chiamate , solo per rimuovere questo fastidioso convalida?

È stato utile?

Soluzione

Il team BCL ha fatto una serie di 3 parte su esattamente perché queste scelte sono state fatte e quali sono i arounds di lavoro sono. Se non avete letto che ancora vi suggerisco di fare come è una grande fonte di informazioni sul tema

Altri suggerimenti

Mi sono imbattuto in un soluzione di terze parti che possono aiutare: AlphaFS .

Dovrebbe essere abbastanza facile da aggirare questa limitazione con un po 'di piattaforma di invoke, supponendo che il software disponga delle autorizzazioni necessarie:

[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
    }
}

Si potrebbe provare a ridurre il percorso mappando una directory padre utilizzando Subst.exe (o qualunque API utilizza internamente):

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

Idealmente si sarebbe mappare via il più possibile del percorso.

Ho avuto strutture di directory di successo l'eliminazione utilizzando sotto piccolo script. pushd utilizza il formato UNC che vi dà 32K invece di 260 limitazione

set "folder=\\SERVER\SHARE\DIVISION\DEPARTMENT\NAME OF TEAM - COULD BE FAIRLY LONG\" 
pushd "%folder%"
for /d %%i in ("*") do rmdir "%%i" /s /q
popd
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top