Pregunta

Antecedentes

Tengo que escribir una herramienta utilizando .NET versión 2.0 en el más alto (el uso de algo fuera de la plataforma no es una opción para este cliente por razones políticas, comerciales y confidencialidad / confianza) para migrar archivos de un servidor a otro a través de la red. Los servidores son servidores de archivos para los equipos locales, y ciertas carpetas del equipo necesario migrar a otros servidores para facilitar una reorganización. La idea básica es que leemos cada archivo y corriente a través de la red fuera de las horas y al cabo de unos días se migrarán los datos. Los permisos de archivo deben ser preservados. Ya que esto tardará unos días (estamos hablando de hasta varios gigabytes de datos, para algunos equipos), necesitamos iterar sobre los archivos cada noche y comparar las fechas de modificación y actualización de los que han cambiado. La teoría es que, finalmente, el nuevo servidor tendrá una copia actualizada de los archivos y los usuarios pueden cambiar al nuevo servidor. Es, por supuesto, no es este sencillo, pero tenemos un diseño que pensamos debería funcionar:)

EL PROBLEMA

Por lo tanto, en teoría, basta con abrir el archivo, transmitir por la red, y escribirlo en el otro extremo, ¿verdad? :)

Por desgracia, en los servidores de sí mismos, los recursos compartidos de archivos fueron creados en las rutas de carpetas como por ejemplo:

  

D: \ Data \ Acciones Equipo \ DIVISIÓN \ DEPARTAMENTO \ NOMBRE DE EQUIPO - podría ser bastante largo \

Para cada usuario, este camino está asignada a una unidad, por ejemplo, podría ser compartida como \\ SERVIDOR \ teamname y se asigna a la T:. La unidad

Esto ha provocado que la situación en la que los archivos como visibles desde el T: unidad están dentro de la limitación MAX_PATH, sin embargo cuando se ve de forma local en el propio servidor, que van mucho más allá de ella. No podemos acceder a los archivos utilizando los recursos compartidos de red ya que esta herramienta debe ser genérico, para ejecutarse en cientos de estos servidores, y no hay forma estándar para decir qué partes del archivo son los que debe estar en movimiento y las que no lo son - no hay ninguna norma de denominación de convenciones, incluso. Además, de vez en cuando hay sub-acciones de otras acciones y así que exceden el límite MAX_PATH por partida doble!

Soy consciente de la solución para especificar las rutas utilizando el "\\? \" Prefijo, que trata a la ruta como una ruta UNC y permite un máximo teórico de 32 k caracteres.

Esta solución se implementa a nivel de API de Win32, el espacio de nombres System.IO es (en su mayoría), básicamente, sólo un envoltorio delgado alrededor funciones nativas Win32 API, sin embargo Microsoft tiene "amablemente" validación adicional implementado (incorrecta) antes de entregar la llamada fuera a la API. En este caso, el .NET Framework está rechazando el camino, ya que afirma que '?' es un carácter ruta no válida.

Así que mi pregunta es ... ¿hay alguna manera que no he pensado en eso me permitirá evitar este sin tener que reescribir por completo la casi totalidad del espacio de nombres System.IO, haciendo una carga de P / Invoke llamadas , sólo para eliminar esta validación molesto?

¿Fue útil?

Solución

El equipo BCL hizo una serie de 3 partes sobre exactamente por qué se hicieron estas opciones y lo que los arounds de trabajo son. Si usted no ha leído que aún le sugiero que haga, ya que es una gran fuente de información sobre el tema

Otros consejos

Me encontré con una solución de terceros que pueden ayudar: AlphaFS .

Debe ser bastante fácil de evitar esta limitación con un poco de invocación de plataforma, asumiendo que su software tiene los permisos necesarios:

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

Usted podría tratar de acortar la ruta mediante la asignación de un directorio principal utilizando Subst.exe (o cualquier API que utiliza internamente):

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

Lo ideal sería asignar distancia lo más posible de la ruta.

He tenido éxito la eliminación de las estructuras de directorio mediante el siguiente pequeño script. pushd utiliza el formato UNC que le da 32K en lugar de 260 limitación

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top