i am developing an App for windows that will start some third party executable files such as cmd, paint, notepad etc using CreateProcess function. I want the functionality to hide and show the window of these EXE programs using HWND or suggest any other solution...
CreateProcess() does not return the HWND of the new process so you will have to find it manually. Use EnumWindows() and GetWindowThreadProcessId() to find HWNDs whose process/thread IDs match the same IDs that CreateProcess() returns in the PROCESS_INFORMATION struct. Once you have the HWNDs, you can use ShowWindow() to show/hide them as needed.
Related
I have a dll that is injected in a process and this dll contains a Form where i want use MessageBox() (or some other type of dialog) to alert the user about some operations.
Eg:
Application.MessageBox('successful operation!','Information',mb_Ok+mb_IconInformation);
Happens that everytime that this is showed, also is showed the icon of target application in Windows taskbar, and i not want this.
Then i want display these messages without show application icon in taskbar.
How make this?
In Delphi 7, Application.MessageBox() calls the Win32 API MessageBox() function specifying the Application.Handle as the owner window 1.
Inside a DLL, Application.Handle is 0 by default, so your MessageBox dialog is being displayed without an owner window assigned to it. That explains why it is able to appear on the Taskbar, as only a top-level unowned window (with the APP_EX_APPWINDOW extended style) can appear there.
So, the simplest solution is to call the Win32 API MessageBox() function yourself, specifying an owner HWND that belongs to the app you have injected your DLL into. Or, if you want to keep using Application.MessageBox(), assign such an HWND to the Application.Handle property after the DLL has been injected.
But either way, make sure the thread that is calling MessageBox() is attached to the message queue of the chosen owner HWND. If you are calling MessageBox() in a separate thread, use AttachThreadInput() to make that attachment before calling MessageBox(), and again to remove the attachment after MessageBox() exits.
1: In later Delphi versions, Application.MessageBox uses the Application.OnGetActiveFormHandle event, the Win32 GetActiveWindow() function, and the Win32 GetLastActivePopup() function (in that order) to find a suitable owner window before resorting to using the Application.Handle.
Pre-amble: I use Lazarus 1.2.6 and Freepascal 2.6.4 on Windows 7 and my solution must be based on that - not C or C++. I could use Delphi though, if something similar exists for that.
Problem: I wish to create a small program that is ideally launched from the command line, but then just runs in the background without the need for the console application to be open visibly.
I'm trying to work out how best to achieve it.
I read this link and this link and this C based example and this Linux example but as one user points out "if you don't want a console application, don't make one", which begs the question of what are the other ways? If you don't want a GUI, and you don't want a console, I assume there's another way to create a silent program, then launch it, and then just have it run in the background? Preseumbly as a service or some such?
Or, the other way that occured to me is to create a Library (which generates a DLL when compiled of course) that contains my programs functions, export those functions at the end of the DLL, then call them from a seperate terminal application which, I assume, I could then close but the functions that are called from the DLL might continue to run? In other words - two programs - one terminal program to launch the other non-visible program and then close the launching program? Is that possible or recommended?
I've written about this topic before, but not specifically with regard to Delphi or Free Pascal.
Use the {$APPTYPE GUI} directive to tell the compiler to generate a GUI application rather than a console application. You'd generally put it near the top of your main project file, where the program statement is. When you use that directive, the program will neither inherit the console of its parent nor create a new console. If you don't actually want a GUI, then don't display any windows; if you have a console application, the OS creates the console for you automatically because "consoleness" is a property of the EXE file.
Using a separate program and DLL won't have the effect you're looking for. As you already know, functions block the caller until they return. Therefore, when the host program calls your DLL function, it will wait until it returns before exiting. A DLL is not a separate program; it can't run without its host. (Using a separate thread won't work, either, because when the main thread terminates the program, it destroys all other threads whether they're finished or not.)
With Lazarus it is very simple. Just write small launcher program:
program project1;
uses
Process;
var
p: TProcess;
begin
p := TProcess.Create(nil);
try
p.ShowWindow := swoHIDE; // To hide your console app
//p.ShowWindow := swoShowNormal; // To show your console app
p.Options := [poNewConsole];
p.CommandLine := 'cmd'; // Change to your app name
p.Execute;
Writeln('Programm launched.');
finally
p.Free;
end;
end.
Actually, it is not Lazarus but pure FPC program.
If you don't want a console application, don't make one.
That sounds like something that I might have said!! And yes, that's the way to deal with this. When one console application starts another one, the parent process blocks until the child completes. You can arrange for the child process to break away from its parent's console, but then you'll just end up with two consoles.
What you really want to do is create a process that targets the GUI subsystem rather than the console subsystem. In other words, you don't want a console application, so don't make one. Make a GUI application instead.
Now, a GUI application doesn't mean that you have to show GUI. There's no compunction to do so. You have a process to break away, execute in the background, not attach to the parent console. That's an application that targets the GUI subsystem but does not show any GUI.
For example, this program targets the GUI subsystem, but shows no GUI. It's rather useless because it blocks indefinitely. However, you'd replace that with your background task.
program project1;
{$apptype gui}
uses
windows;
begin
Sleep(INFINITE);
end.
Assuming you're only using this program under Windows, you can simply call FreeConsole from the Windows API:
FreeConsole function
Detaches the calling process from its console.
For example this simple program:
program project1;
uses
sysutils, windows;
begin
FreeConsole;
while(true) do
sleep(50);
end.
Can be launched from the explorer or from cmd and runs infinitely without showing its own console. When launched from another console, it continues running even if the other cmd instance is closed.
To determine my exe path, I don't know which code I should use.
Please give me explanation when and why should we use:
1. ExtractFilePath(ParamStr(0))
2. ExtractFilePath(Application.ExeName)
Because both code are rendering the same output.
C:\Users\Bianca\Documents\RAD Studio\Projects\Exam1\Win32\Release\
C:\Users\Bianca\Documents\RAD Studio\Projects\Exam1\Win32\Release\
They both give you the same result, but there are subtle differences.
Application.ExeName references the VCL Application object. The use of this property requires you use the Vcl.Forms unit. Internally this does call the ParamStr(0) function.
Notice that the FireMonkey TApplication class does not have this property (as of XE5). So you cannot call Application.ExeName if you are using FireMonkey. And if you ever migrate a VCL project to FireMonkey you will have to rewrite this.
The ParamStr function OTOH is the System unit and is multiplatform (Win, Mac, iOS and Android, depending OC on the Delphi version you are using). On Windows ParamStr(0) calls the GetModuleFileName function, while on the other platforms it parses the command line returning the first token, which should be full path and name of running executable. (Thanks to Rob Kennedy for this correction)
So... I'd suggest you use ParamStr(0) directly.
They are functionally identical. You would use ParamStr(0) if you didn't want the overhead of the Forms unit and all it's baggage.
i am using Delphi XE4 to create a Voip program. i am using an outdated VOIP SDK From a company called BigSpeed which is no longer around the current code points to the following path 'C:\Program Files (x86)\BigSpeed Voice SDK\' where the active x controls are stored.
LIBID_bsVoiChatCln: TGUID = '{D2A88515-99E0-4EEE-A030-E5D2AB306A03}';
IID_IbsVoiChatClnX: TGUID = '{5055A626-56A1-4E58-A461-000A69CA3E03}';
DIID_IbsVoiChatClnXEvents: TGUID = '{665DB561-22D3-4624-B55B-4416309A2E03}';
CLASS_bsVoiChatClnX: TGUID = '{BE761C1E-1F6C-46F8-A99B-0AB29C9B2D03}';
How can i create a new GUID and have the program access the active x controls from a new directory.
You don't want to create new GUIDs. The GUIDs are the identifiers of that component. All you want to do, as far as I can tell from the question and your comments, is to register the DLL at a different location.
The ActiveX DLL almost certainly uses self-registration. This means that you can put the DLL somewhere else and register it there. For instance, suppose the DLL is located in:
C:\MyFolder\MyDll.dll
Then you could register it by executing this command:
regsvr32 C:\MyFolder\MyDll.dll
Looks like you do not understand (or do not explain) relations between your program, the library and the GUIDs.
How can i create a new GUID and
1) GUID is just a 128-bit random number. So you can "create new GUID" simply by editing its hexadecimal string. Or you can press Ctrl+Shift+G in Delphi source editor in designtime. In runtime you can use CreateGUID function of SysUtils unit.
http://docwiki.embarcadero.com/CodeExamples/XE5/en/UsingGUIDs_(Delphi)
http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.CreateGUID
http://en.wikipedia.org/wiki/GUID
But i don't think creating new GUID will do you any good. If anything, it should mean explicitly declared incompatibility with old GUIDs (hence incompatibility with VOIP library)
from a new directory.
2) Why do you think your VoIP library is arranged as a set of ActiveX control ? Just because there are GUIDs there? Not any text file with GUIDs inside would be ActiveX.
ActiveX are specifically arranged Windows servers, that are registered in the registry so that any program could call them. Sometimes you can register them after the fact, if the installer failed it.
http://en.wikipedia.org/wiki/Activex
http://en.wikipedia.org/wiki/Regsvr32
http://support.microsoft.com/?id=207132
So you should read manuals for your library whether they constitute ActiveX or not, and if they do, how to register them in Windows (should be done by the library installer)
If installer does not provide for it, then you can not be sure that the library can work from a different place. Not only your program needs a connection to it, but also the library itself may need connection to its other parts.
have the program access the active x controls
3) If your library really conforms to ActiveX specifications and if it was correctly installed (registered) then you can just import them into Delphi IDE and drop them onto the form like you drop tables and dialogs.
http://docwiki.embarcadero.com/RADStudio/XE3/en/Import_Component_Wizard
http://delphi.about.com/library/howto/htaddactivex.htm
http://www.delphisources.ru/pages/faq/master-delphi-7/content/LiB0125.html
4) if you do not want to drop your VoIP component onto the form, then you can try to create it in runtime with CoCreateInstance. But first you have to read some tutorial about Microsoft COM for beginners. You may miss some advanced concepts, but you should understand the most basic things like how interfaces are similar to and different from classes, how their lifetime is managed, how COM runtime is initialized and finalized for your program and so on.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686615.aspx
http://delphi.about.com/library/weekly/aa121404a.htm
http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1135
How to use CoCreateInstance() to get a com object?
https://stackoverflow.com/search?q=%5Bdelphi%5D+cocreateinstance
all the MS Office related examples in c:\RAD Studio\9.0\OCX\Servers\
5) you may also try to bypass the proper Windows ways of locating and loading the server and try to do it yourself, using DllGetClassObject routines in proper DLLs. If the library is permissive, it will work. But if it does rely on Windows-provided services that has a potential for all kinds of crashes and unmet expectations.
https://www.google.com/search?client=opera&q=CoCreateInstance+and+DllGetClassObject&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680760.aspx
How do I use a COM DLL with LoadLibrary in C++
DllGetClassObject return "No such interface supported" while CoCreateInstance can find it successful
If my memory serves me, You can find examples of that approach in early HTML Help units for delphi. Microsoft HTML Help provides for both late binding using CoCreateInstance and runtime ActiveX servers registry, or early binding towards htmlhlp.ocx treated as DLL. Early versions of HTML Help API for Delphi provided for both options. But i may be wrong here.
I'm trying to assign a ParentWindow, to a control created in a dll. The control is an editor, I need to process a text file, but this control requires a ParentWindow.
How can I solve this problem, if I create this control in a dll?
I'm using Delphi 5.
also create the TForm (maybe not Visible) inside the dll then the control and add it to the form
This is a common question, and the correct answer is "Don't do that".
The first question I have is "why do you feel the need to create a control in a DLL?" Why not just create it in code or include the control itself in your EXE?
Second, if you want to add a control to a separate binary, but it in a Package. Packages are designed specifically to make exporting controls simple and easy.
You need to get the parent window from somewhere! Typically the host application that loads and calls the DLL would supply a window handle. It looks like your DLL provides a custom control for an application, so of course the application needs to supply a parent window handle.
Also, you typically need a window handle to the entire application as well, which you set as Application.Handle before you do anything else in your DLL.
ok, thaks for your answers, i already solved (a few minutes before first answer).
first, i need explain why i don't embed, and that is because costumer ask me that way.
the solution is send my form handle to my dll as an argument, after testing that way, i got no errors...
only modificate the prototype of my procedure, to recieve a HWND as an argument, to ParentWindow prop of my control (created in memory).
that's all.