CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Zapis w pliku exe

Zapis w pliku exe

dział ogólny

Zapis w pliku exe

Nowy postprzez Bishamoth » czwartek, 10 września 2009, 21:19

Witam
Czy jest mozliwosc zapisania informacji tekstowych w pliku exe? Dajmy na to, ze mam komponeny TEdit1 oraz TButton1, wpisuje cos do TEdit1, klikam na TButton1 (zapisuje zawartosc TEdit1), wylaczam program, wlaczam go z powrotem i w TEdit1 znajduje sie to co napisalem wczesniej. Nie chce zadnego zapisywania do pliku tekstowego, czy jakiego kolwiek innego.

Pozdrawiam Bish
Avatar użytkownika
Bishamoth
Bladawiec
Bladawiec
 
Posty: 40
Dołączył(a): niedziela, 1 marca 2009, 22:51
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP3
Kompilator: C++ Builder 6
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez banita » czwartek, 10 września 2009, 21:33

poczytaj o zasobach programu, chocby w portalu CB
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
Podziękował : 1
Otrzymał podziękowań: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Bishamoth » czwartek, 10 września 2009, 23:47

Tworzenie tablicy łańcuchów znaków i umieszczenie jej w zasobach programu.

Jezeli chodzilo Ci o ta porade, to wychodzi na to, ze nie ma mozliwosci zapisania czegokolwiek w binarce podczas dzialania programu... Te pliki *.rh *.rc -sa tworzone przed kompilacja i sa pozniej "wbudowane" w program, wiec nie ma jak ich edytowac :roll: Przynajmniej tak to wyglada po przeczytaniu/
Jest inny sposob na zapisanie tekstu?
Avatar użytkownika
Bishamoth
Bladawiec
Bladawiec
 
Posty: 40
Dołączył(a): niedziela, 1 marca 2009, 22:51
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP3
Kompilator: C++ Builder 6
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez banita » piątek, 11 września 2009, 00:03

http://cyfbar.republika.pl/api5.html#api2

niestety uruchomiony proces nie moze zmieniac swoich zasobow.
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
Podziękował : 1
Otrzymał podziękowań: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez izdrink » piątek, 11 września 2009, 08:35

Witam!
dobrym sposobem na to co chcesz zrobić-jest obsługa plików ini :)
super opisana na cyfbar!!!
zapamietuje to co wpiszesz do edita i przy kolejnym uruchomieniu programu tez tam sie bedzie znajdowac!
i wcale nie musisz uzywac buttona!
wystarcza dwie funkcej(np read i write-read odzczytuje przy tworzeniu form,write zapisuje przy zamykaniu).
a plik ini stworz najlepiej
Kod: Zaznacz cały
void TForm1::Read()
{
   TIniFile *ini = new TIniFile(ChangeFileExt(Application->ExeName,".ini"));
   
   Edit1->Text = ini->ReadString("Sekcja","Wartosc","");

   delete ini;
}


Kod: Zaznacz cały
TIniFile *ini = new TIniFile(ChangeFileExt(Application->ExeName,".ini"));

   ini->WriteString("Sekcja","Wartosc",Edit1->Text);

   delete ini;
Avatar użytkownika
izdrink
Bladawiec
Bladawiec
 
Posty: 10
Dołączył(a): czwartek, 10 września 2009, 09:39
Podziękował : 2
Otrzymał podziękowań: 1
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Bishamoth » piątek, 11 września 2009, 14:40

banita napisał(a):niestety uruchomiony proces nie moze zmieniac swoich zasobow.

O tym juz sie przekonalem ;) A mozliwym by bylo stworzenie dwoch programow. Jeden glowny i drugi poboczny. Glowny program odpala poboczny, a ten czeka az glowny program zakonczy swoje dzialanie, gdy juz sie tak stanie, to poboczny zmieni zasoby glownego, tak by bylo to co sie wpisalo w komponencie TEdit1. Po tym program poboczny konczy swoja prace... Coz, troche na okolo, jednak moze zadzialac. Teraz tylko musze sie dowiedziec, jak dokonac takiego czynu ;P

izdrink napisał(a):Witam!
dobrym sposobem na to co chcesz zrobić-jest obsługa plików ini :)

Bishamoth napisał(a):Nie chce zadnego zapisywania do pliku tekstowego, czy jakiego kolwiek innego.

Przeciez pisalem, ze nie chce zadnej obslugi plikow tekstowych ani tym podobnych. Chce to zrobic w binarce.
Avatar użytkownika
Bishamoth
Bladawiec
Bladawiec
 
Posty: 40
Dołączył(a): niedziela, 1 marca 2009, 22:51
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP3
Kompilator: C++ Builder 6
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Cyfrowy Baron » piątek, 11 września 2009, 16:25

Potrzebujesz chyba porady: ► patrz serwis: Cyfrowy Baron dział porady -> API -> Uruchomienie aplikacji i oczekiwanie na jej zamknięcie.

Co do zapisywanie ustawień w pliku aplikacji to takiej metody chyba nikt nie stosuje. Jest to niebezpieczne, gdyż edycja takich zasobów może uszkodzić plik aplikacji.
Lepszym rozwiązaniem byłoby już stworzenie pliku rozszerzenia aplikacji (*.DLL). Program nie musiałby wcale korzystać z tego pliku, mógłby jednak bez problemu modyfikować zasoby tegoż programu.

Jeżeli sądzisz, że zapisując jakieś dane w pliku *.EXE lub *.DLL chronisz je przed użytkownikiem, to jesteś w błędzie. Takie zasoby można bez problemu podejrzeć pisząc program do edycji zasobów aplikacji, korzystajać chociażby z porady w serwisie Cyfrowy Baron, lub prościej - wykorzystując np. program Resource Hacker.

Jest ogólnie przyjęte, że dane konfiguracyjne aplikacji zapisuje się w rejestrze a opcje programu (opcje użytkownika) w plikach *.INI.

W celu zablokowania modyfikacji danych przez użytkownika należy je zapisywać w postaci binarnej. Można do tego celu wykorzystać struktury.
Innym sposobem jest zapisywanie i odczytywanie danych z/do pliku będącego chronionym hasłem archiwum ZIP (polecam komponent ZIPForge). Takie archiwa można obsługiwać bez wypakowywania plików, zapisując i odczytując dane strumieniowo bezpośrednio z/do pamięci.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Bishamoth » środa, 16 września 2009, 22:46

Witam ponownie ;)
Cyfrowy Baron napisał(a):Innym sposobem jest zapisywanie i odczytywanie danych z/do pliku będącego chronionym hasłem archiwum ZIP (polecam komponent ZIPForge). Takie archiwa można obsługiwać bez wypakowywania plików, zapisując i odczytując dane strumieniowo bezpośrednio z/do pamięci.

To mnie bardzo zaciekawilo. Czy mozna sie czegos wiecej dowiedziec o tym komponencie? Mam go juz zainstalowanego, lecz help do niego, jak dla mnie jest troche... za malo. W szczegolnosci interesuja mnie strumienie :)
Avatar użytkownika
Bishamoth
Bladawiec
Bladawiec
 
Posty: 40
Dołączył(a): niedziela, 1 marca 2009, 22:51
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP3
Kompilator: C++ Builder 6
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Cyfrowy Baron » czwartek, 17 września 2009, 20:09

Plik pomocy jest bardzo dobrze opracowany, ale podam gotowe rozwiązania strumieniowego zapisu i odczytu danych za pomocą ZIPForge. Komponent będzie tworzony dynamicznie, a to oznacza, ze nie trzeba go umieszczać na formularzu.

w pliku nagłówkowym w sekcji Include dodajemy wpis: #include "ZipForge.hpp"

KOD cpp:     UKRYJ  
#include <Classes.hpp>
#include <StdCtrls.hpp>
// [...]
#include "<span class="posthilit">ZipForge</span>.hpp"

private:
          void SaveOptions(void);
          void LoadOptions(void);
 
Zapis do pliku:

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <memory>
//---------------------------------------------------------------------------

#pragma package(smart_init)
#pragma link "<span class="posthilit">ZipForge</span>"

//---------------------------------------------------------------------------
void TForm1::SaveOptions(void)
{
 TZipForge *SaveArchiver = new TZipForge(NULL);

 TMemoryStream *mStream = new TMemoryStream();
 mStream->Position = 0;

 /* tutaj tworzona jest lista typu TStringList i w niej zapisywane są opcje */
 std::auto_ptr<TStrings> optionList(new TStringList());
 optionList->Add("coś tam sobie zapisujesz");

 optionList->SaveToStream(mStream); // przepisanie listy do strumienia pamięci

 String optionFile = "nazwa pliku.zip"; /* nazwa pliku archiwum rozszerzenie może być dowolne, niekoniecznie ZIP */
 SaveArchiver->FileName  = optionFile;

 if(FileExists(optionFile))
 {
  /* jeżeli plik istnieje nastęuje otwarcie archiwum do odczytu i zapisu */
  SaveArchiver->OpenArchive(fmOpenReadWrite);
  SaveArchiver->Active = true;
 }
 else
 {
  /* jeżeli plik nie istnieje archiwum jest otwierane tylko do zapisu */
  SaveArchiver->OpenArchive(fmCreate);
 }

 SaveArchiver->Password = "hasło"; // podaj hasło - rozróżnia wielkość liter
 SaveArchiver->CompressionMode = 9; // stopień kompresji 0-9
 SaveArchiver->CompressionLevel = <span class="posthilit">Zipforge</span>::clMax; // poziom kompresji
 SaveArchiver->EncryptionMethod = caAES_256; /* metoda szyfrowania podawana tylko przy zapisie do archiwum */

 String optionTxt = "option.txt"; // nazwa pliku w archiwum, nazwa dowolna

 SaveArchiver->AddFromStream(optionTxt, mStream, true, 0, 0, 0, Now()); /* przepisanie zawartości strumienia pamięci do pliku w archiwum */
 SaveArchiver->CloseArchive(); /* zamknięcie archiwum, WAŻNE! trzeba zamknać w przeciwnym razie plik będzie niedostępny do dalszych operacji */

 mStream->Position = 0;

 delete mStream;
 delete SaveArchiver;
}


czytaj więcej o metodzie szyfrowania

Odczyt z pliku:
KOD cpp:     UKRYJ  
 /* tutaj tworzona jest lista typu TStringList i w niej umieszczone zostaną pobrane opcje, do przechowywania opcji programu powinna to być lista globalna, czyli należy ja zadeklarować w pliku nagłówkowym w sekcji private lub public i zdefiniować najlepiej w konstruktorze klasy formularza */

TStrings *optionList;
optionList = new TStringList();

//---------------------------------------------------------------------------
void TForm1::LoadOptions(void)
{
 if(!FileExists(optionFile)) return; /* jeżeli plik nie istnieje funkcja przerywa działanie */

 TZipForge *LoadArchiver = new TZipForge(NULL);
 TMemoryStream *mStream = new TMemoryStream();

 String optionFile = "nazwa pliku.zip"; /* nazwa pliku archiwum w którym zapisano opcje */

 LoadArchiver->FileName  = optionFile;
 LoadArchiver->OpenArchive(fmOpenRead); // otwarcie w trybie do odczytu
 LoadArchiver->Password = "hasło"; // podaj hasło archiwum


 String optionTxt = "option.txt"; /* nazwa pliku w archiwum, ten sam plik, który był wykorzystany do zapisu */

 TZFArchiveItem ArchiveItem;
 std::auto_ptr<TStrings> findList(new TStringList());

/* wyliczanie plików w archiwum, celem sprawdzenia, czy archiwum zawiera potrzebny plik tutaj option.txt reprezentowany przez zmienną optionTxt, mozna wyszukiwać grupy plików z rozszerzeniem podając jako argument zamiast pełnej nazwy pliku tylko rozszerzenie np. "*.txt", można też wyszukiwać wszystkie pliki w archiwum "*.*" */

 if(LoadArchiver->FindFirst("*.txt", ArchiveItem, faAnyFile - faDirectory))
  do
  {
    findList->Add(ArchiveItem.FileName);
  }
  while (LoadArchiver->FindNext(ArchiveItem));

 if(findList->IndexOf(optionTxt) < 0)
 {
  /* jeżeli w archiwum nie znaleziono żadnego pliku, obiekt LoadArchiver kończy działanie i przerywa dalsze wykonywanie funkcji */
  LoadArchiver->CloseArchive();
  delete mStream;
  return;
 }

 LoadArchiver->ExtractToStream(optionTxt, mStream); /* wypakowanie zawartości pliku z archiwum do pamięci */
 mStream->Position = 0;

 optionList->LoadFromStream(mStream); /* przepisanie zawartośći strumienia pamięci do listy optionList */
 LoadArchiver->CloseArchive();  /* zamknięcie archiwum, WAŻNE! trzeba zamknać w przeciwnym razie plik będzie niedostępny do dalszych operacji */

 delete mStream;
delete LoadArchiver;
}
Ostatnio edytowano wtorek, 6 września 2011, 10:47 przez Cyfrowy Baron, łącznie edytowano 3 razy
Powód: Poprawiłem błędy w kodzie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Bishamoth » czwartek, 17 września 2009, 21:52

Oki, nie wiem czy to bylo pisane z glowy i nie sprawdzone, czy tez nie, ale:
Kod: Zaznacz cały
[C++ Error] Unit1.cpp(34): E2316 'Items' is not a member of 'TStrings'
[C++ Error] Unit1.cpp(57): E2451 Undefined symbol 'Strings'
[C++ Error] Unit1.cpp(57): E2379 Statement missing ;
[C++ Error] Unit1.cpp(59): E2451 Undefined symbol 'optionTxt'
[C++ Error] Unit1.cpp(71): E2451 Undefined symbol 'optionFile'
[C++ Error] Unit1.cpp(76): E2238 Multiple declaration for 'optionFile'
[C++ Error] Unit1.cpp(83): E2451 Undefined symbol 'Strings'
[C++ Error] Unit1.cpp(83): E2379 Statement missing ;
[C++ Error] Unit1.cpp(90): E2451 Undefined symbol 'optionTxt'
[C++ Error] Unit1.cpp(90): E2285 Could not find a match for 'TZFBaseArchiver::FindFirst(undefined,TZFArchiveItem,int)'

:roll:
Avatar użytkownika
Bishamoth
Bladawiec
Bladawiec
 
Posty: 40
Dołączył(a): niedziela, 1 marca 2009, 22:51
Podziękował : 1
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP3
Kompilator: C++ Builder 6
Gadu Gadu: 0
    NieznanyNieznana

Re: Zapis w pliku exe

Nowy postprzez Cyfrowy Baron » piątek, 18 września 2009, 10:27

Kod jest sprawdzony pochodzi z jednego z moich programów.

Ten komunikat:


[C++ Error] Unit1.cpp(34): E2316 'Items' is not a member of 'TStrings'




dotyczy tego fragmentu kodu:

jest:
Kod: Zaznacz cały
optionList->Items->Add("coś tam sobie zapisujesz");

powinno być:
Kod: Zaznacz cały
optionList->Add("coś tam sobie zapisujesz");




Co do tych komunikatów:


[C++ Error] Unit1.cpp(57): E2451 Undefined symbol 'Strings'
[C++ Error] Unit1.cpp(57): E2379 Statement missing ;
[C++ Error] Unit1.cpp(59): E2451 Undefined symbol 'optionTxt'
[C++ Error] Unit1.cpp(71): E2451 Undefined symbol 'optionFile'
[C++ Error] Unit1.cpp(83): E2451 Undefined symbol 'Strings'
[C++ Error] Unit1.cpp(83): E2379 Statement missing ;
[C++ Error] Unit1.cpp(90): E2451 Undefined symbol 'optionTxt'




to błędy wynikające z błędnej deklaracji zmiennych, gdyż deklarując zmienne typu String pisałem Strings.

Pojawiają się tam drobne literówki, które nieopatrznie wprowadziłem podczas przepisywania kodu. Tam gdzie jest Strings powinno być oczywiście String, gdyż chodzi o zmienne String. Błąd pojawia się dwa razy:

w funkcji SaveOptions:

jest:
Kod: Zaznacz cały
Strings optionTxt = "option.txt"; // nazwa pliku w archiwum, nazwa dowolna

powinno być:
Kod: Zaznacz cały
String optionTxt = "option.txt"; // nazwa pliku w archiwum, nazwa dowolna


oraz w funkcji LoadOptions:

jest:
Kod: Zaznacz cały
  Strings optionTxt = "option.txt"; /* nazwa pliku w archiwum, ten sam plik, który był wykorzystany do zapisu */

powinno być:
Kod: Zaznacz cały
  Strings optionTxt = "option.txt"; /* nazwa pliku w archiwum, ten sam plik, który był wykorzystany do zapisu */




Co do tego komunikatu:

[C++ Error] Unit1.cpp(76): E2238 Multiple declaration for 'optionFile'




Oznacza, on że zmienna o nazwie optionFile została dwukrotnie zadeklarowana, ale ten błąd nie występuje w moim kodzie, wiec to pewnie efekt twoich modyfikacji.



Funkcje zdefiniowane w pliku źródłowym wymagają deklaracji w pliku nagłówkowy, o czym nie pisałem, gdyż sądziłęm, że to oczywiste.

plik nagłówkowy np. Unit1.h:
Kod: Zaznacz cały
private:
          void LoadOptions(void);
          void SaveOptions(void);




Kolejny błąd jaki popełniłem modyfikując funkcję do Twoich potrzeb występuje w funkcji SaveOptions:

jest:
Kod: Zaznacz cały
/* tutaj tworzona jest lista typu TStringList i w niej zapisywane są opcje */
std::auto_ptr<TStrings> optionListt(new TStringList());
optionLista->Items->Add("coś tam sobie zapisujesz");


powinno być:
Kod: Zaznacz cały
/* tutaj tworzona jest lista typu TStringList i w niej zapisywane są opcje */
std::auto_ptr<TStrings> optionList(new TStringList());
optionList->Add("coś tam sobie zapisujesz");




Co do tego komunikatu:


[C++ Error] Unit1.cpp(90): E2285 Could not find a match for 'TZFBaseArchiver::FindFirst(undefined,TZFArchiveItem,int)'




to błąd wywołuje ten fragment kodu:

Kod: Zaznacz cały
if(LoadArchiver->FindFirst(optionTxt, ArchiveItem, faAnyFile - faDirectory))


bierze się stąd, że zmodyfikowałem go do Twoich potrzeb, ale w pomocy jest napisane, że pierwszy argument to wartość typu WideString (mój błąd po podałem wartość typu String). Nie mam też pewności, czy można tutaj podać pełną nazwę pliku, więc możesz to zrobić na dwa sposoby:

pierwszy (niepewny)
Kod: Zaznacz cały
if(LoadArchiver->FindFirst(optionTxt.c_bstr(), ArchiveItem, faAnyFile - faDirectory))

.c_bstr() - konwersja zmiennej typy String do WideString

drugi (musi zadziałać:
Kod: Zaznacz cały
if(LoadArchiver->FindFirst("*.txt", ArchiveItem, faAnyFile - faDirectory))





Poprawiłem kod w moim poprzednim poście, ale kopiując go musisz dostosować go do swojego programu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 2 gości

cron