IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Visual C++ Discussion :

Lancement d'un composante dans un service (VS2010, C++)


Sujet :

Visual C++

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2011
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 6
    Points : 13
    Points
    13
    Par défaut Lancement d'un composante dans un service (VS2010, C++)
    Bonjour,
    je travaille avec VS2010 en C++
    je tente de convertir un logiciel qui fonctionne avec des composantes en un programme de service. (background)
    Conformément à l'exemple de code, le service CMyService démarre correctement si je mets le 1er return avant le CoCreateInstance(..) et ne démarre pas (TimeOut) avec le 2eme return après le CoCreateInstance().
    Il y a donc un problème avec le CoCreateInstance().
    Lequel?
    Merci pour tous les conseils et réponses.
    Bernard

    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    bool CMyService::OnInit(void)
    {
    	return CreateListObject();
    }
     
    bool CMyService::CreateListObject()
    {
    //    return false;
     
    	HRESULT hr = ::CoCreateInstance(CLSID_CListObject,
                                        NULL,
                                        CLSCTX_INPROC_SERVER,
                                        IID_IUnknown,
                                        (LPVOID*)&m_pListObjet);
        return true;
     
     
        if (FAILED(hr)) {
    	    // appliances n'est plus a jour : rebuild all // pbm de appliances.reg (x86-d, x86-r)
             TRACE("Failed to create object. SCODE: %8.8lXH (%lu)\n",
                 GetScode(hr),   GetScode(hr) & 0x0000FFFF);
            m_pListObjet = NULL;
            return false;
        }
        ASSERT(m_pListObjet);
        ...
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    Dans quel type de thread essayez-vous de faire CoCreateInstance ?
    Quel est le type d'appartment du composant que vous voulez instancier ?
    Avez-vous déjà appelé CoInitialize dans ce thread ? Si oui, avec des options compatibles avec l'appartment du composant ?

  3. #3
    Membre à l'essai
    Inscrit en
    Février 2011
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 6
    Points : 13
    Points
    13
    Par défaut re
    Dans quel type de thread essayez-vous de faire CoCreateInstance ?
    1 seul service et 1 seul thread. non?
    Quel est le type d'appartment du composant que vous voulez instancier ?
    CLSCTX_INPROC_SERVER pas aggrege (ca marche ds le pgm source)
    Avez-vous déjà appelé CoInitialize dans ce thread ? Si oui, avec des options compatibles avec l'appartment du composant ?[/QUOTE]

    il n'y a pas de template de projet service ds VS2010. J'utilise une base a partir de http://www.codeproject.com/Articles/...d-Line-Service
    le CoCreateInstance marche (return S_OK) mais m_pListObjet reste NULL.
    pas de debug!! Connaissez vous une possibilite effective de debugger un service? j'ai fait un historique de ce qui est fait:

    j'obtiens:
    avant CoCreateInstance m_pListObjet = 0
    CoCreateInstance return S_OK
    FAILED(hr) m_pListObjet = 0

    Merci encore. J'espere ne pas abuser
    Bernard

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    // MIDL_DEFINE_GUID(CLSID, CLSID_CListObject,0x2AB23F66,0xE1C9,0x4316,0xA2,0x10,0xD4,0xC6,0xA1,0x06,0xE5,0x9A);
     
     
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
         // Initialize OLE libraries  ou      CoInitialize(NULL);
    	if (!AfxOleInit())
    	{
    	     sprintf(chBuf, "erreur OLE init "); m_Key = m_Journal.WriteJournal(chBuf); // JOURNAL
    		_tprintf(_T("Fatal Error: OLE  initialization failed\n"));
      	       return 0;
    	}
     
           AfxEnableControlContainer();  // */
          CoInitialize(NULL);
    	..
    }
     
    bool CMyService::OnInit(void)
    {
    	     return CreateListObject();
    }
     
    bool CMyService::CreateListObject()
    {
    //    return false;
         m_pListObjet = NULL;
    	sprintf(chBuf, "avant  CoCreateInstance,  m_pListObjet = %x ", m_pListObjet); m_Key = m_Journal.WriteJournal(chBuf); // JOURNAL
     
    	HRESULT hr = ::CoCreateInstance(CLSID_CListObject,
                                        NULL,
                                        CLSCTX_INPROC_SERVER,
                                        IID_IUnknown,
                                        (LPVOID*)&m_pListObjet);
       // return false;
     
       if (FAILED(hr)) { 
    	   DWORD err = GetLastError(); 
    	    switch (err) {
    	    case S_OK :
    		    sprintf(chBuf, "CoCreateInstance  return S_OK");  m_Journal.WriteJournal(chBuf); // JOURNAL
    			break;
    	    case  REGDB_E_CLASSNOTREG:
    		    sprintf(chBuf, "REGDB_E_CLASSNOTREG"); m_Journal.WriteJournal(chBuf); // JOURNAL
    		    break;
    	    case  CLASS_E_NOAGGREGATION:
    		    sprintf(chBuf, "CLASS_E_NOAGGREGATION"); m_Journal.WriteJournal(chBuf); // JOURNAL
    		    break;
    	    case    CO_E_CLASSSTRING:
    		    sprintf(chBuf, "CO_E_CLASSSTRING"); m_Journal.WriteJournal(chBuf); // JOURNAL
    		    break;
    	    case E_NOINTERFACE :
    		    sprintf(chBuf, "E_NOINTERFACE"); m_Journal.WriteJournal(chBuf); // JOURNAL
    			break;
    		default: break; 
    		}
     
    	    sprintf(chBuf, "FAILED(hr)  m_pListObjet = %x ", m_pListObjet); m_Journal.WriteJournal(chBuf, m_Key); // JOURNAL
     
        }
        ASSERT(m_pListObjet);
        ...
    }

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    Il y a beaucoup de chose qui me font tiquer dans ce truc.
    Vous semblez un peu jeune sur la plateforme Windows.
    Utilisez des technologies d'il y a 20 an quand on ne connait pas la plateforme, c'est toujours casse-gueule.

    1 seul service et 1 seul thread. non?
    Non, un service est un programme comme un autre, il est juste dans un contexte de sécurité particulier et le manager des services fait le gendarme.
    On peut donc avoir autant de thread et de type d'appartment COM qu'avec les autres types de programmes.

    CLSCTX_INPROC_SERVER pas aggrege (ca marche ds le pgm source)
    Non, cela donne le type de composant que vous voulez instancier et le mode d'accès, pas le type d'appartment COM compatible avec ce composant.

    le CoCreateInstance marche (return S_OK) mais m_pListObjet reste NULL.
    et ne démarre pas (TimeOut) avec le 2eme return après le CoCreateInstance
    Faut savoir, c'est un Timeout sur l'appel de CoCreateInstance ou le fait que m_pListObjet reste NULL ???

    pas de debug!! Connaissez vous une possibilite effective de debugger un service?
    Comme dans l'article que vous donnez en référence, Debug View fonctionne de paire avec OutputDebugString (http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx).
    Mais la méthode la plus simple est de débugger en mode "programme normal" car la majorité des problèmes n'ont rien à voir avec le fait qu'il soit lancé par le service manager.

    Votre code est truffé de primitive "Afx...", Afx est le nom de code des MFC. Si vous n'utilisez pas les MFC, vous ne devriez avec aucune de ces primitives dans votre code.

    Quel est le type de "m_pListObjet" ?
    Utilisez des CComPtr pour simplifier et sécuriser votre code (http://msdn.microsoft.com/en-us/library/hh279683.aspx)

    Je suis un éternel pessimiste, j'utiliserai plutôt SUCCEDED que FAILED (http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx)

  5. #5
    Membre à l'essai
    Inscrit en
    Février 2011
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 6
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Il y a beaucoup de chose qui me font tiquer dans ce truc.
    Vous semblez un peu jeune sur la plateforme Windows.
    Utilisez des technologies d'il y a 20 an quand on ne connait pas la plateforme, c'est toujours casse-gueule.
    J'ai un pgm source et des manuels datant de 15 ans. Je suis seul.
    Vous pouvez evidemment interrompre la discussion, en me le signalant svp, si je vous enerve trop.


    je ne comprends pas la notion de "type d'appartment COM"!!


    Citation Envoyé par bacelar Voir le message
    Faut savoir, c'est un Timeout sur l'appel de CoCreateInstance ou le fait que m_pListObjet reste NULL ???
    je voudrais obtenir pListObject lors du start de CMyService:
    j'ai TimeOut si CoInitialize() est ds le start de CMyService.
    pListObject (du start de CMyService) reste NULL si le CoInitialize() est ds le main du pgm service

    Maintenant j'ai mis le CoCreateInstance, apres le coInitialized() ds le main et j'obtiens qqchose ds pListObject.
    Le compilateur se plaint a cause du
    - IID_PPV_ARGS ( error C2787: 'INotify' : no GUID has been associated with this object) au QueryInterface() car effectivement je ne l ai pas ds le .idl donc pas ds le .c cree lors de la creation de la dll des composantes.
    ou a cause de
    LPVOID* (error C2786: 'void' : invalid operand for __uuidof)

    Citation Envoyé par bacelar Voir le message
    Votre code est truffé de primitive "Afx...", Afx est le nom de code des MFC. Si vous n'utilisez pas les MFC, vous ne devriez avec aucune de ces primitives dans votre code.
    J'utilise MFC pour CString p.e. ou pour l'architecture Document-View... d'autre part. mon pgm de base CLS.exe l'utilise.

    Citation Envoyé par bacelar Voir le message
    Quel est le type de "m_pListObjet" ?
    m_pListobject etait un *IUnknown

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
     
    /***************************************************************
    INotify.h
    Interface purement abstraite qui permet la notification bidirectionnelle entre les appliances entre-elles et avec l'application
    ****************************************************************/
     
    // {ACEA4745-E3D4-494E-8A98-288CD8EB482D}
    static const GUID IID_INotify  = 
    { 0xacea4745, 0xe3d4, 0x494e, { 0x8a, 0x98, 0x28, 0x8c, 0xd8, 0xeb, 0x48, 0x2d } };
     
     
    class INotify : public IUnknown
    {
    public:
        // Standard IUnknown interface functions
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
                                                         LPVOID* ppvObj) = 0;
        virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
        virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
     
        // This interface
        virtual HRESULT STDMETHODCALLTYPE SetClient(LPVOID pClientNotif,LPVOID pClientInvest, LPVOID name) = 0;
        virtual HRESULT STDMETHODCALLTYPE Notify(CInfo pinfo) = 0;
    };
     
     
     
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    	int nRetCode = 0;
     
    	CoInitialize(NULL);
     
    	 CComPtr<IListObject>  pListObject;
    	 HRESULT hr = pListObject.CoCreateInstance(CLSID_CListObject);
     
     
    	 ASSERT(pListObject);
     
     
    	// get a pointer to the m_pListObject's INotify interface(inotify.h) 
         CComPtr<INotify> m_pINotify;
         hr = pListObject->QueryInterface(IID_PPV_ARGS(&m_pINotify) );
         //hr = pListObject->QueryInterface((LPVOID*) &m_pINotify );
     
    	// get a pointer to the m_pListObjet's IInvestigation interface(iinvestigation.h) 
         CComPtr<IInvestigation> m_pInvest;
        if (pListObject->QueryInterface(IID_Investigation, (LPVOID*)&m_pInvest) != S_OK) {
            TRACE("IInvestigation not supported");
            return FALSE;
        }
     
        m_pINotify->SetClient(m_pINotify, m_pInvest, NULL);
     
     
    	// initialize MFC and print and error on failure
    	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    	{
    		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
    		nRetCode = 1;
    	}
    	else
    	{
    		// Parse for standard arguments (install, uninstall, usage)
    		CMyService MyService;
    		if (!MyService.ParseStandardArgs(argc, argv))
    			MyService.StartService();
     
    		// When we get here, the service has been stopped
    		return MyService.m_Status.dwWin32ExitCode;
    	}
     
    	return nRetCode;
    }
    A suivre, Merci
    Bernard

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour permettre au __uuidof() de marcher sur ton interface, utilise la macro DECLSPEC_UUID, qui wrappe ceci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class DECLSPEC_UUID("ACEA4745-E3D4-494E-8A98-288CD8EB482D") INotify : public IUnknown
    {
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    je ne comprends pas la notion de "type d'appartment COM"!!
    Si vous ne voyez pas ce qu'est un COM appartment, le comportement de COM vous apparaîtra toujours très étrange.

    http://msdn.microsoft.com/en-us/library/ms809971.aspx

    Vous devez avoir le reflexe de tout reprendre dans un projet "jouet", pas de thrading complexe, pas de MFC ...

    Il faut bien comprendre qu'il faut appeler CoInitialize dans chaque thread, et toujours avant le moindre autre appel COM dans ce thread.

    CoInitialize permet de dire à COM, si le thread est STA ou MTA et donc dans quel appartment COM se site ce thread. Cela à un impacte sur la possibilité ou non d'instancier tel ou tel type de composant.

    Maintenant j'ai mis le CoCreateInstance, apres le coInitialized() ds le main et j'obtiens qqchose ds pListObject.
    C'est la séquence d'appels obligatoire, et pour chaque thread.

    J'utilise MFC pour CString p.e. ou pour l'architecture Document-View
    Les strings sont dans la STL depuis plus de 15 ans.
    "l'architecture Document-View", heu, je vous signale qu'un service n'a pas à avoir d'IHM, donc les MFC sont inutiles mais surtout dangereuses car elles contiennent de nombreux hacks qui sont potentiellement invalide dans le contexte des services.
    Si vous connaissez bien les MFC, il est possible d'éviter ces écueils, mais ce n'est pas une sinécure.

    Après la lecture du lien sur les COM appartement, êtes-vous toujours bloqué ?

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En effet, je ne vois pas l'intérêt d'un code document/view dans un service. Pour les strings, utiliser selon les besoins des std::string, std::wstring ou _bstr_t.

    Et vérifier que le ThreadingModel de l'objet est réglé (normalement sur "Apartment"), sinon c'est l'horreur.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Lancement d'un VBS dans un Batch = Service KO ?
    Par ghohm dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 26/02/2009, 07h16
  2. lancement sqlloader dans un service Windows
    Par DrZoune dans le forum C#
    Réponses: 7
    Dernier message: 05/02/2008, 10h19
  3. Réponses: 2
    Dernier message: 02/08/2004, 17h34
  4. Réponses: 8
    Dernier message: 17/03/2004, 14h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo