Von Xbase++ aus anderes Xbase++ Programm starten, etc. [erledigt]

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Von Xbase++ aus anderes Xbase++ Programm starten, etc. [erledigt]

Beitrag von Bruno »

Hallo Programmierprofis,
Ich möchte ein Xbase++ Programm machen, hier kurz Funktionsweise.

Kopieren von vorhanden Dateien aus vom Netzlaufwerk auf den PC, ausser den zwei DBF Dateien Dispo und Nachweis.
Struktur von Dispo und Nachweis DBF in leere DBF auf PC anlegen,
Anderes Xbase Programm starten.
Wenn das vom Programm aus gestartete Xbase Programm beendet wurde, und das ist wichtig,
die neuen Dispo und Nachweis DBF in die vorhandenen DBF auf dem Netzlaufwerk einfügen.
Dann das zuerst gestartete Programm beenden.
Wichtig wäre noch, daß das zuerst gestartete Programm nicht mehrfach gestartet werden kann.
Kann man unter Xbase++ ein solches Programm erstellen?

Ich habe keinerlei Erfahrung mit anderen Programmiersprachen, außer anfänglich Clipper und dan Xbase++ ! :D


Wenn dies möglich ist, bitte ich um Hilfestellung, ( dann muss ich das lauffähige Programm, mit Quellcode Verlust, nicht neu schreiben.)
Zuletzt geändert von Bruno am So, 23. Apr 2023 15:11, insgesamt 1-mal geändert.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
sammler0002
UDF-Programmierer
UDF-Programmierer
Beiträge: 63
Registriert: Mi, 23. Dez 2015 22:46
Hat sich bedankt: 21 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von sammler0002 »

Moin Bruno,

wobei genau brauchst Du denn Hilfe?

Um das neu Schreiben wirst Du wohl nicht rum kommen. Oder wolltest Du, dass das jemand für Dich macht?
Grüße von Philipp
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

sammler0002 hat geschrieben: Do, 20. Apr 2023 16:38 Moin Bruno,

wobei genau brauchst Du denn Hilfe?

Um das neu Schreiben wirst Du wohl nicht rum kommen. Oder wolltest Du, dass das jemand für Dich macht?
Das würde ich mir gefallen lassen, wenn das jemand für mich schreiben würde ! :D :D :D

Also so ein Programm schreiben ist kein Problem, ich dachte an Hinweise wo ich ansetzen muss.
z.B. Wie kann ich aus einem Xbase++ Programm ein anderes Xbase++ Programm starten und dabei verhindern das das aufrufende Programm ein weiteres mal gestartet werden kann?

Welche Empfehlung um von einem Netzlaufwerk zu kopieren ( über LW Buchstabe oder ? )

Als erstes bräuchte ich Hilfestellung beim Kopieren, COPY FILE <cSourceFile> TO <cTargetFile>|<cDevice>

Damit kopiere ich eine Datei, gibt es eine Möglichkeit, das ganze Verzeichnis über Xbase zu kopieren ?

Z.B. Copy cVerz to c:\temp\Ziel ?

Ich muss mich erst wieder einarbeiten, habe über 10 Jahre nicht ge-xbased ! :D
Versuch.txt
(410 Bytes) 62-mal heruntergeladen
Zuletzt geändert von Bruno am Do, 20. Apr 2023 17:40, insgesamt 1-mal geändert.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
azzo
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 483
Registriert: So, 28. Mär 2010 19:21
Danksagung erhalten: 11 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von azzo »

Hallo Bruno,
ich habe mal zur Probe deine Frage in ChatGPT eingegeben und diese Antwort erhalten. Denke schaut gar nicht so schlecht aus.
LG
Otto
Her die Erklärung:

Ja, es ist möglich, ein solches Programm mit Xbase++ zu erstellen. Hier sind einige Schritte, die Sie befolgen können, um Ihr Programm zu erstellen:

Kopieren Sie die benötigten Dateien aus dem Netzlaufwerk auf den PC. Sie können dies mit der COPY FILE-Funktion von Xbase++ tun.

Erstellen Sie leere DBF-Dateien auf dem PC, die der Struktur von Dispo und Nachweis entsprechen. Sie können dies mit der CREATE TABLE-Funktion von Xbase++ tun.

Starten Sie das andere Xbase-Programm mit der RUN-Funktion von Xbase++.

Wenn das von Ihrem Programm gestartete Xbase-Programm beendet wurde, fügen Sie die neuen Dispo- und Nachweis-DBF-Dateien in die vorhandenen DBF-Dateien auf dem Netzlaufwerk ein. Sie können dies mit der APPEND FROM-Funktion von Xbase++ tun.

Beenden Sie Ihr erstes Programm mit der QUIT-Funktion von Xbase++.

Verhindern Sie, dass Ihr Programm mehrmals gestartet wird. Sie können dies mit einer einfachen Überprüfung in Ihrem Programmcode tun, bevor das Programm ausgeführt wird.

Code: Alles auswählen

#include "Xbp.ch"
#include "Fileio.ch"
#include "Dbfntx.ch"

PROCEDURE Main()
    LOCAL cNetPath := "N:\DBF\"
    LOCAL cLocalPath := "C:\DBF\"
    LOCAL cDispo := "dispo.dbf"
    LOCAL cNachweis := "nachweis.dbf"

    // Überprüfen, ob das Programm bereits ausgeführt wird
    IF !CheckProgramRunning()
        ? "Programm läuft bereits."
        QUIT
    ENDIF

    // Kopieren der benötigten Dateien vom Netzlaufwerk auf den PC
    CopyFile(cNetPath + cDispo, cLocalPath + cDispo)
    CopyFile(cNetPath + cNachweis, cLocalPath + cNachweis)

    // Erstellen von leeren DBF-Dateien auf dem PC
    CreateTable(cLocalPath + cDispo, "DISPO")
    CreateTable(cLocalPath + cNachweis, "NACHWEIS")

    // Starten des anderen Xbase-Programms
    RUN "C:\Programme\AndereApp.exe"

    // Überprüfen, ob die neuen DBF-Dateien vorhanden sind
    IF File(cLocalPath + cDispo) AND File(cLocalPath + cNachweis)
        // Einfügen der neuen DBF-Dateien in die vorhandenen Dateien auf dem Netzlaufwerk
        APPEND FROM (cLocalPath + cDispo) TO (cNetPath + cDispo)
        APPEND FROM (cLocalPath + cNachweis) TO (cNetPath + cNachweis)

        // Löschen der lokalen DBF-Dateien
        DELETE FILE (cLocalPath + cDispo)
        DELETE FILE (cLocalPath + cNachweis)
    ENDIF

    QUIT
RETURN

FUNCTION CheckProgramRunning()
    LOCAL cMutexName := "MyProgramMutex"
    LOCAL nMutex

    // Versuche, das Mutex zu erstellen
    nMutex := CreateMutex(.T., cMutexName)

    // Wenn das Mutex bereits existiert, dann ist das Programm bereits ausgeführt
    IF nMutex = 0
        RETURN .F.
    END
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

azzo hat geschrieben: Do, 20. Apr 2023 17:34 Hallo Bruno,
ich habe mal zur Probe deine Frage in ChatGPT eingegeben und diese Antwort erhalten. Denke schaut gar nicht so schlecht aus.
LG
Otto
Her die Erklärung:

Ja, es ist möglich, ein solches Programm mit Xbase++ zu erstellen. Hier sind einige Schritte, die Sie befolgen können, um Ihr Programm zu erstellen:

Kopieren Sie die benötigten Dateien aus dem Netzlaufwerk auf den PC. Sie können dies mit der COPY FILE-Funktion von Xbase++ tun.

Erstellen Sie leere DBF-Dateien auf dem PC, die der Struktur von Dispo und Nachweis entsprechen. Sie können dies mit der CREATE TABLE-Funktion von Xbase++ tun.

Starten Sie das andere Xbase-Programm mit der RUN-Funktion von Xbase++.

Wenn das von Ihrem Programm gestartete Xbase-Programm beendet wurde, fügen Sie die neuen Dispo- und Nachweis-DBF-Dateien in die vorhandenen DBF-Dateien auf dem Netzlaufwerk ein. Sie können dies mit der APPEND FROM-Funktion von Xbase++ tun.

Beenden Sie Ihr erstes Programm mit der QUIT-Funktion von Xbase++.

Verhindern Sie, dass Ihr Programm mehrmals gestartet wird. Sie können dies mit einer einfachen Überprüfung in Ihrem Programmcode tun, bevor das Programm ausgeführt wird.

Code: Alles auswählen

#include "Xbp.ch"
#include "Fileio.ch"
#include "Dbfntx.ch"

PROCEDURE Main()
    LOCAL cNetPath := "N:\DBF\"
    LOCAL cLocalPath := "C:\DBF\"
    LOCAL cDispo := "dispo.dbf"
    LOCAL cNachweis := "nachweis.dbf"

    // Überprüfen, ob das Programm bereits ausgeführt wird
    IF !CheckProgramRunning()
        ? "Programm läuft bereits."
        QUIT
    ENDIF

    // Kopieren der benötigten Dateien vom Netzlaufwerk auf den PC
    CopyFile(cNetPath + cDispo, cLocalPath + cDispo)
    CopyFile(cNetPath + cNachweis, cLocalPath + cNachweis)

    // Erstellen von leeren DBF-Dateien auf dem PC
    CreateTable(cLocalPath + cDispo, "DISPO")
    CreateTable(cLocalPath + cNachweis, "NACHWEIS")

    // Starten des anderen Xbase-Programms
    RUN "C:\Programme\AndereApp.exe"

    // Überprüfen, ob die neuen DBF-Dateien vorhanden sind
    IF File(cLocalPath + cDispo) AND File(cLocalPath + cNachweis)
        // Einfügen der neuen DBF-Dateien in die vorhandenen Dateien auf dem Netzlaufwerk
        APPEND FROM (cLocalPath + cDispo) TO (cNetPath + cDispo)
        APPEND FROM (cLocalPath + cNachweis) TO (cNetPath + cNachweis)

        // Löschen der lokalen DBF-Dateien
        DELETE FILE (cLocalPath + cDispo)
        DELETE FILE (cLocalPath + cNachweis)
    ENDIF

    QUIT
RETURN

FUNCTION CheckProgramRunning()
    LOCAL cMutexName := "MyProgramMutex"
    LOCAL nMutex

    // Versuche, das Mutex zu erstellen
    nMutex := CreateMutex(.T., cMutexName)

    // Wenn das Mutex bereits existiert, dann ist das Programm bereits ausgeführt
    IF nMutex = 0
        RETURN .F.
    END
Habe eine txt an den Aufruf angehängt. Zum besseren verstehen.
Und UNC Namen ???

Und DANKE !!! Die ist ja schon eine fast fertige Lösung !
Und Frage Chat GPT ist der hier im Forum ?

In meiner Xbase++ Version gibt es kein CreateMutex und keine Dbfntx.ch !
Zuletzt geändert von Bruno am Do, 20. Apr 2023 18:57, insgesamt 1-mal geändert.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi,
Bruno hat geschrieben: Do, 20. Apr 2023 8:47 die neuen Dispo und Nachweis DBF in die vorhandenen DBF auf dem Netzlaufwerk einfügen.
die Frage ist ob die "alte" Xbase++ App im"Share" Modus arbeitet.
wenn ja könnte man es machen ... aber dann bräuchte man auch nicht das hin/her kopieren
Anderes Xbase Programm starten.

Code: Alles auswählen

FUNCTION SHELLOPENFILE( cPath, cFILE, cPara )
LOCAL lSuccess
LOCAL Retvar   := .F.

   DEFAULT cPath TO ""
   DEFAULT cFILE TO ""
   DEFAULT cPara TO ""

   IF Is64Bit()
      DllCall( "Kernel32.DLL", DLL_STDCALL, "Wow64EnableWow64FsRedirection", FALSE )
   ENDIF

   lSuccess := DllCall( "SHELL32.DLL", DLL_STDCALL, "ShellExecuteA", ;
                        APPDESKTOP() :GetHWND(), ;
                        "open", ;
                        cPath + cFile, ;
                        cPara, ;
                        CURDIR(), ;
                        SW_NORMAL )

   DO CASE

      CASE lSuccess > 32                                              // Aufruf erfolgreich
         Retvar := .T.

      CASE lSuccess = SE_ERR_NOASSOC                                  // Keine verknpfte Anwendung

         // Falls ShowOpenWithDialog = True, wird der Dialog
         // "™ffnen mit" fr diese Datei angezeigt:
         // Shell "RunDLL32 shell32.dll,OpenAs_RunDLL " & Filename

         DllCall( "SHELL32.DLL", DLL_STDCALL, "OpenAs_RunDLL", ;
                  APPDESKTOP() :GetHWND(), ;
                  0, ;
                  cPath + cFile, ;
                  0, ;
                  CURDIR(), ;
                  SW_NORMAL )                                         // SW_MAXIMIZE

         //  Die Auswahlm”glichkeit wird als Erfolg gewertet:
         Retvar := .F.
      OTHERWISE
         // ShellExecute war erfolglos.
         // Boolean-Standardwert False zurckgeben
         DO CASE
            CASE lSuccess = SE_ERR_FNF
               MSGBOX( "File not found.", cPath + cFILE )
            CASE lSuccess = SE_ERR_PNF
               MSGBOX( "Path not found.", cPath + cFILE )
            CASE lSuccess = SE_ERR_ACCESSDENIED
               MSGBOX( "Access denied !", cPath + cFILE )
            CASE lSuccess = SE_ERR_OOM
               MSGBOX( "Out of memory !", cPath + cFILE )
            CASE lSuccess = SE_ERR_SHARE
               MSGBOX( "Cannot share an open file.", cPath + cFILE )
            CASE lSuccess = SE_ERR_ASSOCINCOMPLETE
               MSGBOX( "File association information not complete.", cPath + cFILE )
            CASE lSuccess = SE_ERR_DDETIMEOUT
               MSGBOX( "DDE operation timed out.", cPath + cFILE )
            CASE lSuccess = SE_ERR_DDEFAIL
               MSGBOX( "DDE operation failed.", cPath + cFILE )
            CASE lSuccess = SE_ERR_DDEBUSY
               MSGBOX( "DDE operation is busy.", cPath + cFILE )
         ENDCASE
         Retvar := .F.
   ENDCASE

   IF Is64Bit()
      DllCall( "Kernel32.DLL", DLL_STDCALL, "Wow64EnableWow64FsRedirection", TRUE )
   ENDIF

RETURN Retvar

FUNCTION Is64Bit()
RETURN IF( FILE( "C:\WINDOWS\SysWOW64\Format.COM" ), .T., .F. )
Wichtig wäre noch, daß das zuerst gestartete Programm nicht mehrfach gestartet werden kann.

Code: Alles auswählen

PROCEDURE AppSys
LOCAL cTitle  := "OCal "+xVersion      // hier der "Title-Name"
LOCAL hWndDlg := DllCall( "User32.dll", DLL_STDCALL, "FindWindowA", 0, cTitle )
   IF !( hWndDlg == 0 )
      DllCall( "User32.dll", DLL_STDCALL, "SetForegroundWindow", hWndDlg )
      DllCall( "User32.dll", DLL_STDCALL, "BringWindowToTop", hWndDlg )
      DllCall( "User32.dll", DLL_STDCALL, "ShowWindow", hWndDlg, 1 )
      DllCall( "User32.dll", DLL_STDCALL, "UpdateWindow", hWndDlg )
      *** It is a second instance....  Bye Bye
      QUIT
   ENDIF
RETURN
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

AUGE_OHR hat geschrieben: Do, 20. Apr 2023 18:03 hi,
Bruno hat geschrieben: Do, 20. Apr 2023 8:47 die neuen Dispo und Nachweis DBF in die vorhandenen DBF auf dem Netzlaufwerk einfügen.
die Frage ist ob die "alte" Xbase++ App im"Share" Modus arbeitet.
wenn ja könnte man es machen ... aber dann bräuchte man auch nicht das hin/her kopieren

Ja, das alte Programm arbeitet im Share Modus, es wird nur alles ausgebremst, wenn ein zweiter PC mitarbeitet.
Ich habe nur die Xbasee++ 1.9 Version.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi,
Bruno hat geschrieben: Do, 20. Apr 2023 18:31 Ja, das alte Programm arbeitet im Share Modus, es wird nur alles ausgebremst, wenn ein zweiter PC mitarbeitet.
grundsätzlich läuft der "gemeinsame" Zugriff auf DBF / Index langsamer.

wenn ein 2nd Benutzen auf DBF/Index zugreift wechselt der SMB-Modus von "Exclusive Locks" auf "Opportunistic Locks"
https://learn.microsoft.com/de-de/windo ... stic-locks

deshalb ist sinnvoll eine DBF/Index nur "so lange wie nötig" zu Zugriff zu halten

aber es gibt noch andere Probleme wie "lokal Cache" oder "Netbios over TCP/IP" was man beachten sollte

ich habe dazu ein Tool geschrieben was dir SMB Einstellungen mit PowerShell kontrolliert
https://www.hmgforum.com/viewtopic.php?t=7260
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

Also lege ich mal für den Anfang vor.

Code: Alles auswählen

//////////////////////////////////////////////////////////////////////
//
//  Copyright:
//        Your Copyright goes here., (c) 2000. All rights reserved.
//
//  Contents:
//        This is a standard hybride mode exe.
//
//////////////////////////////////////////////////////////////////////

    #include "Common.ch"
    #include "Directry.ch"
/* This is our main procedure
 */
PROCEDURE Main
    FIELD JAHR

    LOCAL cKey:=""       /* Nur für Testzwecke */

    LOCAL cJahr
    LOCAL cName:=""
    LOCAL cNetPathStamm := "Z:\_DISNIP\DATEN1\"
    LOCAL cNetPathDaten := "Z:\_DISNIP\"
    LOCAL aNetDatei := Directory(cNetPathStamm)
    LOCAL cLokalPathStamm := "C:\_DISNIP\DATEN1\"
    LOCAL cLokalPathDaten := "C:\_DISNIP\"
    LOCAL aDispoDaten:= ""
    LOCAL cDispoDatenLokal:= ""
    LOCAL cDispoDatenNet := ""
    LOCAL aLokalDatei := ""
    SET CHARSET TO ANSI

    AEval( aNetDatei, ;
         {|a| machmal (cName:=a[ F_NAME ],cNetPathStamm,cLokalPathStamm) } )

    WAIT "Habe kopiert ... Eingaben machen" TO cKey

    USE (cLokalPathStamm+"selbst.dbf") ALIAS Selbst
    cJahr:=JAHR+"\"
    CLOSE Selbst
    cDispoDatenLokal:= ALLTRIM(cLokalPathDaten+cJahr)
    cDispoDatenNet := ALLTRIM(cNetPathDaten+cJahr)
/*

Anderes Programm starten, weitere Starts dieses Programmes verhindern,

Nach Programmende des aufgerufenen Programmes Daten ins Netz spielen

*/

    DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)

    aLokalDatei:= Directory(cLokalPathStamm)

    AEval( aNetDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cLokalPathStamm) } )

    WAIT "Habe gelöscht ... Stammdaten" TO cKey

    aLokalDatei:= Directory(cDispoDatenLokal)

    AEval( aLokalDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cDispoDatenLokal) } )

    WAIT "Habe gelöscht ... Dispo Daten" TO cKey

    QUIT

RETURN

FUNCTION machmal(cName,cNetPathStamm,cLokalPathStamm )
    LOCAL cCopyvon:=ALLTRIM(cNetPathStamm+cName)
    LOCAL cCopyzu:=ALLTRIM(cLokalPathStamm+cName)

    COPY FILE (cCopyvon) TO (cCopyzu)
RETURN NIL

FUNCTION loeschmal(cName,cLokalPathStamm)
    LOCAL cLoeschName:=ALLTRIM(cLokalPathStamm+cName)
    DELETE FILE (cLoeschName)
RETURN NIL

FUNCTION DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)
    FIELD ZAEHLER
    LOCAL cKey:=""
    LOCAL cDispoLokal:=""
    LOCAL cDispoNet:=""
    LOCAL cNachweisLokal:=""
    LOCAL cNachweisNet:=""

    cDispoLokal:=ALLTRIM(cDispoDatenLokal+"Dispo.dbf")
    cNachweisLokal:=ALLTRIM(cDispoDatenLokal+"Nachweis.dbf")

    cDispoNet:=ALLTRIM(cDispoDatenNet+"Dispo.dbf")
    cNachweisNet:=ALLTRIM(cDispoDatenNet+"Nachweis.dbf")

    WAIT "Datenübertragung ...." TO cKey

/*    USE (cDispoNet) ALIAS Eingang1 EXCLUSIVE NEW */
    USE (cDispoLokal) ALIAS Ausgang1 SHARED NEW
    USE (cDispoNet) ALIAS Eingang1 EXCLUSIVE NEW

    APPEND FROM (cDispoLokal)

    REPLACE ZAEHLER with RECNO() ALL

    CLOSE Eingang1
    CLOSE Ausgang1

    USE (cNachweisLokal) ALIAS Ausgang2 SHARED NEW
    USE (cNachweisNet) ALIAS Eingang2 EXCLUSIVE NEW

    APPEND FROM (cNachweisLokal)

    REPLACE ZAEHLER with RECNO() ALL

    CLOSE Eingang2
    CLOSE Ausgang2
*/
    WAIT "Datenübertragung Ende" TO cKey

RETURN NIL
damit funktioniert schon mal das Kopieren aller Dateien aus einem Verzeichnis.

Nehme gerne Verbesserungsvorschläge entgegen. :D
Auch Optimierung ist willkommen.
Damit bekomme ich die Stammdaten für die Eingabe lokal, die Arbeitsdatenbanken Dispo und Nachweis werden bei nicht Existenz automatisch erzeugt und sind leer. Erste Hürde geschafft. Jetzt bräuchte ich Hilfe, damit dieses Programm nicht ein zweites mal gestartet werden kann, solange es läuft.
Die entsprechenden Absicherungen weg Neterr etc. muss ich noch machen.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi Bruno,
Bruno hat geschrieben: Do, 20. Apr 2023 17:44 Und Frage Chat GPT ist der hier im Forum ?
ChatGPT ist kein Menschen sondern ein Programm was mit Künstlicher Intelligenz arbeitet
https://chat.openai.com/

leider ist das was ChatGPT "erzählt" oft "zu schön" um wahr zu sein.
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

So habe ich ein Programm, welches vom Netz nach lokal kopiert, wenn dort gearbeitet wird ist die Bremse weg.
Auch das Übertragen der Daten ins Netz funktioniert.
Jetzt fehlt mir noch die Sperre, das dieses Programm nicht ein weiters mal gestartet werden kann, solange es läuft.
Da bräuchte ich echt Eure Hilfe.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Tom »

Hallo, Bruno.

Die ganzen Anmerkungen zu SMB usw. weiter oben kannst Du getrost vergessen. Das spielt in Deinem Fall keine Rolle, und aktuell sowieso kaum noch. Verschenkte Lebenszeit.

Wenn Du wissen willst, ob Deine App bereits läuft, kannst Du das über Windows-API-Funktionen wie FindWindow und ähnliche. Da aber Du selbst die Hoheit hast, geht das auch einfacher, indem Deine Anwendung einfach beim Start eine bestimmte (Hilfs-)Tabelle exklusiv zu öffnen versucht und, wichtig!, dann die ganze Zeit offen hält. Wenn das gelingt (NetErr() antwortet .F.), läuft die Anwendung noch nicht. Wenn es nicht gelingt, läuft sie schon und die neue Instanz kann starten.

Die API-Funktionalität (einfach mal nach "FindWindow" bzw. "FindWindowA" im Forum suchen) hat allerdings den Vorteil, dass die bereits laufende Instanz gleich noch mit Funktionen wie "BringWindowToTop" in den Vordergrund geholt werden kann.
Herzlich,
Tom
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

Hallo Mitglieder,
Dank Eurer Hilfe habe ich jetzt ein kleines Programm zum Netz - Lokal kopieren und auch wieder lokal löschen mit entsprechenden Absicherung wegen Netz usw. fertig.

Wenn ich jetzt ein anders Programm in einem anderen Thread() starten möchte, um die Eingaben lokal machen zu können, bitte um Mithilfe. Ich habe von Klassen überhaupt keine Ahnung und Thread() ist eine Klassen Funktion.

Ich hab sogar eingebaut, das eine DBF erstellt wird, wo man die Verzeichnisse einträgt und somit jederzeit wenn man diese DBF löscht eine neue erstellt wird wo man dann eventuell andere Quell und Zielorte einträgt.

Code: Alles auswählen

#include "Common.ch"
#include "Directry.ch"
/* This is our main procedure
 */
PROCEDURE Main
    FIELD NETSTAMM
    FIELD NETDATEN
    FIELD LOKSTAMM
    FIELD LOKDATEN

    FIELD JAHR
    LOCAL cKey:=""       /* Nur für Testzwecke */
    LOCAL cJahr
    LOCAL cName:=""
    LOCAL cNetPathStamm := "Z:\_DISNIP\DATEN1\"
    LOCAL cNetPathDaten := "Z:\_DISNIP\"
    LOCAL aNetDatei := Directory(cNetPathStamm)
    LOCAL cLokalPathStamm := "C:\_DISNIP\DATEN1\"
    LOCAL cLokalPathDaten := "C:\_DISNIP\"
    LOCAL aDispoDaten:= ""
    LOCAL cDispoDatenLokal:= ""
    LOCAL cDispoDatenNet := ""
    LOCAL aLokalDatei := ""
    SET CHARSET TO ANSI
    IF .NOT. FILE("LW.dbf")           // Falls Datenbank nicht vorhanden
        Laufwerk()                                        // dann erstellen
    ENDIF

    USE LW EXCLUSIVE NEW
    IF Neterr()
        WAIT " Programm läuft schon ....." TO cKey
        QUIT
    ENDIF
    cNetPathStamm := ALLTRIM(NETSTAMM)
    cNetPathDaten := ALLTRIM(NETDATEN)
    cLokalPathStamm := ALLTRIM(LOKSTAMM)
    cLokalPathDaten := ALLTRIM(LOKDATEN)


    AEval( aNetDatei, ;
         {|a| machmal (cName:=a[ F_NAME ],cNetPathStamm,cLokalPathStamm) } )
    WAIT "Habe kopiert ... Eingaben machen" TO cKey
    USE (cLokalPathStamm+"selbst.dbf") ALIAS Selbst
    cJahr:=Alltrim(JAHR)+"\"
    CLOSE Selbst

    cDispoDatenLokal:= cLokalPathDaten+cJahr
    cDispoDatenNet := cNetPathDaten+cJahr
/*.............................................................................*/

/*
Anderes Programm starten, weitere Starts dieses Programmes verhindern,

Nach Programmende des aufgerufenen Programmes Daten ins Netz spielen
*/

/*.............................................................................*/

    DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)
    aLokalDatei:= Directory(cLokalPathStamm)
    AEval( aNetDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cLokalPathStamm) } )
    WAIT "Habe gelöscht ... Stammdaten" TO cKey
    aLokalDatei:= Directory(cDispoDatenLokal)
    AEval( aLokalDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cDispoDatenLokal) } )
    WAIT "Habe gelöscht ... Dispo Daten" TO cKey
    QUIT
RETURN

FUNCTION machmal(cName,cNetPathStamm,cLokalPathStamm )
    LOCAL cCopyvon:=cNetPathStamm+cName
    LOCAL cCopyzu:=cLokalPathStamm+cName
    COPY FILE (cCopyvon) TO (cCopyzu)
RETURN NIL

FUNCTION loeschmal(cName,cLokalPathStamm)
    LOCAL cLoeschName:=ALLTRIM(cLokalPathStamm)+ALLTRIM(cName)
    DELETE FILE (cLoeschName)
RETURN NIL

FUNCTION DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)
    FIELD ZAEHLER
    LOCAL cKey:=""
    LOCAL cDispoLokal:=""
    LOCAL cDispoNet:=""
    LOCAL cNachweisLokal:=""
    LOCAL cNachweisNet:=""
    cDispoLokal:=ALLTRIM(cDispoDatenLokal+"Dispo.dbf")
    cNachweisLokal:=ALLTRIM(cDispoDatenLokal+"Nachweis.dbf")
    cDispoNet:=ALLTRIM(cDispoDatenNet+"Dispo.dbf")
    cNachweisNet:=ALLTRIM(cDispoDatenNet+"Nachweis.dbf")
    USE (cDispoLokal) ALIAS Ausgang1 SHARED NEW
    GO TOP
    IF Zaehler <> 1
        QUIT
    ENDIF
    DO WHILE .T.
        ? " Datenübertragung ..... DISPO ....."
        USE (cDispoNet) ALIAS Eingang1 EXCLUSIVE NEW
        IF ! Neterr()
            APPEND FROM (cDispoLokal)
            REPLACE ZAEHLER with RECNO() ALL
            CLOSE Eingang1
            CLOSE Ausgang1
        ELSE
            LOOP
        ENDIF
        EXIT
    ENDDO
    USE (cNachweisLokal) ALIAS Ausgang2 SHARED NEW
    DO WHILE .T.
        ? " Datenübertragung ..... NACHWEIS ....."
        USE (cNachweisNet) ALIAS Eingang2 EXCLUSIVE NEW
        IF ! Neterr()
            APPEND FROM (cNachweisLokal)
            REPLACE ZAEHLER with RECNO() ALL
            CLOSE Eingang2
            CLOSE Ausgang2
        ELSE
            LOOP
        ENDIF
        EXIT
    ENDDO
    WAIT "Datenübertragung Ende" TO cKey
RETURN NIL
FUNCTION Laufwerk()
      LOCAL aStructure := { ;
              { "NETSTAMM"   , "C", 200, 0 }, ;
              { "NETDATEN"   , "C", 200, 0 }, ;
              { "LOKSTAMM"   , "C", 200, 0 }, ;
              { "LOKDATEN"   , "C", 200, 0 }  }
      DbCreate( "LW", aStructure, "DBFNTX" )

      USE LW NEW EXCLUSIVE
      Browse()
      CLOSE LW
RETURN NIL
Die Wait habe ich nur drinnen wegen besserer Kontrolle, die fliegen aber auch noch raus, wenn es fertig ist mit dem Programmaufruf und entsprechend getestet.
Schaut es Euch an, kann jeder frei nutzen.

P.S. da ich die ganze Nacht am machen war, hau ich mich jetzt erstmal von einem auf das andere Ohr :D :D :D
Nochmals Danke für die Unterstützung.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

Tom hat geschrieben: Fr, 21. Apr 2023 8:32 indem Deine Anwendung einfach beim Start eine bestimmte (Hilfs-)Tabelle exklusiv zu öffnen versucht und, wichtig!, dann die ganze Zeit offen hält. Wenn das gelingt (NetErr() antwortet .F.), läuft die Anwendung noch nicht. Wenn es nicht gelingt, läuft sie schon und die neue Instanz kann starten.

Da sieht man den Wald vor lauter Bäumen nicht :D , ist die einfachste Prüfmöglichkeit, ja vielen Dank.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi Brumo,
Bruno hat geschrieben: Fr, 21. Apr 2023 8:00 Jetzt fehlt mir noch die Sperre, das dieses Programm nicht ein weiters mal gestartet werden kann, solange es läuft.
ich habe hier die PROCEDURE AppSys gepostet die genau das macht was Tom mit API Function gemeint hat

p.s. in der AppSys kann man auch das Hybrid Fenster konfigurieren damit man nicht nur 640 x 480 und 80 x 25 hat

---

ein "RunShell" kann Synchrone oder Asynchrone laufen. ein Thread() oder Windows ShellExecute arbeitet Synchrone

bei einer Asynchrone Ausführung beleibt die Xbase++ App "stehen" während sie bei Synchroner Ausführung "weiter" läuft

---

was dein Konzept mit hin/her kopieren von DBF angeht bin ich skeptisch

Frage : greift die aufgerufene App auf die "kopierten" DBF zu :?:

eine Xbase++ App öffnet DBF defauft "Exclusive" und ich sehe kein

Code: Alles auswählen

   SET EXCLUSIVE OFF                                                  // Netzwerk SHARE
das braucht man aber wenn ein "gemeinsamer" Zugriff erfolgen sol und dann ist der ganze SMB Kram "aktive"
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von brandelh »

Bruno hat geschrieben: Fr, 21. Apr 2023 11:56
Tom hat geschrieben: Fr, 21. Apr 2023 8:32 indem Deine Anwendung einfach beim Start eine bestimmte (Hilfs-)Tabelle exklusiv zu öffnen versucht und, wichtig!, dann die ganze Zeit offen hält. Wenn das gelingt (NetErr() antwortet .F.), läuft die Anwendung noch nicht. Wenn es nicht gelingt, läuft sie schon und die neue Instanz kann starten.

Da sieht man den Wald vor lauter Bäumen nicht :D , ist die einfachste Prüfmöglichkeit, ja vielen Dank.
genau wie Tom schrieb, am Anfang deiner App diese Prüfung ...

Code: Alles auswählen

USE NurEinmal exclusive 
if neterr()
   quit
endif
aus der Hüfte geschossen sollte so eine Routine zwar nicht den 2. Start verhindern, aber ohne Anzeige sofort wieder beenden.
Einfach und gut.

SMB ist immer nur im Netzwerk - nach meiner Erinnerung - auf einem PC ist es das Betriebssystem, das dies vor der Netzwerkkarte erledigt.

Mit Threads brauchst du dich gar nicht beschäftigen, denn du willst eine Anwendung starten, nimm

RUN oder RunShell() mit mehr Kontrolle,
da entscheidest du per Parameter ob das aufgerufene Programm im Vordergrund oder im Hintergrund gestartet wird.
Wenn es im Vordergrund läuft, dann wartet das aufrufende Programm bis es beendet wird.
Was für dich besser ist musst du probieren, auch zu RUNSHELL() findest du hier viele Beispiele verschiedener Autoren (meine meist für PDF Anzeige oder Ausdruck)
Gruß
Hubert
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

AUGE_OHR hat geschrieben: Fr, 21. Apr 2023 18:13 hi Brumo,
Bruno hat geschrieben: Fr, 21. Apr 2023 8:00 Jetzt fehlt mir noch die Sperre, das dieses Programm nicht ein weiters mal gestartet werden kann, solange es läuft.
ich habe hier die PROCEDURE AppSys gepostet die genau das macht was Tom mit API Function gemeint hat

p.s. in der AppSys kann man auch das Hybrid Fenster konfigurieren damit man nicht nur 640 x 480 und 80 x 25 hat

---

ein "RunShell" kann Synchrone oder Asynchrone laufen. ein Thread() oder Windows ShellExecute arbeitet Synchrone

bei einer Asynchrone Ausführung beleibt die Xbase++ App "stehen" während sie bei Synchroner Ausführung "weiter" läuft

---

was dein Konzept mit hin/her kopieren von DBF angeht bin ich skeptisch

Frage : greift die aufgerufene App auf die "kopierten" DBF zu :?:

eine Xbase++ App öffnet DBF defauft "Exclusive" und ich sehe kein

Code: Alles auswählen

   SET EXCLUSIVE OFF                                                  // Netzwerk SHARE
das braucht man aber wenn ein "gemeinsamer" Zugriff erfolgen sol und dann ist der ganze SMB Kram "aktive"
Hi Jimmy, Ja die App greift auf die DBF zu. Bin Grad am Testen mit verschiedenen Laufwerken ( Z:, P: )
Bin noch am schneidern wegen Sicherung der daten.
Aber das eigentliche Dispoprogramm greift auf alle kopierten DBF bis jetzt zu.
Kurz erklärt:
Das Dispoprogramm läuft im Netz und Lokal. Da der letzte Quellcode weg ist dieses Programm. Auf dem PC sind jedoch keine Daten im Programm sondern werden durch dieses reinkopiert. Und zwar Stammdaten wie Fahrer, Kunden, Fahrzeuge, etc. Die werden bei der Eingabe für die Auswahl gebraucht. Die Dispodaten selbst erzeugt das aufgerufene Programm, wenn sie nicht vorhanden sind ( leere DBF, DISPO und NACHWEIS ). Wenn jetzt lokal dieses Programm gestartet wird, lässt sich das Programm im Netz nicht starten. Jedoch können jetzt lokal Dispo Daten eingegeben werden, welche nach Beendigung ins Netz gespielt werden. Hat einen Vorteil, jetzt können theoretisch 250 PCs eingaben machen. Beim einspielen ins Netz versucht jeder PC die Daten zu überspielen, bis er es kann. Sind alle Eingaben für einen Monat erfasst, startet man das Dispoprogramm im Netz und kann somit die Auswertung für Rechnung und Stunden der Fahrer machen. Es gibt also keinen gemeinsamen Zugriff im Netz mehr bei den Eingaben. Bremse gelöst.
Habe noch ein paar Änderungen gemacht, welche aber noch grob sind. Der Hinweis mit der Exclusive DBF lokal, hat mich dazu veranlasst, die Pfade vom Netz und lokal in dieser zu speichern, somit kann sich jederzeit Das Laufwerk ändern und trotzdem funktioniert es.
Zuletzt geändert von Bruno am Fr, 21. Apr 2023 22:34, insgesamt 1-mal geändert.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi Bruno ,
Bruno hat geschrieben: Fr, 21. Apr 2023 21:56 Aber das eigentliche Dispoprogramm greift auf alle kopierten DBF bis jetzt zu.
greifen beider Apps "gleichzeitig" auf die DBF zu :?:
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

AUGE_OHR hat geschrieben: Fr, 21. Apr 2023 22:17 hi Bruno ,
Bruno hat geschrieben: Fr, 21. Apr 2023 21:56 Aber das eigentliche Dispoprogramm greift auf alle kopierten DBF bis jetzt zu.
greifen beider Apps "gleichzeitig" auf die DBF zu :?:
Hi Jimmy
Nein, jeder PC kopiert sich die Daten zum arbeiten aufs lokale Laufwerk.
Beim einspielen ins Netz der Dispodaten ist die Datenbank im Netz gesperrt, solange ein PC überträgt, nach der Übertragung wird das Programm lokal beendet, nächster PC kann dann übertragen.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

Das Programm macht folgendes:
Hole die Stammdaten per kopieren auf die Festplatte ( SSD ), Jetzt Eingaben lokal machen, wenn das aufgerufene Programm beendet worden ist erfolgt das überspielen der Dispodaten in die Datenbank im Netz, sichere die lokal erzeugten DBF im Netz und lösche lokal alle Stammdaten und Dispodaten.
Beim nächsten Start werden wieder die Stammdaten geholt, jedoch keine Dispodaten, die werden als leere DBF vom aufgerufenen Programm erzeugt.
Und sobald man die LW.DBF ( exclusive dbf lokal ) löscht wird beim Neustart eine neue erzeugt wo man dann wieder die Pfadangaben speichern kann.

Code: Alles auswählen

#include "Common.ch"
#include "Directry.ch"
/* This is our main procedure
 */
PROCEDURE Main
    FIELD NETSTAMM
    FIELD NETDATEN
    FIELD LOKSTAMM
    FIELD LOKDATEN

    FIELD JAHR
    LOCAL cKey:=""       /* Nur für Testzwecke */
    LOCAL cJahr
    LOCAL cName:=""
    LOCAL cNetPathStamm := ""
    LOCAL cNetPathDaten := ""
    LOCAL aNetDatei := ""
    LOCAL cLokalPathStamm := ""
    LOCAL cLokalPathDaten := ""
    LOCAL aDispoDaten:= ""
    LOCAL cDispoDatenLokal:= ""
    LOCAL cDispoDatenNet := ""
    LOCAL aLokalDatei := ""
    LOCAL cSelbst:=""
    LOCAL cDispo:=""
    LOCAL aCheck:=""
    LOCAL cUser:= Getenv("COMPUTERNAME")

    SET CHARSET TO ANSI
    IF .NOT. FILE("LW.dbf")           // Falls Datenbank nicht vorhanden
        Laufwerk()                                        // dann erstellen
    ENDIF

    USE LW EXCLUSIVE NEW
    IF Neterr()
        WAIT " Programm läuft schon ....." TO cKey
        QUIT
    ENDIF
    cNetPathStamm := ALLTRIM(NETSTAMM)
    cNetPathDaten := ALLTRIM(NETDATEN)
    cLokalPathStamm := ALLTRIM(LOKSTAMM)
    cLokalPathDaten := ALLTRIM(LOKDATEN)

    aNetDatei := Directory(cNetPathStamm)

    AEval( aNetDatei, ;
         {|a| machmal (cName:=a[ F_NAME ],cNetPathStamm,cLokalPathStamm) } )




    cSelbst:= cLokalPathStamm+"selbst.dbf"

    IF .NOT. FILE(cSelbst)
        quit
    ENDIF
    ? "Habe kopiert ... Eingaben machen"
    USE (cSelbst) ALIAS Selbst
    cJahr:=Alltrim(JAHR)+"\"
    CLOSE Selbst

    cDispo:=cLokalPathDaten+"DISPO.EXE"

    cDispoDatenLokal:= cLokalPathDaten+cJahr
    cDispoDatenNet := cNetPathDaten+cJahr
/*.............................................................................*/

/*
Anderes Programm starten,     */

? curdir()

? RunShell( "", "DISPO.EXE" )




/*.............................................................................*/

    DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)

    DbfSicher(cDispoDatenLokal,cNetPathDaten,cUser )

    aLokalDatei:= Directory(cLokalPathStamm)
    AEval( aNetDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cLokalPathStamm) } )
    ? "Habe gelöscht ... Stammdaten"
    aLokalDatei:= Directory(cDispoDatenLokal)

    AEval( aLokalDatei, ;
         {|a| loeschmal (cName:=a[ F_NAME ],cDispoDatenLokal) } )
    ? "Habe gelöscht ... Dispo Daten"

    QUIT
RETURN

FUNCTION machmal(cName,cNetPathStamm,cLokalPathStamm )
    LOCAL cCopyvon:=cNetPathStamm+cName
    LOCAL cCopyzu:=cLokalPathStamm+cName
    COPY FILE (cCopyvon) TO (cCopyzu)
RETURN NIL

FUNCTION loeschmal(cName,cLokalPathStamm)
    LOCAL cLoeschName:=ALLTRIM(cLokalPathStamm)+ALLTRIM(cName)
    DELETE FILE (cLoeschName)
RETURN NIL

FUNCTION DatenAnfuegen(cDispoDatenLokal,cDispoDatenNet)
    FIELD ZAEHLER
    LOCAL cKey:=""
    LOCAL cDispoLokal:=""
    LOCAL cDispoNet:=""
    LOCAL cNachweisLokal:=""
    LOCAL cNachweisNet:=""

    cDispoLokal:=ALLTRIM(cDispoDatenLokal+"Dispo.dbf")
    cNachweisLokal:=ALLTRIM(cDispoDatenLokal+"Nachweis.dbf")
    cDispoNet:=ALLTRIM(cDispoDatenNet+"Dispo.dbf")
    cNachweisNet:=ALLTRIM(cDispoDatenNet+"Nachweis.dbf")
    USE (cDispoLokal) ALIAS Ausgang1 SHARED NEW
    GO TOP
    IF Zaehler <> 1
        QUIT
    ENDIF
    DO WHILE .T.
        ? " Datenübertragung ..... DISPO ....."
        USE (cDispoNet) ALIAS Eingang1 EXCLUSIVE NEW
        IF ! Neterr()
            APPEND FROM (cDispoLokal)
            REPLACE ZAEHLER with RECNO() ALL
            CLOSE Eingang1
            CLOSE Ausgang1
        ELSE
            LOOP
        ENDIF
        EXIT
    ENDDO
    USE (cNachweisLokal) ALIAS Ausgang2 SHARED NEW
    DO WHILE .T.
        ? " Datenübertragung ..... NACHWEIS ....."
        USE (cNachweisNet) ALIAS Eingang2 EXCLUSIVE NEW
        IF ! Neterr()
            APPEND FROM (cNachweisLokal)
            REPLACE ZAEHLER with RECNO() ALL
            CLOSE Eingang2
            CLOSE Ausgang2
        ELSE
            LOOP
        ENDIF
        EXIT
    ENDDO
    WAIT "Datenübertragung Ende" TO cKey
RETURN NIL
FUNCTION Laufwerk()
      LOCAL aStructure := { ;
              { "NETSTAMM"   , "C", 200, 0 }, ;
              { "NETDATEN"   , "C", 200, 0 }, ;
              { "LOKSTAMM"   , "C", 200, 0 }, ;
              { "LOKDATEN"   , "C", 200, 0 }  }
      DbCreate( "LW", aStructure, "DBFNTX" )

      USE LW NEW EXCLUSIVE
      Browse()
      CLOSE LW
RETURN NIL
function TimeStampXB()
   local cTimeStamp,cTimeStamp2
   cTimeStamp  := dtos(date())+"T"+time()
   cTimeStamp2 := dtos(date())+"T"+time()
   if ! left(cTimeStamp,8) == left(cTimeStamp2,8)
      cTimeStamp := left(cTimeStamp,8)+"T23:59:59"
   endif
return strTran(cTimeStamp,":","")+"L"

FUNCTION DbfSicher(cDispoDatenLokal,cNetPathDaten,cUser)
    LOCAL cKey:=""
    LOCAL cZielnameDispo:=""
    Local cZielnameNachweis:=""
    LOCAL cZeit:=TimeStampXB()
    LOCAL cDispo:=""
    LOCAL cNachweis:=""

    cDispo:=cDispoDatenLokal+"dispo.dbf"
    cNachweis:=cDispoDatenLokal+"nachweis.dbf"

    cZielnameDispo:= cNetPathDaten+"DBF_SICH\"+cZeit+cUser+"dispo.dbf"
    cZielnameNachweis:= cNetPathDaten+"DBF_SICH\"+cZeit+cUser+"nachweis.dbf"

    ? cDispo
    ? cNachweis
    ?
    ? cZielnameDispo
    ? cZielnameNachweis

    COPY FILE (cDispo) TO (cZielnameDispo)
    COPY FILE (cNachweis) TO (cZielnameNachweis)

    ? "Sicherung.............."


RETURN NIL
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi,

ich verstehe noch nicht ganz warum du Daten hin(her kopieren willst da du doch Zugriff im Netzwerk hast
du kannst die DBF mit dem selben Path nutzen den du bei COPY verwendest

"Netzwerk fähig" heisst nicht das du nicht über das Netzwerk zugreifen kannst
du kannst lediglich nicht "gleichzeitig" auf die DBF zugreifen wenn die App nicht "Netzwerk fähig" sind

---

das SMB Problem ist nur dann relevant wenn die Datei "mehrfach" geöffnet wurde im Netzwerk
es ist "dann" auch notwendig den Datensatz beim bearbeiten zu "Sperren" damit nicht "gleichzeitig" ein anderer User die Daten ändert

Frage ; was ist mit Index Dateien NTX oder CDX :?:

es ist wichtig das IMMER auch ALLE zur DBF gehörigen Index Dateien geöffnet werden, auch wenn man nichts ändert

---

Tip :
wenn du bei Console bleiben will dann siehe dir mal c:\ALASKA\XPPW32\Source\SYS\AppSys.prg an
den CODE lädt Xbase++ default, vor Main, wobei ein Console Fenter 640 x 480 mit 80 x 25 sehr klein ist

als Font ist "Alaska Crt" eingestellt aber auch Terminal, Courier oder Lucida Console sind geeignet

in die AppSys gehört auch der DLL Code (an den Anfang) welcher einen 2nd Start verhindert und die App, falls "verdeckt", nach vorn bringt
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

Hi Jimmy,
der Zugriff auf das Programm öffnet 9 Stammdatenbanken mit 16 Indexen, und 2 Dispodatenbanken mit 20 Indexdateien.
Das Programm lief Problemlos bis unter WIN XP im Netzwerk, mit Zugriff von 3 PCs. Mit WIN 7 Updates kamen die ersten Bremsen, da ab WIN 7 nur von einem PC aus darauf zugegriffen wurde, war das egal. Jetzt sollen 4 PCs drauf zugreifen mit schreib und lese Möglichkeit. Da haut die Bremse rein. Das Programm ist Ursprünglich auf einem kleinen Novell Server gewesen, und da gab es keine Bremse. Technik schreitet fort, Bremsen werden dadurch erzeugt. Da ich durch den Quellcode Verlust nicht das lauffähige Programm ändern kann, brauche ich ein Lösung, bis ich das Dispoprogramm komplett neu geschrieben habe.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von brandelh »

Wenn du organisatorisch sicherstellen kannst, dass die Masseneingaben der Rechner sich nicht gegenseitig überschreiben können,
ist es durchaus sinnvoll diese auf lokaler Ebene zu machen. Lokal exklusive Dateien sind halt viel schneller als sich überschneidende.

Ich frage mich aber wie das gehen soll, warum gibt es 4 Rechner, wenn immer nur einer arbeiten darf ?

Meine Haushaltsverwaltung öffnet auch exclusiv, immer nur einer darf, aber wo ich gerade bin ist nicht wichtig,
Ich wähle mich mit RemoteDesktopVerbindung auf den "Server" (win 10 Pro, die home können nicht als Server dienen) ein (über lokales LAN ! eindeutig zu bevorzugen !, DSL oder LTE übers Internet)

Somit ist immer nur einer aktiv, es könnten aber auch mehrere sein, die nacheinander ....
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von AUGE_OHR »

hi Bruno,
Bruno hat geschrieben: Sa, 22. Apr 2023 6:52 Das Programm lief Problemlos bis unter WIN XP im Netzwerk, mit Zugriff von 3 PCs. Mit WIN 7 Updates kamen die ersten Bremsen, da ab WIN 7 nur von einem PC aus darauf zugegriffen wurde, war das egal.
die meisten (älteren) von uns kennen noch den Novell Server und für XP gab es auch einen Windows Client
nun konnte XP schon P2P und dafür "brauchte" man SMB-1 / CIFS

ab Windows 7 kam dann SMB-2 und das sind die SMB-Sachen von denen ich gesprochen habe
grob gesagt gab es nun 2 Wege und Windows "sollte" dann "entscheiden" ... :^o

ab Windows 10 ist default SMB-1 / CIFS "disable", aber NICHT wenn den PC "upgegradet" wurde (wie die meisten älteren PC)
es ist also immer noch aktive ... komplett ABSCHALTEN

es waren Sicherheits-Gründe warum man nicht mehr SMB-1 und UDP Port 135-139 nutzen soll

wenn es einmal "eingeschaltet" war und auf die UDP Ports "hört" ist ein "Listen" aktive
obwohl nichts mehr ankommen "sollte" wird immer noch "Zeit" verschwendet um zu "lauschen"

das ganze hängt mit NetBIOS zusammen was unter SMB-1 genutzt wurde ... ABSCHALTEN !

---

das Tool was ich geschrieben habe prüft mit Powershell diese Punkte.
wenn was nicht "stimmt" wird eine Hilfe eingeblendet mit Bildern "wo" man "was" machen sollte

damit sollten dann die Windows 10/11 Voraussetzungen stimmen für SMB-2 Betrieb

---

es gibt bei SHARE Betrieb 2 SMB Modi : "Exclusive Locks" auf "Opportunistic Locks"
wenn nur 1 x Zugriff erfolgt ist "Exclusive Locks" nicht viel langsamer als USE ... EXCLUSIVE

deshalb ist es falsch wenn man DBF / Index öffnet und "ewig" offen hält

man sollte die DBF/Index nur so lange geöffnet halten wie sie gebraucht wird
das öffnen sollte keine grosser Verzögerung mehr hervorrufen wie früher mit 100 mBit und HDD

leider kannst du das in deinem alten App, ohne Source, nicht mehr ändern.
aber bei der neuen App solltest du es berücksichtigen und eine Netzwerk-fähige Function schreiben die auch gleich alle zugehörigen *.NTX öffnet
gruss by OHR
Jimmy
Benutzeravatar
Bruno
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 103
Registriert: So, 16. Apr 2023 23:11
Wohnort: Lauterbach
Hat sich bedankt: 30 Mal
Danksagung erhalten: 4 Mal

Re: Von Xbase++ aus anderes Xbase++ Programm starten, etc.

Beitrag von Bruno »

brandelh hat geschrieben: Sa, 22. Apr 2023 7:26 Wenn du organisatorisch sicherstellen kannst, dass die Masseneingaben der Rechner sich nicht gegenseitig überschreiben können,
ist es durchaus sinnvoll diese auf lokaler Ebene zu machen. Lokal exklusive Dateien sind halt viel schneller als sich überschneidende.

Ich frage mich aber wie das gehen soll, warum gibt es 4 Rechner, wenn immer nur einer arbeiten darf ?

Meine Haushaltsverwaltung öffnet auch exclusiv, immer nur einer darf, aber wo ich gerade bin ist nicht wichtig,
Ich wähle mich mit RemoteDesktopVerbindung auf den "Server" (win 10 Pro, die home können nicht als Server dienen) ein (über lokales LAN ! eindeutig zu bevorzugen !, DSL oder LTE übers Internet)

Somit ist immer nur einer aktiv, es könnten aber auch mehrere sein, die nacheinander ....
Es dürfen alle Rechner arbeiten ! Es wurde unter WIN 7 bis jetzt nur einer benutzt.
Gruss Bruno
Xbase++ 1.9.355 ohne eExpress
Antworten