una - liberar archivo en uso c#
Acceder a archivos más allá de MAX_PATH en C#/. NET (5)
Debería ser bastante fácil evitar esta limitación con un poco de invocación de plataforma, suponiendo que su software tenga 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
}
}
FONDO
Necesito escribir una herramienta usando .NET versión 2.0 al más alto (usar algo de fábrica no es una opción para este cliente por motivos políticos, comerciales y de confidencialidad / confianza) para migrar archivos de un servidor a otro a través de la red. Los servidores son servidores de archivos para equipos locales y ciertas carpetas del equipo deben migrarse a otros servidores para facilitar una reorganización. La idea básica es leer cada archivo y transmitirlo en la red en horas y luego de unos días, los datos se migrarán. Los permisos de archivos deben conservarse. Como esto llevará algunos días (estamos hablando de varios gigabytes de datos, para algunos equipos), necesitamos iterar sobre los archivos cada noche y comparar las fechas de modificación y actualizar las que han cambiado. La teoría es que, finalmente, el nuevo servidor tendrá una copia actualizada de los archivos y los usuarios podrán cambiar al nuevo servidor. Por supuesto, no es tan simple, pero tenemos un diseño que creemos que debería funcionar :)
EL PROBLEMA
Entonces, en teoría, simplemente abrimos el archivo, lo transmitimos a través de la red y lo escribimos en el otro extremo, ¿verdad? :)
Desafortunadamente, en los propios servidores, los archivos compartidos se crearon en las rutas de las carpetas, como:
D: / Data / Team Shares / DIVISION / DEPARTMENT / NAME OF TEAM - PODRÍA SER MUY LARGO /
Para cada usuario, esta ruta se asigna a una unidad, por ejemplo, se compartiría como // SERVER / TEAMNAME y se mapearía en la unidad T :.
Esto ha provocado que la situación en la que los archivos visibles desde la unidad T: estén dentro de la limitación MAX_PATH
, sin embargo, cuando se ven localmente en el servidor, van mucho más allá. No podemos acceder a los archivos utilizando los recursos compartidos de red ya que esta herramienta debe ser genérica, para ejecutarse en cientos de estos servidores, y no hay una forma estándar de decir qué archivos compartidos son los que debemos mover y los que no lo están - hay sin nomenclatura estándar de convención, incluso. Además, ocasionalmente hay MAX_PATH
de otras acciones y, por lo tanto, ¡ MAX_PATH
límite de MAX_PATH
dos veces!
Soy consciente de la solución para especificar rutas usando el prefijo "//? /", Que trata la ruta como una ruta UNC y permite un máximo teórico de 32k caracteres.
Esta solución se implementa en el nivel API de Win32, el espacio de nombres System.IO es (básicamente) básicamente una envoltura delgada alrededor de las funciones API nativas de Win32; sin embargo, Microsoft ha implementado "útilmente" la validación adicional (incorrecta) antes de entregar la llamada a la API . En este caso, .NET Framework rechaza la ruta porque afirma que ''?'' es un caracter de ruta inválido
Así que mi pregunta es ... ¿hay alguna manera en que no haya pensado que me permita solucionar este problema sin tener que reescribir completamente el espacio de nombres System.IO, haciendo un montón de llamadas P / Invoke, solo para eliminar esta validación molesto?
El equipo de BCL hizo una serie de 3 partes sobre exactamente por qué se hicieron estas elecciones y cuáles son las alternativas. Si aún no lo ha leído, le sugiero que lo haga, ya que es una gran fuente de información sobre el tema
He tenido éxito eliminando las estructuras de directorios usando la siguiente secuencia de comandos pequeña. 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
Me encontré con una solución de terceros que podría ayudar: AlphaFS .
Podría intentar acortar la ruta mapeando un directorio padre usando subst.exe (o las API que usa internamente):
http://www.makeuseof.com/tag/how-to-map-a-local-windows-folder-to-a-drive-letter/
Lo ideal es que trazar el mapa lo más posible del camino.