Pozastavení aplikace   otázka

VB.NET

Prosím o radu, jak pozastavit zpracovávání programu do ukončení Wordu, který je spouštěn právě z tohoto programu. V programu mám pro událost tlačítka připravenou kontrolu naplnění potřebných proměnných, kontrolu adresáře, souboru .doc atd. Potom spouštím Word, doplňuji proměnné do záložek Wordu a zobrazuji Word pro konečnou editaci .doc. V tomto okamžiku potřebuji pozastavit aplikaci až do okamžiku ukončení Wordu, kdy dále aplikace zaznamenává ne/splnění úkolu. Pozastavení by mělo reagovat pouze na spuštěný Word s daným souborem .doc (aby nečekal na ukončení všech dokumentů v případě více otevřených .doc dokumentů).

Předpokládám řešení pomocí Threading.Thread.Sleep( ... ), ovšem tady končím. Předem moc děkuji.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A proč nemáte veškeré zadávání a validaci dat napsanou ve VBA/VSTO přímo v daném dokumentu abyste se vyhnul právě takovým problémům?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Aplikace slouží pro usnadnění rutinních činností při vedení komerčních zakázek. Data zakázek jsou uložena v txt souboru (tím jsem se vyhnul SQL - neumím). S VBA jsem doposud nepracoval, VSTO ani neznám. Wordovské formuláře jsou firemními řízenými dokumenty, i proto mi přišlo jednodušší je "pouze vyplňovat" z aplikace, která rovněž eviduje vydané dokumenty.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Být vámi bych okamžitě začal hledat nějaké profesionální (na zakázku) řešení, nebo se velice rychle dostanete do problémů z kterých se nevysekáte. Divím se, že už v tomto stádiu vám to vůbec nějak funguje. Záleží samozřejmě na tom, kolik zaměstnanců toto řešení používá, pro 3 lidi by bylo něco lepšího asi zbytečné...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Problém jste popsal zcela přesně. Oblast řízení zakázek jsme chtěli ošetřit nějakým profi systémem, měli jsme i několik nabídek. Vše se ovšem jevilo našemu vedení příliš drahé a komplikované. Proto jsem se rozhodl pro vlastní aplikaci, která mi pomůže zejména v administrativní práci. Stejnou pracovní pozici má dalších 5 lidí, ne všichni však mají o tento program zájem. Prográmek již používám a postačuje mi, ovšem stále je co zlepšovat a právě "pozastavení programu" je jedním z vylepšení.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Co se týče vašeho původního problému, tak spustit soubor asociovaný s nějakou aplikací a počkat až bude tato aplikace ukončena by šlo například takto:

Dim word = Process.Start("C:\Dokumenty\Zakázky.doc")
word.WaitForExit()
'MessageBox bude zobrazen až po ukončení aplikace
'Word s otevřeným výše uvedeným dokumentem.
MessageBox.Show("Hotovo.")

Vaše aplikace bude samozřejmě po dobu běhu Wordu zcela vytuhlá.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Chtěl jsem původně kolegovi napsat totéž, ale při pokusech s "WaitForExit" jsem zjistil, že to čeká, až se uzavře weškerý Word, tedy ne jen konkrétní (příkazem otevřený dokument), ale celý program - což vyžaduje uzavření všech případně otevřených dokumentů.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Asi bude třeba nějak zjistit ID spuštěného procesu WORD (protože každý spuštěný proces má jedinečné ID) a pak nějak zařídit kontrolu pouze tohohle procesu. A předtím taky zajistit, aby se každý doc soubor ve Windows otevíral vždy v novém Wordu (= v novém procesu). U Excelu se to dělá takhle:

1) "Tento počítač" - "Nástroje" - "Možnosti složky"

2) "Typy souborů" - nalistovat koncovku ".xls"

3) "Upřesnit" - najet na položku "Otevřít" - "Upravit"

4) "Aplikace použitá k provedení akce" - zadat cestu ke spouštěcímu souboru - např. "D:\Program Files\Microsoft Office\OFFICE10\EXCEL.EXE" "%1"

5) "Používat DDE" nechat zatržený, "Zpráva DDE" vymazat (!!!)

6) "Aplikace" = "EXCEL"; "Téma" = "System"

* tenhle postup zajistí spuštění nového xls souboru vždy v nově spuštěném procesu (čili s jedinečným ID). Předpokládám, že to bude fungovat i v případě Wordu.

Pak bych zkusil znovu výše navrhovaný postup, pokud nic, hodil bych sem na fórum obslužný kód. V Excelu vyrábím sestavy pořád, ve Wordu jsem to ještě nezkoušel. Možná ale uzrál čas něco se přiučit...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Opět nabízím jednu ze zděděných API funkci (jen si to předělej do net (to je snadný))

Volá se to přes ShellAndWait("cesta k souboru samozrejme s odkazem na otevreni souboru word")

PS: co já ještě v knihovničce nenajdu :D

Attribute VB_Name = "Cekani_na_Program"
Option Explicit

Public Type STARTUPINFO
     cb As Long
     lpReserved As String
     lpDesktop As String
     lpTitle As String
     dwX As Long
     dwY As Long
     dwXSize As Long
     dwYSize As Long
     dwXCountChars As Long
     dwYCountChars As Long
     dwFillAttribute As Long
     dwFlags As Long
     wShowWindow As Integer
     cbReserved2 As Integer
     lpReserved2 As Long
     hStdInput As Long
     hStdOutput As Long
     hStdError As Long
End Type

Public Type PROCESS_INFORMATION
     hProcess As Long
     hThread As Long
     dwProcessID As Long
     dwThreadID As Long
End Type

Public Declare Function WaitForSingleObject Lib "kernel32" ( _
    ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long _
    ) As Long

Public Declare Function CreateProcessA Lib "kernel32" ( _
    ByVal lpApplicationName As Long, _
    ByVal lpCommandLine As String, _
    ByVal lpProcessAttributes As Long, _
    ByVal lpThreadAttributes As Long, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, _
    lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION _
    ) As Long

Public Declare Function CloseHandle Lib "kernel32" ( _
    ByVal hObject As Long _
    ) As Long

Public Const NORMAL_PRIORITY_CLASS = &H20&
Public Const INFINITE = -1&

Public Sub ShellAndWait(ByVal RunProg As String)
     Dim RetVal As Long
     Dim proc As PROCESS_INFORMATION
     Dim StartInf As STARTUPINFO
     StartInf.cb = Len(StartInf)
     'Spustíme program RunProg
     RetVal = CreateProcessA(0&, RunProg, 0&, 0&, 1&, _
          NORMAL_PRIORITY_CLASS, 0&, 0&, StartInf, proc)
     'Zablokujeme náš exe dokud spuštený proces neskoncí
     RetVal = WaitForSingleObject(proc.hProcess, INFINITE)
     RetVal = CloseHandle(proc.hProcess)
End Sub

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zbytečnost, tuto funkčnost má v sobě .NET už ve výše zmiňované třídě System.Diagnostics.Process.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji všem za pomoc. Načerpal jsem zde hodně nových poznatků. Přesto jsem skončil u ryze amatérského řešení, které mi však zcela postačuje a osvědčilo se. Vím, že zbytečně zatěžuji procesor atd., ale funguje spolehlivě.

Dialog7.Show()  'Pro pokračování prg je nutno ukončit dokument word
Dim doc As String = w.ActiveDocument.Name

 Try
   Do While doc = "Dokument_word.doc"
      Me.Refresh()
      Dialog7.Select()
      Dialog7.Refresh()
      doc = w.ActiveDocument.Name
   Loop
 Catch
   Dialog7.Close()
   Me.Refresh()
 End Try

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Měl bych 2 připomínky nebo dotazy:

Jak se Vám to chová ve chvíli, kdy uživatel ve Wordu neukončí dokument "Dokument_word.doc", ale přepne se do jiného dokumentu (tzn. aktivním dokumentem se stane dokument jiný)?

Dále bych do Vašeho cyklu přidal nějaký ten "sleep", aby to tolik nebralo procesor (přece stačí testovat jednou nebo dvakrát za sekundu).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přepínání oken bylo právě jedním z problémů, které tento cyklus vyřešil. Můžu tak přerušit práci s dokumentem, prohlédnout například mejly, organizovat soubory v total comm a podobně. Když znovu aktivuji apliaci z lišty, mám zobrazené okno aplikace s dialogem ("Ukončit word pro další práci s aplikaci), aktivuji word dokončím dokument, zavřu word a můžu pokračovat s aplikací nebo jiným programem.

Řešení se "sleep" je super, díky.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přiznám se, že kód jsem nezkoušel, ale jsem přesvědčen, že pokud uživatel Váš dokument neuzavře (neukončí) a místo toho si "přes něj" otevře jiný dokument, pak to Váš program nepozná a rozjede se. Nebo to máte nějak ošetřeno?

Omluva - přehlédl jsem, že jste na tento problém již narazil.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Promiňte, špatně jsem pochopil dotaz. Odzkoušel jsem to a je tu drobná chyba. Pokud je spuštěný jiný doc před aktivací "Doument_word.doc" je vše OK. Problém je, když při běžícím "Dokument_word.doc" otevřu další doc. To program "odbrzdí" a pokračuje.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Odzkoušel jsem několik variant a konečně jsem našel asi optimální řešení:

Dim w As New Microsoft.Office.Interop.Word.Application()
w.Documents.Open(IO.Path.Combine(Application.StartupPath, "Dokument.doc")).Activate()
w.Visible = True

Dim docname As String = w.Application.ActiveDocument.Name  

Try
Do While w.Application.Documents(docname).Name = docname
                    Me.Refresh()
                    Dialogopozastavení.Select()
                    Dialogopozastavení.Refresh()
                    Threading.Thread.Sleep(500)
                Loop
            Catch
                Dialogopozastavení.Close()
                ' Pokračování aplikace
            End Try

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback