esgehtschon
Goto Top

Feststellen ob Word 2003 im Hintergrund läuft

Hallo,

wie kann ich unter VBA (Word 2003) feststellen , ob die Wordanwendung gerade im Hintergrund ausgeführt wird ?

Grüße

Content-ID: 80710

Url: https://administrator.de/contentid/80710

Ausgedruckt am: 26.11.2024 um 15:11 Uhr

misterdemeanor
misterdemeanor 14.02.2008 um 13:26:24 Uhr
Goto Top
Grüß Dich,

inwiefern definierst Du "im Hintergrund"? Ob sie in der Taskleiste minimiert ist oder ob sich eine andere Anwendung über Word befindet, bzw. Word nicht den Fokus hat?

BG, Felix -misterdemeanor-
misterdemeanor
misterdemeanor 14.02.2008 um 14:30:06 Uhr
Goto Top
Für den Fall das Du herausfinden willst ob der Benutzer gerade mit Word arbeitet, respektive Word im Vorgergrund ist schreibe folgendes in ein Modul:

Private Declare Function GetForegroundWindow Lib "user32" () As Long  
Private Declare Function FindWindowByClass Lib "user32" Alias "FindWindowA" _  
  (ByVal lpClassName As String, ByVal lpWindowName As Long) As Long


Public Function WordHasFocus() As Boolean
  Dim hWnd As Long
    hWnd = FindWindowByClass("opusapp", 0&)  
    If CBool(GetForegroundWindow = hWnd) Then
      WordHasFocus = True
    Else
      WordHasFocus = False
    End If
End Function

API Funktionen sind nötig da in Word keine WindowsHandles verfügbar gemacht werden. Hoffe das in Word2003 die entsprechende Klasse immer noch "opusapp" heißt. Getestet mit Word2002(XP).

BG, Felix -misterdemeanor-
esgehtschon
esgehtschon 14.02.2008 um 17:15:24 Uhr
Goto Top
Hallo misterdemeanor,

danke für die Antwort , ich probiere sie dann aus.
Mein Problem ist folgendes: Wir haben ein neues (großes) Programm eingeführt, das seine Dokumente mit Word aufbereitet. Wir wollten nun die Dokumente mit Barcode versehen , damit Rückläufer , wg. Empfänger unbekannt, eingescannt und vollautomatisch den Akten zugeordent werden können. Dafür habe ich ein Barcodeprogramm besorgt , das , über ein VBA-Programm von mir, einen 2D Barcode ins Adressfeld schreiben soll. Das funktionierte auch alles ganz gut unter VBA solange man Word im Dialog aufrief. Sobald jedoch Serienschreiben im Hintergrund (also unsichtbar) abgeabeitet werden, stürzt das Programm mit Fehlermeldung ab. Ich wollte daher eine Abfrage, die mir anzeigt ob Word gerade im Hintergrund arbeitet um das Barcode-Programm dann nicht auszuführen.

MFG
misterdemeanor
misterdemeanor 14.02.2008 um 19:41:27 Uhr
Goto Top
Hallo,

über ein VBA-Programm
von mir, einen 2D Barcode ins Adressfeld
schreiben soll. Das funktionierte auch alles
ganz gut unter VBA solange man Word im Dialog
aufrief.

Also aus Deinem VBA-Programm wird Word manuell(vom User-->DiAlOG) gestartet?

Sobald jedoch Serienschreiben im
Hintergrund (also unsichtbar) abgeabeitet
werden, stürzt das Programm mit
Fehlermeldung ab.

Dein VBA-Programm oder euer neues Programm? Und welches verarbeitet nun die Serienbriefe? Ich nehme jetzt mal an euer neues Programm. Und definiere doch bitte mal "im Hintergrund" genauer: Also WINWORD.EXE im Task-Manager sichtbar aber nicht in der Task-Leiste?

Sorry das ich so viele Fragen stelle face-wink Aber da Du ja etwas mehr erzählt hast glaube ich kaum das Dir der Code aus meinem vorigen Post helfen würde. Folgender (wahrscheinlich) eher.

Das kommt wieder in ein Modul

Public Declare Function EnumWindows Lib "user32" _  
  (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _  
  (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
  
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _  
  (ByVal hWnd As Long, ByVal nIndex As Long) As Long

Const GWL_STYLE = (-16)
Const WS_VISIBLE = &H10000000

Function EnumWinProc(ByVal lhWnd As Long, ByVal lParam As Long) As Long
  Dim RetVal As Long
  Dim WinClassBuf As String * 255
  Dim WinClass As String
  Dim lStyle As Long
    RetVal = GetClassName(lhWnd, WinClassBuf, 255)
    WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces  
    If WinClass = "OpusApp" Then  
      lStyle = GetWindowLong(lhWnd, GWL_STYLE)
      If lStyle And WS_VISIBLE Then
        'hier dann Code falls laufende Word-Anwendung(en)  
      Else
        'und hier der eher wichtigere Teil falls Wordanwendung(en) UNSICHTBAR laufen  
      End If
    End If
    EnumWinProc = True
End Function

Public Function StripNulls(OriginalStr As String) As String
  If (InStr(OriginalStr, Chr(0)) > 0) Then
    OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
  End If
  StripNulls = OriginalStr
End Function

und so rufst Du die EnumWinProc dann auf

  Dim lRet As Long
  Dim lParam As Long
    lRet = EnumWindows(AddressOf EnumWinProc, lParam)

Aber beantworte doch besser noch meine obigen Fragen face-wink

BG, Felix -misterdemeanor-
esgehtschon
esgehtschon 18.02.2008 um 09:47:32 Uhr
Goto Top
Hallo Misterdemeanor,

danke für Deine ausführliche Antwort.
Also, mit "im Hintergrund" meine ich, dass Word nur im Taskmanager zu sehen ist, jedoch nicht auf der Taskleiste. Ich vermute mal, dass Word in diesen Fällen möglicherweise über Ole angesteuert wird, kann das aber nicht sicher sagen.
Wenn das Programm, es handelt sich um ein umfangreiches Buchhaltungsprogramm, die Serienbriefe im Hintergrund verarbeitet, druckt es die Dokumente einfach nicht aus sobald in der Hintergrundbearbeitung ein Fehler erscheint. Auch eine "on error" -Routine hilft da nicht.
Das Word-Dokument wird von dem Buchhaltungsprogramm geöffnet, also nicht von meinem VBA. In der Vorlage (.dot) habe ich jedoch das Ereignis "BeforePrint" aktiviert und lasse mein Programm davon abarbeiten. Ich habe mich also "dazwischengeschaltet".
Diesen etwas umständliche Weg musste ich nehmen, da das Buchhaltungsprogramm das Dokument nicht direkt über VBA erstellt, sondern eine XML-Datei erzeugt, in der der Text vorbereitet wird, und diesen dann in Word einliest. Dabei wechselt die Kontrolle über den Ablauf ein paar mal zwischen dem Buchhaltungsprogramm und Word hin und her.
Der Ablauf ist also fogendermassen:
Dialog: Man ruft im Buchhaltungsprogramm einen Vorgang auf, dieser öffnet ein vorbereitetes Word-Dokument, das aber vom Benutzer noch verändert werden kann. Beim Schließen, wird das Dokument im Buchhaltungsprogramm gespeichert. Beim ausdrucken wird "BeforePrint" ausgelöst und mein Programm fügt den Barcode ein. Das klappt gut.
Serienbriefe: Hier läuft das (Word-Erstellungs) Programm jedoch unsichtbar im Hintergrund, und da gibt es Probleme. Es wird gemeldet dass das Barcode-Program (für 2D Barcode, "TBarCode") nicht geladen werden könne. Warum es geladen werden muss, schließlich ist es über Verweis schon im Vorfeld "angemeldet", ist unklar. Ich vermute, dass das Buchhaltungsprogramm einfach nicht mit Fremdprogrammen zurechtkommt. Wurde vielleicht sogar absichtlich unterbunden.
Ich probiere dann Deinen Code aus und gebe Dir Bescheid.
Danke nochmal, für Deine Mühe.

Gruß
esgehtschon
esgehtschon 18.02.2008 um 13:53:31 Uhr
Goto Top
Hallo Misterdemeanor,

das Programm geht, aus mir unerklärlichen Gründen , in eine Endlosschleife. Ich rufe es, im Testmodus unter VBA, wie unten beschrieben auf.
"EnumWinProc" wird angesprungen, das Programm läuft an , es kommt allerdings bei WinClass der Wert "tooltips_class32" statt "opusApp". Das Programm läuft dann weiter, bis zum Ende und springt dann wieder nach oben auf die allererste Zeile "Function EnumWinProc(ByVal lhWnd As Long, ByVal lParam As Long) As Long".
Das habe so ca. 30 mal durchlaufen lassen, es kommt da nicht mehr raus.
Kenne mich leider mit API-Aufrufen nicht aus.

MFG


mein Programm, wie ich Deine Routine aufrufe (nur der Kopf):
' * HAUPTPROGRAMM *
' Liest die Variablen aus und startet die Programme
Sub Variablen_auswerten()
' Dieses Programm wird durch die Ereignisse "BeforeClose" und "BeforePrint" ausgeführt
If Sys_SperreEreignisse = 1 Then Exit Sub ' Programm wird nicht (mehr) ausgeführt

Dim Zeile As String, Laenge As Integer
Dim Pos_1 As Integer, Pos_2 As Integer, i As Integer
Dim Vars(10) As String, AnzVar As Integer
Dim Barcode As String, SNummern As String
Dim Variablenstring As Variant
Dim lRet As Long, lParam As Long

lRet = EnumWindows(AddressOf EnumWinProc, lParam)


Dein Programm, wie eingefügt:
Public Declare Function EnumWindows Lib "user32" _
(ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long) As Long

Const GWL_STYLE = (-16)
Const WS_VISIBLE = &H10000000

Function EnumWinProc(ByVal lhWnd As Long, ByVal lParam As Long) As Long
Dim RetVal As Long
Dim WinClassBuf As String * 255
Dim WinClass As String
Dim lStyle As Long
RetVal = GetClassName(lhWnd, WinClassBuf, 255)
WinClass = StripNulls(WinClassBuf) ' remove extra Nulls & spaces
If WinClass = "OpusApp_class32" Then
lStyle = GetWindowLong(lhWnd, GWL_STYLE)
If lStyle And WS_VISIBLE Then
' Wenn Word im Vordgrund läuft
Sys_WordImHintergrund = "nein"
Else
' Wenn Word im Hintergrund läuft
Sys_WordImHintergrund = "ja"
End If
End If
EnumWinProc = True
End Function

Public Function StripNulls(OriginalStr As String) As String
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function
misterdemeanor
misterdemeanor 18.02.2008 um 17:09:19 Uhr
Goto Top
Grüß Dich,

lass uns mal zusammenfassen:

  1. Du hast eine Word 2003 Vorlage erstellt. (.dot)
  2. Hierbei handelt es sich um eine Vorlage für Seriendruck.
  3. Neben den SeriendruckFeldern hast Du auch ein OCX-Steuerelement von TBarCode in der Vorlage.
  4. In der BeforePrint/Close Ereignisprozedur versiehst Du das TBarCode Steuerelement mit Daten/dem BarCode.
  5. In Deiner Buchhaltungssoftware kannst Du diese Vorlage auswählen, damit diese verwendet wird.

Nochmal zu 5. : Die BH Software verlangt sogar eine .dot File. Wenn dem so ist gibt es sicher Richtlinien zu dessen Erstellung wie z.B. die Namen der SeriendruckFelder...richtig?


OK, und in der BH Software kann man sich nun einen Brief respektive einen Serienbrief erzeugen lassen(?).

  1. Für einen einzelnen Datensatz wird Word geöffnet, der User kann damit arbeiten und muss es auch schließen. Der BarCode wird in dem Fall richtig erzeugt(?).
  2. Für mehrere Datensätze wird Word unsichtbar geöffnet und es werden die Dokumente gedruckt (oder werden die doc´s gespeichert, Auswahlmöglichkeit vorhanden?) Die von Dir erwähnte .XML File dient Word dann als Datenquelle für den Serienbrief, richtig? Werden diese nur temporär erzeugt/dann gelöscht, oder bleibt diese XMLFile bestehen?

Der besagte Fehler tritt also auch nur auf wenn Du den zweiten "Vorgang" auslöst?. Bitte einmal genauen Fehlercode posten, falls bekannt.

Ist das soweit richtig? Sorry, ich kann schon ziemlich nerven.
Kannst Du mal den Code posten mit welchem Du das TBarCode OCX Element mit Daten "füllst"? Wie ist die .dot Vorlage benannt? Gibt es eine Richtlinie wie der erzeugte Serienbrief benannt wird? Ehrlich gesagt würde die ganze .dot File / Beispiel-Serienbrief (Mit Müller Mustermann; Ingrid Insider) via eMail an mich noch mehr helfen (siehe in meinem Profil)

BG, Felix -misterdemeanor-
misterdemeanor
misterdemeanor 18.02.2008 um 17:14:33 Uhr
Goto Top
Um eine Endlosschleife handelt es sich nicht. Es werden alle TopLevel Fenster (Desktop als Parent) durchlaufen (enumeriert). Das können schon gerne 100 und mehr sein.
Für Dein Problem ist es ohnehin so nicht hilfreich. Mir sind auch noch andere Eigenheiten von Word aufgefallen die einige Erweiterungen erfordern würden. Erstmal lassen wir das so auf Eis liegen. Am besten Du beantwortest/bestätigst/korrigierst mal meinen anderen Post, dann sehen wir weiter face-wink

BG, Felix -misterdemeanor-
esgehtschon
esgehtschon 19.02.2008 um 08:53:53 Uhr
Goto Top
Hallo misterdemeanor,

die Sache ist leider etwas kompliziert.
Also: Das BH-Programm hat nur eine einzige .dot Vorlage für alle auszudruckende Dokumente. Dies ist eine leere Seite die VBA-Code zum Einlesen der XML-Datei, in Kommunikation mit dem BH-Programm, enthält. Der Inhalt der ausgegebenen Dokumente wird im BH-Programm, ohne erkennbare Word-Beteiligung, vollständig aufbereitet und als XML abgelegt. Es wird dann die entsprechende VBA-Routine der Vorlage aufgerufen die die XML-Datei einliest und abwechselnd mit dem BH-Programm, die Seiten aufbereitet. Die genauen Mechanismen sind mir allerdings auch nicht bekannt. Nachdem die Seite aufgebaut ist, kann der Benutzer in Word diese noch ergänzen oder verändern. Außer bei Serienbriefen. Bei Serienbriefen läuft alles unsichtbar im Hintergrund ab.
Da in dieses hin und her des Dokumentaufbaus schlecht einzugreifen ist, habe ich mir überlegt, dass es besser ist zu warten bis das BH-Programm den Text fertig gestellt hat und erst dann, also bevor gedruckt oder bevor das Dokument geschlossen und gespeichert wird, meine Routinen aufzurufen.
Einige Sachen von mir laufen schon. So habe ich eine Seitennummerrierung und ein Druckprotokoll einfügen können, die auch in Serienbriefen einwandfrei laufen.
Wenn der Benutzer das einzelne Worddokument ( in der vollen Word 2003 Funktionalität, aber trotzdem in der Umgebung des BH-Programmes) vor sich hat (also interaktiv) und dieses dann ausdruckt, wird über das "BeforePrint" Ereignis der Barcode eingefügt und mit ausgedruckt. Das klappt gut.
Die Word-Dokumente werden beim Schließen nicht als .doc gespeichert, sondern landen in der internen Datenbank der BH. Wo die XML-Dateien bleiben, konnte ich nicht feststellen, aber ich gehe davon aus, dass diese nur temporär erzeugt werden.
Meine ganzen Zusatzprogrammierungen sind eindeutig von dem BH-Programm nicht vorgesehen und haben daher auch keine Unterstützung des Supports.
Es trat ursprünglich das Problem auf, dass das BH-Programm, aus irgendeinem Grund, keine Seitennummerierung durchführen konnte, so unglaublich das auch klingt, und ich mir deshalb einen Ausweg gesucht habe. So auf den Geschmack gekommen, versuche ich jetzt da noch etwas mehr draus zu machen face-smile.

Mit freundlichen Grüßen
misterdemeanor
misterdemeanor 19.02.2008 um 16:00:57 Uhr
Goto Top
Grützi,

schon komisch, je mehr Du erläuterst desto unklarer wird es für mich face-smile

Also Dein Buchhaltungsprogramm (poste doch mal bitte wie es heißt und von welchem Hersteller) kommt also mit einer eigenen .dot Vorlage die bereits VBA-Code enthält. Dieser bereits vorhandene VBA-Code übernimmt das erstellen des Dokumentes. Den Inhalt erhält es von einer temporär erzeugten XML-File welche vom BH-Programm erzeugt wird.

Die Word-Dokumente werden beim Schließen nicht als .doc gespeichert, sondern landen in der
internen Datenbank der BH.

(?) Die Word-Dokumente selbst landen in dieser Datenbank? Wow. So langsam würde ich mir das wirklich mal vor Ort ansehen wollen. Aber jetzt umsomehr dies ominöse .dot Vorlage...feb(at)wolfsburg.de

BG, Felix -misterdemeanor-
esgehtschon
esgehtschon 21.02.2008 um 07:33:10 Uhr
Goto Top
Hallo misterdemeanor,
Dein Buchhaltungsprogramm (poste doch mal bitte wie es heißt )<<

also das Programm heißt Ikaros (hoffentlich wird das hier nicht als Schleichwerbung geandet) von Ferber-Software.

kommt also mit einer eigenen .dot Vorlage die bereits VBA-Code enthält. Dieser bereits vorhandene VBA-Code übernimmt das erstellen des Dokumentes. Den Inhalt erhält es von einer temporär erzeugten XML-File welche vom BH-Programm erzeugt wird. <<

Ja, so ist es.

>> (?) Die Word-Dokumente selbst landen in dieser Datenbank?<<

Ob jetzt tatsächlich Word *.doc in der Datenbank landen, kann ich nicht sagen. Aber der in Word eingegebene Inhalt wird jedenfalls in der Datenbank gespeichert und als Word-Datei auch wieder genau so ausgegeben.

Aber jetzt umsomehr dies ominöse .dot Vorlage <<
Die .dot kann ich Dir leider nicht schicken , da wir hier vertraglich gebunden sind.

Zwischenzeitlich habe ich auch eine Word-Interne Lösung gefunden, die, bis jetzt zumindest, ganz gut zu funktionieren scheint. Damit ist zwar das eigentliche Problem nicht gelöst, aber ich kann es umgehen.
Ich poste sie weiter oben, damit Andere dafür nicht unsere ganzen Texte durchsuchen müssen.

Nochmals vielen Dank für Deine Antworten.

MFG
esgehtschon
esgehtschon 21.02.2008 um 07:40:23 Uhr
Goto Top
Hallo

Also nach einigem herumprobieren habe ich noch eine Word-interne VBA Lösung finden können.

Dim Sys_WordImVordergrund as Boolean
Sys_WordImVordergrund = ActiveDocument.ActiveWindow.Visible

Das scheint ziemlich zuverlässig zu funktionieren.

MFG