Nachricht an andere Anwendung
-
Hi,
also ich möchte den mehrfachen Programmstart unterbinden (klappt schon) und wenn das Programm schon läuft an das alte Prog eine Nachricht schicken, so vonwegen öffne mal Datei so und so! Wie mache ich das?MFG
Alexander Sulfrian
-
Entweder mit Mailslots oder besser mit Mapped Files wie das heißt.
-
Ich poste einfach die ganzen Quellcodes wie ich das gemacht habe.
SharedMem.h
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SharedMem.h Copyright (c) 2002 by EM. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, * * USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //--------------------------------------------------------------------------- //%SCRTASK: Kapselung von File-Mapping Funktionen (Gemeinsame Speicherverwaltung) // //%VERSION: 1.0 23.08.2002 //%AUTHOR: EM //%REQUIRE: Borland CBuilder 5.0 or greater //--------------------------------------------------------------------------- #ifndef SharedMemH #define SharedMemH //--------------------------------------------------------------------------- class TSharedMem{ HANDLE hMapFile; LPVOID lpMapAddress; AnsiString FName; int FSize; bool FIsFirst; public: TSharedMem(AnsiString Name,int Size); virtual ~TSharedMem(); void Write(void* Buf, int len); void Read(void* Buf, int len); __property AnsiString Name={read=FName}; __property int Size={read=FSize}; __property bool IsFirst={read=FIsFirst}; }; #ifndef SharedMem_Linked #define SharedMem_Linked #pragma link "SharedMem.obj" #endif #endif
SharedMem.cpp
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SharedMem.cpp Copyright (c) 2002 by EM. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, * * USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <sysutils.hpp> #pragma hdrstop #include "SharedMem.h" //--------------------------------------------------------------------------- #pragma package(smart_init) TSharedMem::TSharedMem(AnsiString Name, int Size) :FName(Name), FSize(Size) { if ((hMapFile=OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, Name.c_str()))==NULL){ hMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, Size, Name.c_str()); if (hMapFile==NULL) throw Exception("CreateFileMapping fehlgeschlagen"); FIsFirst=true; }else{ FIsFirst=false; } lpMapAddress=MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0,0,0); if (lpMapAddress==NULL) throw Exception("MapViewOfFile fehlgeschlagen"); } //--------------------------------------------------------------------------- TSharedMem::~TSharedMem() { if (!UnmapViewOfFile(lpMapAddress)) throw Exception("UnmapViewOfFile fehlgeschlagen"); } //--------------------------------------------------------------------------- void TSharedMem::Write(LPVOID Buf, int len) { if (len>0) memcpy(lpMapAddress, Buf, len); } //--------------------------------------------------------------------------- void TSharedMem::Read(LPVOID Buf, int len) { if (len>0) memcpy(Buf, lpMapAddress, len); } //---------------------------------------------------------------------------
Mutex.h
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mutex.h Copyright (c) 2002 by EM. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, * * USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ //--------------------------------------------------------------------------- //%SCRTASK: Kapselung für Mutex-Funktionen // //%VERSION: 1.0 23.08.2002 //%AUTHOR: EM //%REQUIRE: //--------------------------------------------------------------------------- #ifndef MutexH #define MutexH //--------------------------------------------------------------------------- class EMutexExists: public Exception{ public: EMutexExists(AnsiString Msg); }; class TMutex { AnsiString FName; HANDLE FHandle; public: TMutex(AnsiString Name); virtual ~TMutex(); bool Create(); bool Release(); __property AnsiString Name={read=FName}; __property HANDLE Handle={read=FHandle}; }; #ifndef Mutex_Linked #define Mutex_Linked #pragma link "Mutex.obj" #endif #endif
Mutex.cpp
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mutex.cpp Copyright (c) 2002 by EM. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, * * USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <vcl.h> #pragma hdrstop #include "Mutex.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- // EMutexExists //--------------------------------------------------------------------------- EMutexExists::EMutexExists(AnsiString Msg) :Exception(Msg) { } //--------------------------------------------------------------------------- // TMutex //--------------------------------------------------------------------------- TMutex::TMutex(AnsiString Name) :FName(Name) { FHandle=CreateMutex(NULL, FALSE, Name.c_str()); if (GetLastError()==ERROR_ALREADY_EXISTS) throw EMutexExists("Mutex \"" + FName + "\" ist schon vorhanden."); } //--------------------------------------------------------------------------- TMutex::~TMutex() { ReleaseMutex(FHandle); } //--------------------------------------------------------------------------- bool TMutex::Create() { if (FHandle!=NULL) CreateMutex(NULL,FALSE,FName.c_str()); return (FHandle!=NULL); } //--------------------------------------------------------------------------- bool TMutex::Release() { return ((bool)ReleaseMutex(FHandle)); }
Dann das Ganze in einem Anwendungsprojekt hinterlegt
Header NewAppMain.h
//--------------------------------------------------------------------------- #ifndef NewAppMainH #define NewAppMainH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "SharedMem.h" #include "Mutex.h" //--------------------------------------------------------------------------- typedef void __fastcall (__closure *TOnDropFiles)(TObject* Sender, const TStringList* items); // Wird aufgerufen wenn StandAlone = true und neue Instanz eines offnen Programms //- erstellt wird. typedef void __fastcall (__closure *TOnNewInstance)(const TStringList* args); //--------------------------------------------------------------------------- class TExtForm : public TForm { __published: private: bool FDragFileAccept; void SetDragAccept(bool value); void __fastcall WMDropFiles(TWMDropFiles &msg); TOnDropFiles FOnDropFiles; bool FStandAlone; void SetStandAlone(bool value); TSharedMem* FMemory; AnsiString GetSharedMemName(); TMutex* FMutex; AnsiString GetMutexName(); DWORD FMyMsg; AnsiString GetMessageName(); void __fastcall FormWndProc(TMessage &Message); TOnNewInstance FOnNewInstance; TStringList* FArguments; protected: static const AnsiString SHARED_MEM_NAME; static const AnsiString MESSAGE_NAME; static const AnsiString MUTEX_NAME; __property AnsiString MutexName = { read = GetMutexName }; __property AnsiString SharedMemName = { read = GetSharedMemName }; __property AnsiString MessageName = { read = GetMessageName }; public: __fastcall TExtForm(TComponent* Owner); virtual __fastcall ~TExtForm(); static void ParseParams(const AnsiString& str, TStringList* strlst); // Drag & Drop von Dateien __property bool DragFileAccept = { read = FDragFileAccept, write = SetDragAccept }; // Ereignisbehandlung, für Dateien per Drag & Drop __property TOnDropFiles OnDropFiles = { read = FOnDropFiles, write = FOnDropFiles }; // Nur eine Instanz __property bool StandAlone = { read = FStandAlone, write = SetStandAlone }; __property TOnNewInstance OnNewInstance = { read = FOnNewInstance, write = FOnNewInstance }; __property TStringList* Arguments = { read = FArguments }; BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles); END_MESSAGE_MAP(TForm); }; //--------------------------------------------------------------------------- extern PACKAGE TExtForm *ExtForm; //--------------------------------------------------------------------------- #endif
NewApp.cpp
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "NewAppMain.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TExtForm *ExtForm; const AnsiString TExtForm::SHARED_MEM_NAME = ".SharedMem"; const AnsiString TExtForm::MESSAGE_NAME = ".Message"; const AnsiString TExtForm::MUTEX_NAME = ".Mutex"; //--------------------------------------------------------------------------- __fastcall TExtForm::TExtForm(TComponent* Owner) : TForm(Owner), DragFileAccept(false), FOnDropFiles(NULL) { FStandAlone = false; this->WindowProc=FormWndProc; FMemory = NULL; FMutex = NULL; FOnNewInstance = NULL; FArguments = new TStringList(); } //--------------------------------------------------------------------------- void TExtForm::SetStandAlone(bool value) { FStandAlone = value; if (value){ if (FMemory == NULL) FMemory=new TSharedMem(SharedMemName, 255); try{ if (FMutex == NULL) FMutex=new TMutex(MutexName); }catch(const EMutexExists& e){ int len = FArguments->Count; len = strlen(FArguments->GetText()) + 1; FMemory->Write( FArguments->GetText(), len ); DWORD procId; GetWindowThreadProcessId(Handle, &procId); SendMessage(HWND_BROADCAST, FMyMsg, len, procId); Application->Terminate(); } }else{ if (FMemory != NULL) delete FMemory; if (FMutex != NULL) delete FMutex; } } //--------------------------------------------------------------------------- __fastcall TExtForm::~TExtForm() { StandAlone = false; delete FArguments; } //--------------------------------------------------------------------------- void TExtForm::SetDragAccept(bool value) { DragAcceptFiles( Handle, value ); FDragFileAccept = value; } //--------------------------------------------------------------------------- void __fastcall TExtForm::WMDropFiles(TWMDropFiles &msg) { if ( FOnDropFiles == NULL ) return; int count = DragQueryFile( (HDROP) msg.Drop, 0xFFFFFFFF, NULL, 0 ); char buf[MAX_PATH]; TStringList* items = new TStringList(); for (int i=0; i<count; i++){ DragQueryFile( (HDROP)msg.Drop, i, buf, MAX_PATH ); items->Add( buf ); } FOnDropFiles(this, items); delete items; } //--------------------------------------------------------------------------- AnsiString TExtForm::GetSharedMemName() { return ExtractFileName(Application->ExeName) + SHARED_MEM_NAME; } //--------------------------------------------------------------------------- AnsiString TExtForm::GetMutexName() { return ExtractFileName(Application->ExeName) + MUTEX_NAME; } //--------------------------------------------------------------------------- AnsiString TExtForm::GetMessageName() { return ExtractFileName(Application->ExeName) + MESSAGE_NAME; } //--------------------------------------------------------------------------- void __fastcall TExtForm::FormWndProc(TMessage &Message) { DWORD procId; GetWindowThreadProcessId(this->Handle,&procId); if((Message.Msg == FMyMsg) && (Message.LParam != (LPARAM)procId)){ char* szMsg = new char[Message.WParam]; FMemory->Read(szMsg, Message.WParam); szMsg[Message.WParam]='\0'; if (FOnNewInstance != NULL ){ TStringList* args = new TStringList(); args->SetText(szMsg); FOnNewInstance( args ); delete args; } delete szMsg; }else{ this->WndProc(Message); } } //--------------------------------------------------------------------------- void TExtForm::ParseParams(const AnsiString& str, TStringList* strlst) { #ifdef _DEBUG if (strlst == NULL) throw Exception("strlst darf nicht NULL sein"); #endif TStringList* zwischen = new TStringList(); AnsiString tmp = StringReplace( str, " ", "\n", TReplaceFlags() << rfReplaceAll ); zwischen->SetText( tmp.c_str() ); tmp = ""; bool inBrackets = false; for (int i = 0; i <= zwischen->Count; i++){ if ( (! inBrackets) && (tmp != "") ){ strlst->Add( Trim(tmp) ); tmp = ""; if (i == zwischen->Count) break; } AnsiString s = zwischen->Strings[i]; if (s.SubString(1,1) == "\""){ inBrackets = true; } AppendStr(tmp, StringReplace(s, "\"", "", TReplaceFlags() << rfReplaceAll) + " "); if (s.SubString(s.Length(), 1) == "\"") inBrackets = false; } strlst->Delete(0); delete zwischen; } //---------------------------------------------------------------------------
Dann kommt das Ganze in die Projektgallerie.
Wenn Du dann willst das die ganzen Parameter von der zweiten Instanz übertragen werden. Musst Du TExtForm::StandAlone = true setzen und das OnNewInstance Ereignis überschreiben
-
Hoffen wir, daß niemand frägt, wie der IE-Explorer funktioniert...
-
Der IE kann auch nicht viel umständlicher sein.
Beispiele für "SingleInstance"-Programme gibt es u.a. auch hier, für die Parameterübergabe an die erste Programminstanz kann dann z.B. SendMessage o.ä. mit WM_COPYDATA verwendet werden.
-
1. zur mehrfachen ausführung
http://www.bytesandmore.de/rad/index.htm?http://www.bytesandmore.de/rad/cpp/snipp/sc06014.php
2. zur übergabe von paramentern
http://www.bytesandmore.de/rad/index.htm?http://www.bytesandmore.de/rad/cpp/snipp/sc06016.php