Programm nur eine Instanz, aber wie ProgramParam. übergeben?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Programm nur eine Instanz, aber wie ProgramParam. übergeben?

Beitrag von STARGÅTE »

Tachchen,

Wie ich mein programm in nur einer Instanz starten lassen kann habe ich bereits gefunden:
Programm - nur eine Instanz erlauben

Aber wir kann ich nun zB die Programmparameter die das zwete gestartete Programm bekommt, dann an das erste senden bevor ich das zweite dann wieder schließe ?

Also wenn ich zB eine Datei anklicke, und den Pfad nun an das erste gestartete Programm übergeben will?
Und vorallem wie "merkt" das erste programm das dann ?

Globaler Speicher ? Event ?

Bitte um Hilfe, danke im voraus.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von ts-soft »

Code: Alles auswählen

Procedure OnlyOne(MutexName.s)
  Protected *mem, i, count, para.s, tmp.s, hWnd, hWnd2
  Protected cd.COPYDATASTRUCT
  Protected result = CreateMutex_(0, 0, @MutexName)
  If GetLastError_() = #ERROR_ALREADY_EXISTS
    ReleaseMutex_(result)
    CloseHandle_(result)
    *mem = OpenSharedMemory("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx}")
    hWnd = PeekI(*mem)
    CloseSharedMemory(*mem)
    If IsIconic_(hWnd)
      ShowWindow_(hWnd, #SW_RESTORE)
    EndIf
    SetForegroundWindow_(hWnd)
    count = CountProgramParameters()
    For i = 1 To count
      tmp = ProgramParameter(i - 1)
      If FileSize(tmp) > 0
        para + tmp + ";"
      EndIf
    Next
    If para
      cd\cbData = StringByteLength(para) + SizeOf(Character)
      cd\lpData = @para
      hWnd2 = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
      SendMessage_(hWnd, #WM_COPYDATA, hWnd2, cd)
      While WindowEvent() : Wend
    EndIf
    End
  EndIf
  Prefs("SharedMemory") = Str(CreateSharedMemory("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx}", SizeOf(Integer)))

  ProcedureReturn result
EndProcedure
Kurzbeschreibung:
Für Mutex und SharedMemory benutze ich dieselbe GUID. SharedMemory enthält nur das
hWnd des ersten Fensters, kann man also auch anders lösen.
Wenn erste Instance also existiert, dann setze ich es in den Fordergrund, weil das würde ja
auch passieren, wenn ich die zweite Instanz zulassen würde.

Danach lese ich die Parameter ein, in einen String und übermittle diese per WM_COPYDATA,
wo die erste Instanz dies dann im Callback mitbekommt und bearbeitet.

Falls ich doch der erste bin, wird dann der SharedMemory erstellt, in dem ich nach erstellen
des Fensters den hWnd poke.

Ich hoffe Du kommst damit so klar.

Gruß
Thomas

//edit:
Hier noch der entsprechende Ausschnitt aus dem Callback:

Code: Alles auswählen

Procedure WIN_MAIN_CB(hWnd, Msg, wParam, lParam)
  Protected *cd.COPYDATASTRUCT
  Protected para.s, i, count, tmp.s
  Protected Result
  
  Result = #PB_ProcessPureBasicEvents
  
  Select Msg
    
    Case #WM_COPYDATA
      *cd = lParam
      para = PeekS(*cd\lpData)
      count = CountString(para, ";")
      For i = 1 To count
        tmp = StringField(para, i, ";")
        Edit_New(tmp)
      Next
  
  ProcedureReturn Result
EndProcedure
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von STARGÅTE »

Danke schon mal,
aus welcher Quelle nimmst du SharedMemory() befehle ?
Im Forum scheint nichts aktuelles zu sein ...

UNd das mit dieser GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx}" ist doch frei ausgedacht oder ? ich kann doch genausogut einen "normalen" Namen für den Memory nutzen oder ?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von RSBasic »

@STARGÅTE
Wenn man nach "OpenSharedMemory" sucht, dann findet man zwei Threads von ts-soft und seine Codes/Includes funktionieren auch. Oder bekommst du irgendwelche Fehler?
STARGÅTE hat geschrieben:UNd das mit dieser GUID "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx}" ist doch frei ausgedacht oder ? ich kann doch genausogut einen "normalen" Namen für den Memory nutzen oder ?
Ja kannst du auch machen. (Laut Beispiel von ts-soft in einem anderen Thread)
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von STARGÅTE »

Nachdem ich die Namen umgeändert habe nicht mehr :wink:

Ich dachte ja er hat auf http://www.realsource.de/ irgendwo etwas ^^
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von ts-soft »

shared memory:

Code: Alles auswählen

Define HandleMap

Procedure CreateSharedMemory(Name.s, Size)
  Shared HandleMap
  HandleMap = CreateFileMapping_(#INVALID_HANDLE_VALUE, 0, #PAGE_READWRITE|#SEC_COMMIT|#SEC_NOCACHE, 0, Size, @Name)
  If HandleMap
    ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
  EndIf
EndProcedure

Procedure OpenSharedMemory(Name.s)
  Shared HandleMap
  HandleMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, @Name)
  If HandleMap
    ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
  EndIf
EndProcedure

Procedure CloseSharedMemory(MemoryAddress)
  Shared HandleMap
  UnmapViewOfFile_(MemoryAddress)
  CloseHandle_(HandleMap)
EndProcedure
MakeGUID:

Code: Alles auswählen

CompilerIf Defined(GUID, #PB_Structure) = #False
Structure GUID
  Data1.l
  Data2.w
  Data3.w
  Data4.b[8]
EndStructure
CompilerEndIf

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
; requires uuid-dev
ImportC "-luuid"
  uuid_generate(*out.GUID)
  uuid_unparse_upper(*uu.GUID, *out)
EndImport
CompilerEndIf

Procedure.s MakeGUID()
  Protected guid.GUID, result.s
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      result = Space(36)
      uuid_generate(@guid)
      uuid_unparse_upper(@guid, @result)
      result = "{" + PeekS(@result, -1, #PB_Ascii) + "}"        
    CompilerCase #PB_OS_Windows
      Protected lpsz.s{76}
      If CoCreateGuid_(@guid) = #S_OK
        result = PeekS(@lpsz, StringFromGUID2_(guid, @lpsz, 76), #PB_Unicode)
      EndIf      
    CompilerDefault
    
  CompilerEndSelect
  
  ProcedureReturn result
EndProcedure
PS: ich würde immer eine GUID für solche Dinge verwenden, nur so kann man sicher sein, der Name ist einmalig!
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von STARGÅTE »

Danke, werde mir mal alles genauer angucken.

Noch eine Frage zu SharedMemory:

Du verwendest da ein HandleMap für "alle", heißt das, ich kann nur ein SharedMemory nutzen ?
DEnn wenn ich zB zwei erstelen würde, würde ja der zweite den ersten HandleMap überschreiben.
Beim schließen würde er dann immer nur den 2. schießen, weil der erste verloren gegangen ist, in bezug auf CloseHandle_()
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von ts-soft »

STARGÅTE hat geschrieben:Noch eine Frage zu SharedMemory:

Du verwendest da ein HandleMap für "alle", heißt das, ich kann nur ein SharedMemory nutzen ?
HandleMap wird doch nur intern verwandt, ist also kein Rückgabewert, mit dem Du arbeiten mußt :wink:
Du kannst soviele Maps anlegen, wie virtueller Speicher erreichbar ist. Für Dein Vorhaben aber nicht
so sinnvoll, weil es ja keine Events gibts. Deshalb ja auch WM_COPYDATA.

Die Map wird erst mit dem schliessen der letzten Instance komplett geschlossen, wie beim laden von DLLs.

//edit
Die CloseFunktion solltest Du für mehrere Maps aber noch abändern. Letzte Zeile entfernen, handle wird
mit schliessen des Fensters automatisch freigegeben, genauso wie das Handle für den Mutex.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von STARGÅTE »

Nach langem rumprobieren, scheint bei mir irgendwie das "CopyData" nicht zu funktionieren.

Hier mal ein reduzierter Code:

Code: Alles auswählen


Text.s = "Hallo"

CopyData.COPYDATASTRUCT
CopyData\cbData = StringByteLength(Text) + SizeOf(Character)
CopyData\lpData = @Text

OpenWindow(1,100,100,100,100,"1")
OpenWindow(2,300,100,100,100,"2")

SendMessage_(WindowID(2), #WM_COPYDATA, WindowID(1), @CopyData)
;SendMessage_(WindowID(2), #WM_CLOSE, 0, 0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      CloseWindow(EventWindow())
    Case #WM_COPYDATA
      Debug "COPYDATA"
  EndSelect
Until #False
Es kommt einfach nix an (also kein "COPYDATA")
Wenn ich stattdessen #WM_CLOSE senden, wird es auch wirklich geschlossen ...
was mach ich falsch ?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Programm nur eine Instanz, aber wie ProgramParam. überge

Beitrag von ts-soft »

Was meinst Du, warum ich das Callback als Beispiel gepostet habe? :wink:
Im PB eventloop kommt ja leider nicht allzuviel an.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten