Delphi Pages Forums  

Go Back   Delphi Pages Forums > Delphi Forum > General

Lost Password?

Reply
 
Thread Tools Display Modes
  #1  
Old 01-14-2001, 03:31 AM
whatever_ whatever_ is offline
Member
 
Join Date: Jan 2001
Posts: 36
Default Command Line Arguments?

Hey,
I am limiting the instances of my program to one.. When a 2nd instance is being executed it is terminated and the first instance is being focused.

But how do I pass the command line arguments from the 2nd instance to the 1st?
ATM I am copying the arguments from 2nd instance to clipboard and pasting back in 1st...
But this solution isn't very good because clipbrd is bein overwritten

so any1 knows a better solution?
thx
Reply With Quote
  #2  
Old 01-14-2001, 10:07 PM
medialight medialight is offline
Junior Member
 
Join Date: Nov 2000
Posts: 4
Default RE: Command Line Arguments?

Hi,
I have some suggestions for you:

1). Try to do the same, but with files
2). Try to move all lines from the ClipBoard to TStrinList and then add it back
3). http://www.delphipages.com/tips/thread.cfm?ID=68 or http://www.torry.net/samples/samples/os/appsdemo.zip

Kind Regards,
Serge M.
Reply With Quote
  #3  
Old 01-15-2001, 02:04 AM
Lapince Lapince is offline
Senior Member
 
Join Date: Jan 2001
Posts: 163
Default RE: Command Line Arguments?

Here's the best way for me to do so... It's an article published in UNDU April 1998... If you don't want to read the article, just copy the unit included in it... I used it many times, and it's perfect, and you don't have to overwrite data in clipboard...
If you want more details, mail me (lapince@ifrance.com)
The article :

For many programs, having more than one instance running at the same time isn't a problem. It may even be a desirable feature, in SDI applications like Notepad, for instance. Often, though, the program will read and write data files (or registry keys) in a way which will cause corruption if another copy is launched, or it may simply not make any sense to have multiple instances running. In these cases it is valuable to have a simple mechanism to detect and control instance launches, especially with Windows 98 and its single-click launch interface.

Under 16 bit Windows, the solution was simple; Just examine the previous instance global variable to see if a copy is already running, and do the right thing. Under Win32, things are a bit more complicated. Several solutions are available on the Web, including one on the Borland Tips page, but I still felt compelled to write my own for several reasons. First, I needed to transmit the command line parameters of a second launch attempt to the primary instance in one program I wrote (it processes BMP files dragged onto its Explorer icon). Second, I wanted a plug-in unit which required minimal alteration from one program to the next, and little or no foolery in my DPR file. Third, I wanted it to be secure, reliable, and fast; In particular, it should run before any other VCL code initializes or allocates anything.

To meet the first requirement, I used WM_COPYDATA on the command line string. This in turn required me to get a window handle from the primary instance to use as a target for the message. FindWindow handles this nicely, but I couldn't use the automatic application window or any other standard window of the application, because of the third requirement.

The second requirement led me to place all of the code into a unit which is simply placed in the DPR "uses" clause. The actual instance management code runs in the unit's initialization. Global variables in the interface part provide the event hook and passed data storage.

Due to the third requirement, the unit must be the very first unit used by the DPR, and could not use any other application unit. In particular, almost every unit is likely to use Forms, and Forms is normally the first unit used by a DPR, but Forms sets up and initializes the whole Application framework.

The result of all this is the InstanceManager unit below. Simply make it the first unit in your program's DPR's uses list, and edit the constant declarations to fit your needs. Note that by using the same string constant for two or more different programs, you can create a "family" of executables which share instance management - I use this ability in a timeclock program, which not only should not run more than once, but cannot run at the same time as its administative utility. Also, this unit doesn't just prevent a second instance from running. It can call a notification event, which can decide on a case-by-case basis whether to allow the other instance to run, perhaps by examining the command line.

unit InstanceManager;
interface

{Notes: make InstanceManager the *very first* unit in your program's USES
clause. To take advantage of the notification and launch-string, put a
method with no parameters in one of your forms and assign it to triggerProc.
Once triggerProc is called, rcvStr contains the command line of the launch
attempt.

If the only reaction you want is to bring the first instance to the front,
just put a method like the following in your main form, and in the form's
OnCreate set InstanceManager.triggerProc:=ToFront;

procedure TForm1.ToFront;
begin
Application.Restore;
Application.BringToFront;
end;

If you don't have a dependable main form, make ToFront a class procedure of
any old class.}

{ Customize these constants before using }
const UniqueAppName = 'Unique application name';
AppNotifyValue: integer = 0;

var rcvStr: string;
rcvValue: integer;
ForbidOtherInstance: boolean = True;
triggerProc: procedure of object;

implementation

uses Windows, SysUtils, Messages;

var mutex, thisWnd: HWND;
IMWndClass: TWndClassA;
mustHalt: boolean;
copydata: TCOPYDATASTRUCT;

function IMWndProc(HWindow: HWnd; Message, WParam: Longint; LParam: Longint): Longint; stdcall;
begin
if Message=WM_COPYDATA then
begin
rcvStr := StrPas(PCOPYDATASTRUCT(lParam).lpData);
rcvValue := PCOPYDATASTRUCT(lParam).dwData;
if Assigned(triggerProc) then triggerProc;
Result := Ord(ForbidOtherInstance);
end
else
Result := DefWindowProc(hWindow, Message, WParam, LParam);
end;

initialization

FillChar(IMWndClass, SizeOf(IMWndClass), 0);
IMWndClass.lpfnWndProc := @IMWndProc;
IMWndClass.hInstance := HINSTANCE;
IMwndClass.lpszClassName := 'TInstanceManager';
if Windows.RegisterClass(IMWndClass) = 0 then RaiseLastWin32Error;
mutex := CreateMutex(nil, True, UniqueAppName);
if GetLastError = ERROR_ALREADY_EXISTS then
begin
mustHalt := True;
if WaitForSingleObject(mutex, 5000)=WAIT_OBJECT_0 then
begin
thisWnd := FindWindow(IMwndClass.lpszClassName, UniqueAppName);
if thisWnd = 0 then RaiseLastWin32Error;
CopyData.dwData := AppNotifyValue;
CopyData.lpData := CmdLine;
CopyData.cbData := StrLen(CmdLine);
mustHalt := (SendMessage(thisWnd,WM_COPYDATA,0,Integer(@CopyDa ta))>0);
end;
thisWnd := 0;
ReleaseMutex(mutex);
if mustHalt then Halt;
end
else
begin
thisWnd := CreateWindow(IMwndClass.lpszClassName,UniqueAppNam e,0,0,0,0,0,0,0,hInstance, nil);
if thisWnd = 0 then RaiseLastWin32Error;
ReleaseMutex(mutex);
end;

finalization
if thisWnd>0 then DestroyWindow(thisWnd);

end.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump


All times are GMT. The time now is 08:43 PM.


Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2019, vBulletin Solutions, Inc.