[Delphi]Zmiana TResourceStream na String

0

Witam.
Szukam cały dzień jak zamienić TResourceStream (strumień danych) na String ew. jeżeli jest taka możliwość to zamiany danych (na "PAUSE" na "EXIT") w strumieniu bezpośrednio, jednak wolałbym zamiane na string gdyż mam większe możliwościi znalazłem taki kod do zmiany

var
  ResChalange:String;
  Res : TResourceStream;
begin
   Res:=TResourceStream.Create(hInstance, 'source', RT_RCDATA); //Odczyt danych z zasobu res
   ResChalange:=Res; //Konwert z strumienia na zmienną
   ResChalange:=StringReplace(ResChalange,'PAUSE','EXIT',[rfReplaceAll]); //Zmiana PAUSE na EXIT w strumieniu
   ResChalange.SaveToFile('C:\plik.exe'); //Zapisz wykonanie
   Res.Free;

Może się to wydać wam banalne bo może gdzieś w google jest ale ja mam problem z tym (włączeFirefoxa i mi się kompmuli a neta mam to max 15 KB/s).

Proszę o wsparcie

0

Przecież raz ten kod nie zadziała. Dwa powinieneś to zrobić tak jak poniżej, jeżeli plik jest tekstowy to zadziała.
Po trzecie wnoskując z rozszerzenia pliku, do ktorego zapisujesz strumień to raczej Ci się nie uda, bo pliki exe,
na ogół w swojej zawartości zawierając bajt o kodzie $0, a jak wiadomo string to typ zwany też null terminated
string, a więc taki bajt przerwie łańcuch tekstowy i z prawidłowej zamiany nic nie wyjdzie. Po czwarte to mi się
wydaje, że zmnieniając w execu dane słowo na inne, o innej długości niż te oryginalne, można uszkodzić exek.
Po piąte to raczej musiałbyś sobie wykombinować funkcję która zamieniała by dane na inne, w streamie. A po
szóste to taki kod jak poniżej przy nawet sporym pliku tekstowym i nie tylko, nie powinien obciązac procesora.

{$R zasoby.res}
var
  S : string;
  RS : TResourceStream;
begin
  RS := TResourceStream.Create(HInstance, 'nazwa_zasobu', RT_RCDATA);
  SetLength(S, RS.Size);
  RS.Read(PChar(S)^, RS.Size);
  RS.Free;
  ShowMessage(S);
end;
0

Na pewno w string'ach nie może być #0 ? Coś mi się zdaje że to dotyczy PChar'ów.

b

0

Oczywiście, że nie może string zostanie "ucięty" na pierwszym napotkanym znaku #$00 .

0

dobra to tuż wiem ze będę musiał zmienic bajty pliku, mam a to kod, ale dalej nie wiem jak znależąźć wyraz PAUSE izamienić na inny tekst. Co do zasobu too ma jakieś 300kb a teks kury zostanie dodany zaPAUSE nie będzie mial wiexej niż 1mb

0

Spróbuj tym kodem. Ślęczałem nad nim i wykombinowałem coś takiego: Wiem, że czytanie po jednym bajcie jest mało
optymalne, ale dla wsadzonego exeka w bajtach 1 277 952 funkcja wykonuje się 576 milisekund, także do przyjęcia, a
jak jesteś ambitny to na podstawie tej mojej funkcji spróbuj napisać taką aby sprawdzała większy bufor, ja próbowalem
jednak nie za bardzo to mi wyszło. Wyszukiwanie zmienionego miejsca potrafię zrobić, lecz elegancka podmiena tekstu
w wybranym buforze, a później zapis do streamie albo zapis oryginalnego bajtu do streama, jeżeli ten nie jest znakiem
szukanego słowa - mi nie wyszło. Jak potrzebujesz CaseSensitive i tym podobne - to już kombinuj coś sam. Chyba, że
ktoś Ciebie tutaj wyręczy. Może i są jakieś gotowe kody na googlach, lecz nie udało mi się znaleźć coś odpowiedniego.

function ReplaceTextInStream(SourceStream : TStream; TextToFind, NewText : string) : TMemoryStream;
var
  B : Byte;
  I : int64;
  X : integer;
  S, TmpS : string;
  MS : TMemoryStream;
begin
  MS := TMemoryStream.Create;
  Result := TMemoryStream.Create;
  if (TextToFind = '') or (NewText = '') then
  begin
    Exit;
  end;
  TmpS := Copy(TextToFind, 1, 1);
  MS.LoadFromStream(SourceStream);
  MS.Position := 0;
  I := 0;
  repeat
    S := TmpS;
    MS.Position := I;
    MS.Read(B, 1);
    Result.Write(B, 1);
    if Length(TextToFind) = 1 then
    begin
      TextToFind := Chr(Integer(B));
    end;
    if B = Byte(TextToFind[1]) then
    begin
      for X := 1 to Length(TextToFind) - 1 do
      begin
        MS.Read(B, 1);
        S := S + Chr(Integer(B));
      end;
    end;
    if (S = TextToFind) then
    begin
      Result.Position := Result.Position - 1;
      Result.Write(PChar(NewText)^, Length(NewText));
      I := I + Length(TextToFind);
    end
    else
    begin
      I := I + 1;
    end;
  until I = MS.Size;
  MS.Free;
end;

procedure TForm1.Button1Click(Sender : TObject);
{$R zasoby.res}
var
  MS : TMemoryStream;
  RS : TResourceStream;
  Start, Stop : Cardinal;
begin
  RS := TResourceStream.Create(HInstance, 'nazwa_zasobu', RT_RCDATA);
  Start := GetTickCount;
  MS := ReplaceTextInStream(RS, 'dos', 'inny_wyraz');
  Stop := GetTickCount;
  ShowMessage('Czas wykonania funkcji: ' + IntToStr(Stop - Start));
  MS.SaveToFile('test.bin');
end;
0
kAzek napisał(a)

Oczywiście, że nie może string zostanie "ucięty" na pierwszym napotkanym znaku #$00 .

Sranie w banie. Sprawdź zanim coś palniesz. To że większość funkcji tak się zachowa, że obetnie stringa przy pierwszym napotkanym zerze nie oznacza że string nie może zawierać znaków #0, może ich mieć dowolną ilosć:

var t : textfile;
s : string;
begin
s := #65#0#65;
assignfile(t,'c:\test.txt');
rewrite(t);
writeln(t,s);
closefile(t);
end;

Między String na null terminated string jest duża różnica. Przykładem NTS jest PChar.

b

0

Przy użyciu Write lub Writeln zgadzam się - tekst nie będzie ucięty, ale już taki kod jak poniżej zachowa się inaczej.

var
  S : String;
begin
  S := #65#0#65;
  ShowMessage(S);
end;
0

wszystko pięknie tylko nie zapisuje nowej wartości byte tylko używa starej przez co jeżeli zamieniona składnia (ze słowa PAUSE np: cmd.exe) nie ma 5 znaków to nie może odczytać poprawnie aplikacji, co do samego "skryptu" to jest świetny! Jak byś mógł poprawić bo ja nie za bardzo łapie gdzie jest błąd.

Ale i tak dzięki za pomoc!

0

Następny ku... z tym skryptem. To jest kod nie skrypt [!!!] I ogarnij się. Moja funkcja działa dobrze,
bo zrobiłem sobie na próbę plik tekstowy o zawartości jak poniżej i wkompilowałem go do zasobów:
3 aaa pause Test Cosik pause Ble
I po zmianie w pliku wynikowym test.bin mam:
3 aaa cmd.exe Test Cosik cmd.exe Ble
Także działa, tylko Tobie można pisać, a Ty dalej swoje. Taka zmiana w exe dosowym czy nawet w
Windowsowym jeżeli nie robi się tego edytorem zasobów i edytuje się inne treści niż zasoby to jak
po zmianie tekst ma inną ilośc znaków niż oryginalny to exe się uszkodzi - to normalne. Nie jestem
w temacie formatu PE eksperem, ale myślisz, że po co takie dane jak nagłowki czy sekcje i długości
takowych. Myślisz, że sobie otworzysz exe edytorem tekstowym i pozmieniasz jak się Tobie chce, a
po zmianie będzie wszystko działać? To się mylisz. A kod mój dostałeś, chcesz to go zmieniaj sam.

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