[ dreadknight @ 12.11.2010. 22:09 ] @
Ono što pokušavam da uradim je da preko COM (Component Objject Model) pristupim aplikaciji koju nisam otvorio preko COM-a. Recimo, konkretno želim da zatvorim word proces. Znam preko COM-a lepo da otvorim proces word-a i da mu šaljem komande da piše, ubacuje slike, prepoznaje tekst itd. E sad bi mi trebalo takođe da uhvatim kontrolu word-u čiji proces nisam kreirao. Da li je to moguće uraditi, tj da li je moguće dohvatiti IDispatch tog procesa. Da li je možda moguće zatvoriti proces worda na neki drugi način? I kako se to radi?
Hvala unapred na odgovoru.
[ kiklop74 @ 15.11.2010. 20:42 ] @
Dobijanje IDispatch interfejsa nije moguce u svim slucajevima. Treba da imas na umu da kada se instancira word za manipulisanje preko COM metoda pokrece se nova instanca sa <word.exe> /automation.

Ono sto mozes je da izlistas sve procese koji se trenutno izvrsavaju i da na osnovu nekog parametra odredis koji bi hteo da zatvoris.

Na primer:

Single interface for enumerating processes and modules under NT and Win9x/2K
http://www.codeguru.com/Cpp/W-...essesmodules/article.php/c5729

Pa onda koriscenjem API funkcije TerminateProcess ubijes na silu zeljeni proces
http://msdn.microsoft.com/en-us/library/ms686714(v=VS.85).aspx

ili nadjes glavni prozor tog procesa sa EnumerateWindows API funkcijom i posaljes mu WM_CLOSE poruku sa SendNotifyMessage
http://msdn.microsoft.com/en-us/library/ms644953%28VS.85%29.aspx
[ ljube @ 27.11.2010. 14:42 ] @
Može li da pomogne pozivanje procesa TASKKILL?

Probaj TASKKILL /? ima primjer kako se ubija notepad.
[ kiklop74 @ 06.12.2010. 03:40 ] @
Zasto mu dajes lose savete?

Je'l se ovde bavimo c++om ili programiranjem skripti?

Nema nista gore nego pisati programe koji pozivaju externe CLI aplikacije samo zato sto je to "lakse i brze" (a ne i najbolje). Ako je vec cilj lakse i brze onda uzmi lepo notepad i pishi batch script.

[ mmix @ 06.12.2010. 09:49 ] @
Ne vidim zasto je los savet? Covek je lepo pitao "Da li je možda moguće zatvoriti proces worda na neki drugi način? I kako se to radi?".

Ja ne bi tako uradio ali to ne znaci da ne moze a i prosto je za iskodirati

[ kiklop74 @ 06.12.2010. 14:14 ] @
Savet je los zato sto stvara naviku da se sve "krpi" gomilom pokupljenih delova koda koji posle cine nekog frankenstajna. Naravno da sve moze. Ali valjda je cilj i neka konzistencija i kvalitet a ne samo - "daj da ga resim za 45 sekundi".
[ ljube @ 07.12.2010. 16:02 ] @
Naziv topika "Dobijanje IDispatch iz procesa ili aplikacije" zaista nema mnogo veze sa onim što je autor na kraju pojasnio da želi da ubije word.

Savjeti možda jesu loši jer podrazumjevaju nasilno gašenje worda ali vjerovatno bi to trebala biti zadnja solucija ako ostalo zakaže.

Ono što bi bio konstruktivan savjet je konkretan primjer dobijanja IDispatch-a od worda koji nisi kreirao - pa da vidimo koliko je to errorprone naspram ostalih rješenja.

[ kiklop74 @ 07.12.2010. 16:23 ] @
Citat:
ljube:
Ono što bi bio konstruktivan savjet je konkretan primjer dobijanja IDispatch-a od worda koji nisi kreirao - pa da vidimo koliko je to errorprone naspram ostalih rješenja.


OK kad je vec tako evo sta kaze Microsoft

How To Attach to a Running Instance of an Office Application

[ ljube @ 07.12.2010. 18:46 ] @
Dobro, ovo je već nešto konkretno.
Nisam znao za GetActiveObject. Hvala na linku.

[ kiklop74 @ 07.12.2010. 19:20 ] @
A evo i programa koji zatvara word (moze da se kompaljira samo sa msvc)

Code:

// killword.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <comdef.h>
#include <iostream>

#ifdef UNICODE
#define tclog std::wclog
#else
#define tclog std::clog
#endif

#pragma comment(lib,"comsuppwd.lib")

struct ole {
    ole(void): shouldRelease(false) {
        HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
        shouldRelease = ((hr == S_OK) || (hr == S_FALSE));
    }
    ~ole(void) {
        docleanup();
    }
private:
    volatile bool shouldRelease;
    void docleanup(void) {
        if (shouldRelease) {
            shouldRelease = false;
            ::CoUninitialize();
        }
    }
};

/*_com_dispatch_help

L"\x0009" - IDispatch*
L"\x0008" - BSTR
L"\x000b" - boolean
L"\x000c" - enum
L"\x400c" - VARIANT*
*/

HRESULT CloseWord(void) {
    ole ol;
    HRESULT result = S_OK;

    try {

        IUnknownPtr ppunk;
        IDispatchPtr ppdisp;

        result = ppunk.GetActiveObject("Word.Application");
        _com_util::CheckError(result);
        {
        IDispatch *pdisp = NULL;
        result = ppunk.QueryInterface(IID_IDispatch,pdisp);
        _com_util::CheckError(result);
        ppdisp.Attach(pdisp);
        ppunk.Release();
        }

        LPOLESTR name=L"Quit"; 
        DISPID dispid = NULL;
        result = ppdisp->GetIDsOfNames (
                                 IID_NULL,
                                 &name,
                                 1,
                                 LOCALE_USER_DEFAULT,
                                 &dispid);
        _com_util::CheckError(result);

        variant_t save(false);
        variant_t empty;
        result = _com_dispatch_method( ppdisp
                                      ,dispid
                                      ,DISPATCH_METHOD
                                      ,VT_EMPTY
                                      ,NULL
                                      ,L"\x400c\x400c\x400c"
                                      ,&save
                                      ,&empty
                                      ,&empty
                                      );
    } catch(const _com_error& e) {
        tclog << e.ErrorMessage() << std::endl;
    }
    
    return result;
}


int __cdecl _tmain(int /*argc*/, _TCHAR** /*argv[]*/) {

    if ( SUCCEEDED(CloseWord()) ) {
        tclog << TEXT("Closed Word instance.") << std::endl;
    }
    return 0;
}



[Ovu poruku je menjao kiklop74 dana 07.12.2010. u 20:45 GMT+1]
[ ljube @ 07.12.2010. 20:18 ] @
Wow, eto ga kompletno rješenje. Ovaj dio sa "struct ole" je baš neobičan pristup. Ovo se ponaša kao klasa?
Svaka čast na primjeru.
[ kiklop74 @ 07.12.2010. 20:38 ] @
Nije neobicno ponasanje. To je klasicna primena RAII idioma.

http://en.wikipedia.org/wiki/RAII

Time se garantuje da ce COM biti adekvatno zatvoren cak i u slucaju izuzetka. Takodje smanjuje kolicinu koda.

Inace struct i class su sinonimi. Jedina razlika je da su kod deklaratora class svi elementi po defaultu private dok su kod struct svi elementi public iliti:

Code:


class{
public:

};

//je ekvivalentno:

struct {
};