Question

CONTEXTE

Je dois écrire un outil en utilisant la version .NET 2.0 au plus haut (en utilisant quelque chose sur l'étagère est pas une option pour ce client, pour des raisons politiques, commerciales et de confidentialité / confiance) pour migrer les fichiers d'un serveur à un autre sur la réseau. Les serveurs sont des serveurs de fichiers pour les équipes locales, et certains dossiers de l'équipe doivent migrer vers d'autres serveurs pour faciliter une réorganisation. L'idée de base est que nous lisons chaque fichier et de flux sur le réseau en dehors des heures et après quelques jours, les données seront migrés. Les autorisations de fichiers doivent être conservés. Comme cela prendra quelques jours (nous parlons à plusieurs gigaoctets de données, pour certaines équipes), nous avons besoin de parcourir les fichiers chaque nuit et comparer les dates de modification et mettre à jour ceux qui ont changé. La théorie est que finalement le nouveau serveur aura une copie à jour des fichiers et les utilisateurs peuvent basculer vers le nouveau serveur. Il est bien sûr pas tout à fait ce simple, mais nous avons une conception que nous pensons devrait fonctionner:)

PROBLÈME

Donc, en théorie que nous venons d'ouvrir le fichier, le diffuser sur le réseau, et l'écrire à l'autre bout, à droite? :)

Malheureusement, sur les serveurs eux-mêmes, les partages de fichiers ont été créés à des chemins de dossier tels que:

  

D: \ Data \ actions équipe \ DIVISION \ SERVICE \ NOM DE L'ÉQUIPE - SERAIT LONG ASSEZ \

Pour chaque utilisateur, ce chemin est mappée sur un lecteur, par exemple, il serait partagé en tant que \\ SERVER \ teamname et mis en correspondance avec le T:. Lecteur

Cela a provoqué la situation dans laquelle les fichiers comme visible du T: entraînement sont dans la limite de MAX_PATH, mais lorsqu'on regarde localement sur le serveur lui-même, ils vont bien au-delà. Nous ne pouvons pas accéder aux fichiers en utilisant les partages réseau que cet outil doit être générique, pour fonctionner sur des centaines de ces serveurs, et il n'y a aucun moyen standard de dire que les partages de fichiers sont ceux que nous devrions aller et ceux qui ne sont pas - il y a nommant pas même norme de convention. De plus, de temps en temps il y a des sous-actions d'autres actions et nous dépassent la limite de MAX_PATH deux fois plus!

Je suis au courant de la solution de contournement pour spécifier les chemins en utilisant le préfixe « \\? \ », Qui traite le chemin comme un chemin UNC et permet un maximum théorique de 32k caractères.

Cette solution de contournement est mis en œuvre au niveau de l'API Win32, l'espace de noms System.IO est (la plupart du temps) fondamentalement juste une enveloppe mince autour des fonctions API Win32 natives, mais la validation Microsoft ont « obligeamment » supplémentaire (incorrect) mis en œuvre avant de passer l'appel de à l'API. Dans ce cas, le .NET Framework rejette le chemin parce qu'il prétend que «? est un caractère de chemin non valide.

Alors ma question est ... est-il une manière que je ne l'ai pas pensé à cela me permettra de travailler autour de cela sans avoir à réécrire complètement la presque totalité namespace System.IO, ce qui rend une charge d'appels P / Invoke , pour supprimer cette validation ennuyeux?

Était-ce utile?

La solution

L'équipe BCL a fait une série en 3 parties exactement pourquoi ces choix ont été faits et ce que les contournements de travail sont. Si vous avez lu pas encore, je vous suggère de faire comme il est une excellente source d'information sur le sujet

Autres conseils

Je suis tombé sur une solution tierce qui peut aider: AlphaFS .

Il devrait être assez facile à contourner cette limitation avec un peu de Invoke de plate-forme, en supposant que votre logiciel dispose des autorisations nécessaires:

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

Vous pouvez essayer de raccourcir le chemin en traçant un répertoire parent à l'aide Subst.exe (ou tout autre API qu'il utilise en interne):

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

Idéalement, vous voulez mapper loin, autant que possible du chemin.

J'ai eu du succès suppression de structures de répertoires à l'aide de petit script ci-dessous. pushd utilise le format UNC qui vous donne 32K au lieu de 260 limitation

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top