Sign in to follow this  
Geovani

Tratar Erros De Api Do Windows: Shellapi

Recommended Posts

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

Share this post


Link to post
Share on other sites

use o try e except

exemplo

try

faça algo

except

faça algo se houver erro

end;

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites

ah certo ashushau

então tenta em flags adicionar

FOF_SILENT

ficando

fFlags := FOF_NOCONFIRMATION or FOF_SILENT;

abraço

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

isso boa Thales ;)

ahusahu eu nem testei só usei essa flag uma vez pra deletar arquivo!

abraços

Share this post


Link to post
Share on other sites

Valeu Thales!! Deu certo!!

Seria interessante saber qual é o arquivo que deu erro...

Mais uma dúvida, será que tem como pegar a MSN de erro?

Desde já !! Valeu!!!!

Grato

Geovani

Share this post


Link to post
Share on other sites

É, seria interessante pegar esse erro mesmo. É possivel que naquele registro seja reportado alguma coisa. Vou dar uma olhada na documentação e mais tarde eu posto.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
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

[email protected]

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this