Z Delphi do BCB - błąd krytyczny

0

Witam,

jak pisałem w innym temacie - przepisuję posty program z Delphi do BCB. Zadanie programu to łączenie się z serwerem FTP i pobieranie listy plików i porozdzielanie ich osobno na listę folderów i osobno na listę katalogów. Jako metodę rozdzielania przyjąłem, że badane jest czy w nazwie pliku jest kropka. Jeśli nie to przyjmuję że jest to katalog a jeśli tak to przyjmuję że jest to plik. Może mało pomysłowe ale zawsze. Ale nie w tym rzecz. Chodzi o to, że w kod w Delphi kompiluje się poprawnie. W BCB również, jednak w BCB przy pobieraniu listy plików pokazuje się bład krytyczny "Access violation". Podejrzewam że źle tworze obiekt FTP ale czekam na Wasze propozycje. Zamieszczam kod Delphi i przetłumaczony przeze mnie kod CPP:

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j:integer;
  mamKropke: boolean;
  ListaFTP, ListaPlikow, ListaKatalogow: TStringList;
  FTP: TIdFTP;
begin
  ListaFTP       := TStringList.Create;
  ListaPlikow    := TStringList.Create;
  ListaKatalogow := TStringList.Create;

FTP := TIdFTP.Create(nil);
  FTP.Host := 'host';
  FTP.Username := 'username';
  FTP.Password := 'password';
  FTP.Passive := true;

  FTP.Connect;
  if ftp.Connected = true then
  begin
     ShowMessage('Polaczylem sie');
     ftp.List(ListaFTP, '', false);
  end
  else
  begin
     ShowMessage('Nie polaczylem sie');
  end;
FTP.Free;

mamKropke := false;

  for i := 0 to listaftp.Count-1 do
  begin
     for j := 0 to length(listaFTP.Strings[i]) do
     begin
        if (listaFTP.Strings[i][j] = '.') then
        begin
           mamKropke := true;
           ListaPlikow.Add(listaFTP.Strings[i]);
           mamkropke := false;//jak juz umieszcze na liscie to zmieniam zmienna
           break;
        end;
        if (j = length(listaFTP.Strings[i])) and (mamKropke = false) then //jesli wciaz nie ma kropy a robie teraz ostatnia literke to...
        begin
           ListaKatalogow.Add(listaFTP.Strings[i]);
        end;
     end;

  end;
  Katalogi.Text := ListaKatalogow.Text;
  Pliki.Text := ListaPlikow.Text;

  ListaFTP.Free;
  ListaPlikow.Free;
  ListaKatalogow.Free;

i kod CPP:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        //zmienne lokalne:
        bool mamKropke;

        TStringList *ListaFTP = new TStringList;
        TStringList *ListaPlikow = new TStringList;
        TStringList *ListaKatalogow = new TStringList;
        TIdFTP *FTP = new TIdFTP (this);

        FTP->Host = "host";
        FTP->Username = "username";
        FTP->Password = "password";
        FTP->Passive = true;



        try
        {
            FTP->Connect();
            if (FTP->Connected())
            {
               ShowMessage("Połączono!");
               FTP->List(ListaFTP, "", false);
            }
            else
            {
               ShowMessage("Nie udało mi się połączyc!");
            }
        }
        catch (Exception &VCLException)
        {
            throw new Exception("Błąd o kodzie: " + VCLException.Message);
        };
        FTP->Free();//juz nie bedziesz potrzebny :)

        mamKropke = false;

        for (int i = 0; ListaFTP->Count-1; i++)
        {
           for (int j = 0; ListaFTP->Strings[i].Length(); j++)
           {
               if (ListaFTP->Strings[i][j] == '.') //tutaj wpisujesz w apostrofach
               {
                  mamKropke = true;
                  ListaPlikow->Add(ListaFTP->Strings[i]);
                  mamKropke = false;
                  break;
               }
               if ((j == ListaFTP->Strings[i].Length()) && (mamKropke == false))
               {
                  ListaKatalogow->Add(ListaFTP->Strings[i]);
               }
           }
        }

        katalogi->Text = ListaKatalogow->Text;
        pliki->Text = ListaPlikow->Text;

        ListaFTP->Free();
        ListaPlikow->Free();
        ListaKatalogow->Free();
}

Jest jeszcze coś. Po odinstalowaniu BCB gdy uruchamiałem plik EXE skompilowany w BCB, pokazuje mi się komunikat o tytule

"Project1.exe - Nie można znaleźć składnika"
i treści
"Uruchomienie tej aplikacji nie powiodło się, ponieważ nie znaleziono vcl.bpl. Ponowne zaistaowanie aplikacji może naprawić ten problem"
dlaczego tak się dzieje? Czy to znaczy, ze jak napisze w BCB program to na innym komputerze bez BCB go nie uruchomie? Mozna jakos to wylaczyc?

Pozdrawiam!

0
  1. Poczytaj jak działa pętla w C++ (jakoś słabo widzę warunek jej zakończenia) a w ogóle po co w ogóle tyle kodu jak FTP->List(); wystarczy (bez parametrów wiec tamte StringListy niepotrzebne) załadowanie Memo (domyślam się że to Memo) z listą plików i listą katalogów to sprowadza się do (i to pewna metoda odróżnienia plików od katalogów a nie bzdurna "na kropkę"):
		for (int i = 0; i < FTP->DirectoryListing->Count; i++) {
			 if (FTP->DirectoryListing->Items[i]->ItemType == ditDirectory) {
				katalogi->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
			 }
			 else if (FTP->DirectoryListing->Items[i]->ItemType == ditFile) {
				pliki->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
			 }
		}
  1. Zależy od wersji BCB musisz szukać czegoś w stylu "Link with runtime packages" w nowszych wersjach jest to w Project -> Options -> Packages -> Runtime packages jak to odznaczysz to tak zbudowane exeki możesz rozprowadzać bez dodatkowych bibliotek.
0

@kAzek dzięki za info, ale sama instrukcja

 FTP->List()

bez parametrów nie przejdzie ;/ Dostaje błąd o komunikacie

[C++ Error] Unit1.cpp(48): E2193 Too few parameters in call to '_fastcall TIdFTP::List(TStrings *,const AnsiString,const bool)'
.
Ten sam kod w Delphi działa, to mnie zastanawia.

0

To zaktualizuj Indy do najnowszej wersji kto teraz używa 9 to taki zabytek jak BCB 6. Poniżej instrukcja (moje wypociny, bo w necie nie można znaleźć nic mądrego do BCB) ;)

Usuń Indy 9
Component -> Install Packages... zaznacz Internet Direct (Indy) for... i Remove

Pobierz najnowsze Indy
http://indy.fulgan.com/ZIP/

i wypakuj do dowolnego folderu (muszm mieć prawa zapisu w tym folderze zresztą kto instaluje stare kompilatory do %Program Files%) np.:
$(BCB)\Source\Indy10_5189
uruchom
$(BCB)\Source\Indy10_5189\Lib\Fullc_6.bat
Po kompilacji utworzy się folder
$(BCB)\Source\Indy10_5189\C6
w nim powinny być głównie skompolowane pakiety *.bpl i pliki nagłówków *.hpp które będzie trzeba przekopiować:
Przekopiuj wszystkie pliki *.bpl i *.bpi z tego folderu do
$(BCB)\Bin
i w 32bit systemach
WINDOWS\System32
w 64 bit
WINDOWS\SysWOW64
a także (na wszelki wypadek) do
$(BCB)\Lib
Przekopiuj wszystkie (zastąp istniejące) pliki z wyjątkiem *.bpl i *.bpi do folderu $(BCB)\Include\Vcl
W Tools > Environment options > zakładka Library dodaj do Library path ścieżkę do folderu $(BCB)\Source\Indy10_5189\C6
Teraz Component -> Instal Packages i dodaj po kolei
$(BCB)\Bin\dclIndyCore60.bpl
$(BCB)\Bin\dclIndyProtocols60.bpl

Gratulacje właśnie zaktualizowałeś Indy ;)

0

Dzięki, Kazuś :) Ale nawet jak już mam indy10 to kod FTP->List(); nie idzie. Ten sam komunikat ;/

0

Dodaje jako zalacznik moj projekt. Jesli mozesz to sprawdz go u siebie bo moze w nim cos jest nie tak.

0

Nie pomyślałem że przy instalacji nowego Indy trzeba skopiować nadpisać wszystkie pliki z wyjątkiem *.bpl i *.bpi z $(BCB)\Source\Indy10_5189\C6 do $(BCB)\Include\Vcl\ (nadpisać istniejące) i na wszelki wypadek *.bpl i *.bpi z $(BCB)\Source\Indy10_5189\C6 do $(BCB)\Lib bo inaczej są problemy przy dynamicznym tworzeniu komponentów (już zaktualizowałem instrukcję powyżej)
W tym projekcie i tak nie zadziała bo jest skopany jakimś pozostałościami (pewnie gdzieś są odniesienia a nie chce mi się szukać gdzie) ze starszej wersji Indy (nie mogę dojść o co mu biega bo dziwne błędy których nie mogę zlokalizować) build nic nie daje... szkoda czasu na zabawę bo w tym czasie można utworzyć 1000 takich mini projektów w każdym razie jak zrobisz od nowa projekt to teraz musi już działać (sprawdziłem na dynamicznym IdFTP tak jak masz wcześniej nie pomyślałem że może to być różnica).

Poza tym masz kilka błędów kodzie poprawiłem:

        TIdFTP *FTP = new TIdFTP (this);

        FTP->Host = "host";
        FTP->Username = "name";
        FTP->Password = "password";
        FTP->Passive = true;

        try
        {
            FTP->Connect();
            if (FTP->Connected())
            {
               ShowMessage("Połączono!");
               FTP->List();
            }
            else
            {
               ShowMessage("Nie udało mi się połączyc!");
            }
        }
        catch (Exception &VCLException)
        {
           throw new Exception("Błąd o kodzie: " + VCLException.Message);
        };

        for (int i = 0; i < FTP->DirectoryListing->Count; i++)
        {
             if (FTP->DirectoryListing->Items[i]->ItemType == ditDirectory)
             {
                  katalogi->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
             }
             else if (FTP->DirectoryListing->Items[i]->ItemType == ditFile)
             {
                pliki->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
             }
        }

        FTP->Free();//juz nie bedziesz potrzebny :)

Gdybyś miał błąd connection closed gracefully nic się nie przejmuj to zwykły cichy wyjątek i występuje tylko podczas uruchamiania w środowisku BCB ale można się go "całkiem pozbyć" (tzn nie będzie się pojawiał nawet w środowisku BCB) dodając EIdConnClosedGracefully a nawet od razu EIdSilentException do ignorowanych Tools -> Debugger Options na zakładce Language Exceptions.

0

Kazuś, ten sam problem przy FTP->List(); ;/ A czy deklaracja tej funkcji ma podane WSZYSTKIE parametry domyślne że nie potrzebuje parametrów? Pytam bo przykładowe kody na googlach zawsze mają jakieś parametry.

0

@kAzek coś z INDYkami musi być powalone bo na Twoim screenie masz faktycznie trzy metody List() a popatrz na mój (jest w załączniku)...

0

Już udało mi się załatwić sprawę z Indy i mam trzy metody FTP->List(). Tylko teraz dostaję błąd linkera o treści:

[Linker Error] Unresolved external 'Idftp::' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idftp::~TIdFTP()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idexplicittlsclientserverbase::~TIdExplicitTLSClient()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idtcpconnection::~TIdTCPConnection()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idcomponent::~TIdComponent()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idbasecomponent::TIdBaseComponent(Classes::TComponent *)' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idftp::SetPassive(const bool)' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idftp::List()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idftplist::GetItems(int)' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ
[Linker Error] Unresolved external '__fastcall Idftp::GetDirectoryListing()' referenced from C:\DOCUMENTS AND SETTINGS(...)\PULPIT\BCB_KATALOGI\UNIT1.OBJ

0

Wywal wszystkie *.obj z projektu, do Unit1.cpp dodaj #include <IdFTP.hpp> i powinien się skompilować. A jak coś to edytuj (przy zamkniętym projekcie) plik projektu *.bpr zwróc uwagę na te linie w PACKAGES nie musi być tyle tego dziadostwa ale tak jest domyslnie (można usunąć niepotrzebne już normalnie w opcjach projektu).

    <LIBRARIES value="IndyProtocols60.lib IndySystem60.lib IndyCore60.lib rtl.lib vcl.lib"/>
    <SPARELIBS value="vcl.lib rtl.lib IndyCore60.lib IndySystem60.lib IndyProtocols60.lib"/>
    <PACKAGES value="vcl.bpi rtl.bpi dbrtl.bpi adortl.bpi vcldb.bpi vclx.bpi bdertl.bpi 
      vcldbx.bpi ibxpress.bpi dsnap.bpi cds.bpi bdecds.bpi qrpt.bpi teeui.bpi 
      teedb.bpi tee.bpi dss.bpi teeqr.bpi visualclx.bpi visualdbclx.bpi 
      dsnapcrba.bpi dsnapcon.bpi bcbsmp.bpi vclie.bpi xmlrtl.bpi inet.bpi 
      inetdbbde.bpi inetdbxpress.bpi inetdb.bpi nmfast.bpi webdsnap.bpi 
      bcbie.bpi websnap.bpi soaprtl.bpi dclocx.bpi dbexpress.bpi dbxcds.bpi 
      bcb2kaxserver.bpi IndyCore60.bpi IndySystem60.bpi IndyProtocols60.bpi"/> 

Aby ręcznie się nie bawić w dodawanie tego to powinno wystarczyć że dodasz komponent IdFTP choć na chwilę możesz go potem usunąć a środowisko powinno dodać to co potrzebne.

0

Jak wywalić pliki *.obj z projektu? Jeśli mówisz o katalogu to gdy je usunę to przy kompilacji znowu się pojawiają. Linijkę

#include <IdFTP.hpp>

już miałem wcześniej. Zrobiłem ten manewr z dodaniem komponentu IdFTP na formę ale wciąż mam to samo ;/

0

Sprawdź czy ten projekt sie skompiluje (to ten Twój tylko z kodu zmieniony)

0

Mam taki oto komunikat:

Build
[Linker Fatal Error] Fatal: Unable to open file 'INDYPROTOCOLS60.LIB'

1

No wreszcie to luzik z ZRODLO_INDY\C6 wrzuć wszystkie pliki *.bpi i *.lib do $(BCB)\Lib\Release\ i $(BCB)\Lib\Debug\ musi śmigać.

0

No fakt, smiga :) A co zmieniłeś w tym projekcie? Bo tamten wczesniejszy wciąż ma ten sam komunikat...? Tylko coś nie pobiera mi listy plikow i katalogow (zawiesza się po komunikacie Polaczono!) ale moze to z winy serwera albo mojego lacza.

0

Działa ale po komunikacie połączenia dostaję taki komunikat:

No FTP list parsers have been registered.

O co chodzi?

0
void __fastcall TForm1::Button1Click(TObject *Sender)
{

        TIdFTP *FTP = new TIdFTP (this);

        FTP->Host = host->Text;
        FTP->Username = user->Text;
        FTP->Password = pass->Text;
        FTP->Passive = true;

        try
        {
            FTP->Connect();
            if (FTP->Connected())
            {
               ShowMessage("Połączono!");
               FTP->List();
            }
            else
            {
               ShowMessage("Nie udało mi się połączyc!");
            }
        }
        catch (Exception &VCLException)
        {
            throw new Exception("Błąd o kodzie: " + VCLException.Message);
        };


        for (int i = 0; i < FTP->DirectoryListing->Count; i++)
        {
             if (FTP->DirectoryListing->Items[i]->ItemType == ditDirectory)
             {
                katalogi->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
             }
             else if (FTP->DirectoryListing->Items[i]->ItemType == ditFile)
             {
                pliki->Lines->Add(FTP->DirectoryListing->Items[i]->FileName);
             }
        }
        FTP->Free();//juz nie bedziesz potrzebny :)
        
}
//---------------------------------------------------------------------------
 
1

Chyba nadal masz gdzieś jeszcze odniesienia do indy 9. Przeszukaj cały folder Lib (z pod folderami) w poszukiwaniu plików indy.* wszystko co znajdzie usuń bo to z 9 (zresztą będziesz widział po dacie pliku że stary) i przebuduj projekt a jak się zacznie o coś pluć to znaczy że jeszcze gdzieś w ustawieniach zachowały się odniesienia do 9 i trzeba tego poszukać i usunąć.

EDIT: Googlałem trochę bo zaciekawił mnie problem (nigdy wcześniej z takim czymś się nie spotkałem) i okazało się, że niektóre serwery mogą nie obsługiwać MLS
Dodaj:

#include <IdAllFTPListParsers.hpp>

a przed List wstaw:

FTP->UseMLIS = FTP->CanUseMLS; //ewentualnie na sztywno FTP->UseMLIS = Fale;
0

Kazuś, jesteś wielki! Dzięki Ci, Kolego!:)

Jeszcze tylko jeden, maleńki problem. Pole Edit1 które mam na hasło, ma ustawione PasswordChar na '*'. Jak przywrócić, po kliknięciu na CheckBox pokazywało hasło normalnie? W zdarzeniu OnClick CheckBoxa dałem kod:

void __fastcall TForm1::pokazClick(TObject *Sender)
{
        if (pokaz->Checked == true)
        {
           pass->PasswordChar = '#0';
        }
        else
        {
           pass->PasswordChar = '*';
        }
} 

ale gdy klikam to raz pokazuje w gwiazdkach a raz w zerach. Jak zrobić aby raz było w gwiazdkach a raz normalnie?

0
  char passchars[] = {'*', '\0'};
  pass->PasswordChar = passchars[pokaz->Checked];
0

Dziękować :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1