Ir para conteúdo
Fórum Script Brasil
  • 0

Tratar Erros De Api Do Windows: Shellapi


Geovani

Pergunta

Olá pessoal!

Estou fazendo um programa de backup automático, estou usando uma função da API do windows que copia arquivos e/ou pastas com as suas subpastas, então, preciso tratar para que se acontecer algum erro, não apareça uma mensagem de erro e aguarde clicar OK para cancelar.

Não sei se existe um tratamento do tipo: se o titulo da mensagem de erro for = "Não foi possivel copiar arquivo ou pasta" então não mostra a mensagem de erro.

alguém sabe se tem como fazer o traramento acima?

Grato!

Geovani

Link para o comentário
Compartilhar em outros sites

Posts Recomendados

  • 0
use o try e except

exemplo

try

faça algo

except

faça algo se houver erro

end;

Joey, acho que ele não está se referindo a isso, acho que a função não levanta exceção, mas só mostra uma menssagem de erro.

Link para o comentário
Compartilhar em outros sites

  • 0
Guest Visitante

Desculpe, ai vai a função.

---------------------------------------------

Uses Shellapi

//COPIAR ARQUIVOS E PASTAS

Procedure CopyDir(const cFrom, cTo : string);

var

OpStruc : TSHFileOpStruct;

frombuf, tobuf : array[0..128] of Char;

begin

FillChar(frombuf, Sizeof(frombuf), 0);

FillChar(tobuf, Sizeof(tobuf), 0);

StrPCopy(frombuf, cFrom);

StrPCopy(tobuf, cTo);

with OpStruc do

begin

Wnd := Application.Handle;

wFunc := FO_COPY;

pFrom := @frombuf;

pTo := @tobuf;

fFlags := FOF_NOCONFIRMATION;

fAnyOperationsAborted := False;

hNameMappings := nil;

lpszProgressTitle := nil;

end;

ShFileOperation(OpStruc);

end;

//Exemplo: CopyDir(origem, destinot);

----------------------------------------------

Essa função acima copia arquivos e pastas.

Quando eu seleciono a pasta Documentação para copiar, a função mostra a seguinte mensagem não copiando o arquivo:

---------------------------

Erro ao copiar arquivo ou pasta

---------------------------

Não é possível copiar 03_FTI_Valoriza Taxas Diarias x Convenio x Plano: O nome do arquivo especificado é inválido ou muito extenso. Especifique outro nome.

É mostrada a mensagem acima e aguarda clicar em ok para cancelar a cópia.

Já tentei try [comando] except [comando] end; e não funciona..

alguém sabe como evitar essa mensagem?

Obrigado a todos!

Link para o comentário
Compartilhar em outros sites

  • 0

Ou então ->

fFlags := FOF_NOCONFIRMATION or FOF_NOERRORUI;

Acho que esse ultimo tem mais a ver, porque FOF_SILENT só não mostrará a caixa de progresso, enquanto FOF_NOERRORUI não mostrará o erro.

Link para o comentário
Compartilhar em outros sites

  • 0

Olha cara, eu olhei tudo aqui e não descobrí como se faz pre pegar esse erro. Talvez algum outro colega saiba.

Uma coisa que reparei. O windows é burro, não é? Quando ele tem uma lista de arquivos pra copiar como é o seu caso, e encontra um erro, ao invés de pular o arquivo e continuar copiando o que der, ele mostra uma menssagem de erro e para de copiar. Além disso essa rotina ainda tem vários incovenientes. Então acho que seria o caso de escrevermos nossas próprias rotinas de cópia de arquivos. Bom, uma rotina pra copiar um arquivo é fácil, mas já pra copiar uma pasta inteira é mais complexo porque envolve conceitos de recursividade, além de exigir variações de comportamento amplas. Eu vou tentar aqui escrever algumas rotinas para fazer essas cópias, mas não garanto nada. Caso consiga posto mais tarde.

Link para o comentário
Compartilhar em outros sites

  • 0

Amigo, escreví a função abaixo que faz a cópia e cria um TStringList com a lista de arquivos que não puderam ser copiados, espero que ajude ->

function CopyDir(sc, ds : string) : TStringList;
var
  List : TStringList;

function vldir(dr : string) : boolean;
begin
  result:=((trim(dr) <> '..') and (trim(dr) <> '.'));
end;

procedure Search(sor, des : string);
var
  Rec : TSearchRec;
  s,d : string;
begin
  ForceDirectories(des);
  if (FindFirst(sor+'\*.*',faReadOnly or faHidden or faSysFile or faDirectory or faArchive,rec)<>0) then 
  begin
    FindClose(rec);
    exit;
  end;
  while true do
  begin
    if ((rec.Attr and fadirectory)<>0) then
    begin
      if vldir(rec.Name) then
      Search(sor+'\'+rec.name,des+'\'+rec.Name)
    end else
    begin
      s:=sor+'\'+rec.name;
      d:=des+'\'+rec.name;
      if (cardinal(CopyFile(PAnsiChar(s),PAnsiChar(d),false)) = 0)
      then List.Add(s);
    end;
    if (FindNext(rec) <> 0) then
    begin
      FindClose(rec);
      break;
    end;
  end;
end;

begin
  if (sc[length(sc)] = '\') then delete(sc,length(sc),1);
  if (ds[length(ds)] = '\') then delete(ds,length(ds),1);
  if not(directoryexists(sc)) then
  begin
    result:=nil;
    exit;
  end;
  List:=TStringList.Create;
  Search(sc,ds);
  result:=list;
end;
Exemplo ->
procedure TForm1.Button1Click(Sender: TObject);
begin
  with CopyDir(edit1.Text,edit2.Text) do
  begin
    savetofile('c:\log.txt');
    free;
  end;;
end;

Assim você poderá adapta-la a suas necessidades, tipo perguntar pra substituir...etc...

Testei aqui e não apresentou nenhum problema, mas qualquer problema que ocorra não deixe de me avisar.

Link para o comentário
Compartilhar em outros sites

  • 0

Mas uma das vantagens do SHFileOperation na cópia é a barra de progresso.

Se for um arquivo ou diretório muito extenso, o usuário teria uma previsão de término, ao passo que escrevendo rotinas específicas, você teria que fazer uma recursão para saber o total de size dos arquivos e depois outra recursão para copiá-los pelo BlockRead e BlockWrite para implementar a barra.

Link para o comentário
Compartilhar em outros sites

  • 0
Mas uma das vantagens do SHFileOperation na cópia é a barra de progresso.

Se for um arquivo ou diretório muito extenso, o usuário teria uma previsão de término, ao passo que escrevendo rotinas específicas, você teria que fazer uma recursão para saber o total de size dos arquivos e depois outra recursão para copiá-los pelo BlockRead e BlockWrite para implementar a barra.

Opa, não precisa fazer BlockRead/BlockWrite não. Se ele quiser ele pode primeiro fazer uma busca para ver a somatória do tamanho dos arquivos e usar a função CopyFileEx ao invés de CopyFile, que permite o fornecimento da função de CallBack a ser notificada a cada bloco de arquivo copiado.

Link para o comentário
Compartilhar em outros sites

  • 0

Editei o código denovo, e coloquei mais um detalhezinho que estava faltando, mas a função antiga também funcionava da mesma maneira, essa só ficou mais rápida.

E o Geovani não disse se o çodigo serviu, se ele usou ou não...

Link para o comentário
Compartilhar em outros sites

  • 0

Só lembrando de uma coisa: Eu não sei como é que funciona o SHFileOperation mas esse que escreví funciona assim, por exemplo, se SC e DS forem isso ->

C:\Delphi

D:\Programas

nesse caso ele não vai criar uma pasta Delphi dentro de Programas, e sim criar uma pasta Programas, caso não exista e copiar o conteúdo de Delphi para lá. Para criar uma Pasta Delphi dentro de Programas tem que ser assim ->

C:\Delphi

D:\Programas\Delphi

Aí sim a pasta Delphi dentro de Programas vai ser igual a Delphi do c:.

A rotina cria todos os diretórios que forem necessários para copiar a pasta, nesse caso se não existir o diretório Programas ele o cría também.

Link para o comentário
Compartilhar em outros sites

  • 0

Editei o código denovo, e coloquei mais um detalhezinho que estava faltando, mas a função antiga também funcionava da mesma maneira, essa só ficou mais rápida.

E o Geovani não disse se o çodigo serviu, se ele usou ou não...

desculpe por não ter respondindo antes... você disse que editou o código de novo, você alterou aquele postado?

eu testei aquele codigo e deu o erro:

---------------------------

Project1

---------------------------

Access violation at address 00442A86 in module 'Project1.exe'. Read of address 00000000.

---------------------------

OK

---------------------------

Teria como você postar novamente?

no meu programa de backup eu salvo o erro em um memo, no final eu salvo em um arquivo, mas deixo eu me viro depois..

obrigado!

Link para o comentário
Compartilhar em outros sites

  • 0

Opa, acho que deu erro porque você forneceu diretório inexixtente como fonte, aí ele retorna nil. Tente filtrar ->

var errolog : TStringList;
begin
  errolog:=copydir(sc, ds);
  if (errolog <> nil) then
  begin
    memo1.addstrings(errolog);
    memo1.lines.savetofile(logfile);
    errolog.free;
  end;
end;

abraço.

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Thales!!

Não funciou comigo :/

eu preciso copiar arquivos e pastas, ele está apenas copiando pasta, e não está mostrando os erros no memo...

Essa ferramenta de backup que estou fazendo ela irá copiar a base de dados e a documentação para um servidor 2.

Por exemplo:

1º Backup

Origem: C:\CacheSys\Mgr\Cache.dat

Destino: \\Servidor2\C\Cachesys\Mgr\Cache.dat

obs: Nesse backup escolhi o arquivo arquivo cache.dat, porque dentro de Mgr tem varios arquivos e subpastas

2º Backup

Origem: D:\CacheDB\Clientes

Destino: \\Servidor2\D\CacheDB\Clientes

Obs Nesse backup escolhi a pasta CacheDB porque tem subpastas e dentro de cada uma tem o arquivo Cache.dat

3º Backup

Origem: D:\Documentacao

Destino: \\Servidor2\D\Documentacao

Obs: O maior problema se encontra nessa pasta, porque o pessoal aqui fica criando inumeras subpastas para detalhar cada coisa, então existem arquivos a função não consegue copiar devido ao tamanho do arquivo.

Onde aparece o erro:

---------------------------

Erro ao copiar arquivo ou pasta

---------------------------

Não é possível copiar 03_FTI_Valoriza Taxas Diarias x Convenio x Plano: O nome do arquivo especificado é inválido ou muito extenso.

Especifique outro nome.

---------------------------

OK

---------------------------

Tem como eu enviar um exemplo para o seu email?

abraço e obrigado!

Link para o comentário
Compartilhar em outros sites

  • 0
Por exemplo:

1º Backup

Origem: C:\CacheSys\Mgr\Cache.dat

Destino: \\Servidor2\C\Cachesys\Mgr\Cache.dat

Essa função não pode ser chamada com nome de arquivo porque foi escrita pra copiar pastas inteiras. Testei várias vezes aqui e em todas funcionou perfeitamente.

Essa ferramenta de backup que estou fazendo ela irá copiar a base de dados e a documentação para um servidor 2.

então você quer copiar dados de um computador pro outro, aí pode ser que a função CopyFile não funcione, vou tentar adaptar com CopyFileEx.

Obs: O maior problema se encontra nessa pasta, porque o pessoal aqui fica criando inumeras subpastas para detalhar cada coisa, então existem arquivos a função não consegue copiar devido ao tamanho do arquivo.

É, essa função tem uma limitação quanto ao tamanho do nome do arquivo, a CopyFileEx não.

Tem como eu enviar um exemplo para o seu email?

Meu email

thalespo@terra.com.br

Link para o comentário
Compartilhar em outros sites

  • 0

Geovani, tenta agora ->

function CopyDir(sc, ds : string) : TStringList;
var
  List : TStringList;

function vldir(dr : string) : boolean;
begin
  result:=((trim(dr) <> '..') and (trim(dr) <> '.'));
end;

procedure Search(sor, des : string);
var
  Rec : TSearchRec;
  s,d : string;
  __cancel : BOOL;
begin
  __Cancel := false;
  ForceDirectories(des);
  if (FindFirst(sor+'\*.*',faReadOnly or faanyfile or favolumeid or faHidden or faSysFile or faDirectory or faArchive,rec)<>0) then
  begin
    FindClose(rec);
    exit;
  end;
  while true do
  begin
    if ((rec.Attr and fadirectory)<>0) then
    begin
      if vldir(rec.Name) then
      Search(sor+'\'+rec.name,des+'\'+rec.Name)
    end else
    begin
      s:=sor+'\'+rec.name;
      d:=des+'\'+rec.name;
      if (cardinal(CopyFileEx(PAnsiChar(s),PAnsiChar(d),0,0,@__cancel,1)) = 0)
      then List.Add(s);
    end;
    if (FindNext(rec) <> 0) then
    begin
      FindClose(rec);
      break;
    end;
  end;
end;

begin
  if (sc[length(sc)] = '\') then delete(sc,length(sc),1);
  if (ds[length(ds)] = '\') then delete(ds,length(ds),1);
  if not(directoryexists(sc)) then
  begin
    result:=nil;
    exit;
  end;
  List:=TStringList.Create;
  Search(sc,ds);
  result:=list;
end;

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...