Pergunta

FUNDO

Preciso escrever uma ferramenta usando o .NET versão 2.0 no mais alto (usar algo fora da prateleira não é uma opção para esse cliente por razões políticas, comerciais e de confidencialidade/confiança) para migrar arquivos de um servidor para outro sobre a rede. Os servidores são servidores de arquivo para equipes locais, e certas pastas de equipe precisam ser migradas para outros servidores para facilitar uma reorganização. A idéia básica é que lemos cada arquivo e transmitem -o pela rede fora de horas e, após alguns dias, os dados serão migrados. As permissões de arquivo precisam ser preservadas. Como isso levará alguns dias (estamos conversando com vários gigabytes de dados, para algumas equipes), precisamos iterar os arquivos a cada noite e comparar as datas de modificação e atualizar aqueles que mudaram. A teoria é que, eventualmente, o novo servidor terá uma cópia atualizada dos arquivos e os usuários podem mudar para o novo servidor. Obviamente, não é tão simples, mas temos um design que achamos que deveriam funcionar :)

O PROBLEMA

Então, em teoria, apenas abrimos o arquivo, transmitem -o pela rede e o escrevemos do outro lado, certo? :)

Infelizmente, nos próprios servidores, os compartilhamentos de arquivos foram criados em caminhos de pastas como:

D: Data Team ações Divisão Departamento Nome da equipe - poderia ser bastante longo

Para cada usuário, esse caminho é mapeado para uma unidade, por exemplo, ele seria compartilhado como server TeamName e mapeado para a unidade T:.

Isso causou a situação em que os arquivos são visíveis da unidade T: estão dentro do MAX_PATH Limitação, no entanto, quando visualizada localmente no próprio servidor, eles vão muito além dele. Não podemos acessar os arquivos usando os compartilhamentos de rede, pois essa ferramenta precisa ser genérica, para executar centenas desses servidores, e não há uma maneira padrão de dizer quais compartilhamentos de arquivos são aqueles que devemos nos mudar e os que não são - existe Nenhum padrão de convenção de nomenclatura mesmo. Além disso, ocasionalmente, existem submaras de outras ações e, portanto, excedemos o MAX_PATH Limite duas vezes!

Estou ciente da solução alternativa para especificar caminhos usando o prefixo "? ", Que trata o caminho como um caminho UNC e permite um máximo teórico de caracteres de 32k.

Esta solução alternativa é implementada no nível da API Win32, o espaço de nome System.io é (principalmente) basicamente apenas um invólucro fino em torno das funções nativas da API Win32, no entanto, a Microsoft implementou a validação extra (incorreta) antes de entregar a chamada para a API . Nesse caso, a estrutura .NET está rejeitando o caminho porque afirma que '?' é um caráter de caminho inválido.

Então, minha pergunta é ... existe uma maneira de não pensar que me permitirá contornar isso sem ter que reescrever completamente o espaço de nome quase todo o sistema.io, fazendo uma carga de chamadas P/Invoke, apenas para Remover esta validação irritante?

Foi útil?

Solução

The BCL team did a 3 part series on exactly why these choices were made and what the work arounds are. If you haven't read that yet I suggest you do as it's a great source of information on the subject

Outras dicas

I ran into one third-party solution that may help: AlphaFS.

It should be fairly easy to work around this limitation with a bit of platform invoke, assuming your software has the necessary permissions:

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

You could try shortening the path by mapping a parent directory using subst.exe (or whatever APIs it uses internally):

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

Ideally you'd map away as much as possible of the path.

I have had success deleting directory structures using below small script. pushd uses UNC format which gives you 32K instead of 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top