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

C++ Discussion :

probleme avec HRESULT


Sujet :

C++

  1. #1
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut probleme avec HRESULT
    Bonjour,

    J'utilise ce petit bout de code ci-dessous:
    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
     
    HRESULT reponse;
      reponse=CoGetClassObject(CLSID_TTestServeurCOM, CLSCTX_REMOTE_SERVER, NULL, IID_ITestServeurCOM, &distributedObject);
     
      switch(reponse){
                      case S_OK:
                           std::cout << "Location and connection to the specified class object was successful." << std::endl;
                           break;  
                      case REGDB_E_CLASSNOTREG:
                           std::cout << "CLSID is not properly registered. Can also indicate that the value you specified in dwClsContext is not in the registry." << std::endl;
                           break;
                      case E_NOINTERFACE:
                           std::cout << "Either the object pointed to by ppv does not support the interface identified by riid, or the QueryInterface operation on the class object returned E_NOINTERFACE." << std::endl;
                           break;
                      case REGDB_E_READREGDB:
                           std::cout << "Error reading the registration database." << std::endl;
                           break;
                      case CO_E_DLLNOTFOUND:
                           std::cout << "In-process DLL or handler DLL not found (depends on context)." << std::endl;
                           break;
                      case CO_E_APPNOTFOUND:
                           std::cout << "EXE not found (CLSCTX_LOCAL_SERVER only)." << std::endl;
                           break;
                      case E_ACCESSDENIED:
                           std::cout << "General access failure (returned from LoadLib/CreateProcess)." << std::endl;
                           break;
                      case CO_E_ERRORINDLL:
                           std::cout << "EXE has error in image." << std::endl;
                           break; 
                      case CO_E_APPDIDNTREG:
                           std::cout << "EXE was launched, but it didn't register class object (may or may not have shut down)." << std::endl;
                           break;
                      default:
                           std::cout << "Reponse inconnue???: " << reponse << std::endl;
                           break;
      }
    La fonction CoGetClassObject vient d'une librairie Microsoft. D'apres la doc en ligne, elle renvoi des codes d'erreurs HRESULT. Tous ce qu'elle peut renvoyée est dans le switch.

    Probleme: je passe toujours dans le default.

    Quelqu'un a-t-il une idée?

  2. #2
    Membre chevronné Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par défaut
    Donne le code de ton erreur, dans visual studio tu as un outil pour faire la correspondance entre le erreur COM et sa definition.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Et si tu donnes le code d'erreur, donne-le en hexadécimal.

    PS: Je te déconseille de tester directement S_OK dans le switch, sauf pour des fonctions où la distinction entre S_OK et S_FALSE est bien documentée.
    Tu devrais tester S_OK dans le default avec la macro SUCCEEDED().
    ...Ou bien, ne passer dans le switch que si la fonction a échoué (la macro SUCCEEDED() retourne vrai ou la macro FAILED() retourne faux)...
    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.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    En fait, je parie que ton erreur est CO_E_NOTINITIALIZED (0x800401F0) et que tu as oublié d'appeler CoInitialize() avant CoGetClassObject().
    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.

  5. #5
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    En fait, je parie que ton erreur est CO_E_NOTINITIALIZED (0x800401F0) et que tu as oublié d'appeler CoInitialize() avant CoGetClassObject().
    Medinoc tu as bien deviné.

  6. #6
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Bon, tant que je suis la, je continue.

    Maintenant, j'appelle la fonction CoInitialize() qui me retourne S_OK.

    Par contre, au niveau du CoGetClassObject(), j'ai en retour:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    REGDB_E_CLASSNOTREG: "CLSID is not properly registered. Can also indicate that the value you specified in dwClsContext is not in the registry."
    Pour résumé, coté serveur, j'ai une dll que j'enregistre avec ce petit .exe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        TCOMITestServeurCOMT<TTestServeurCOM> serveur = CoTTestServeurCOM::Create();
        IUnknown * serveurPtr = serveur;
        LPDWORD objectNumber;
        int reponse=CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER, REGCLS_MULTI_SEPARATE, objectNumber);
     
        if(reponse==S_OK)
                        std::cout << "Serveur enregistre: " << objectNumber << std::endl;
        else
                        std::cout << "Serveur NON enregistre." << std::endl;
    Quand j'execute cela, ca donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Serveur enregistre: 409028
    Et pourtant, il ne le voit pas.
    Remarque: les 2 objets sont pour l'instant sur la même machine.

    Une idée de pourquoi il ne le voit pas comme enregistré?

    P.S. : désolé, j'ai pas encore modifié le code pour utiliser succeeded().

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    (Rappel: CoRegisterClassObject, c'est pour un Out-of-Process server, et la classe n'est enregistrée que tant que le serveur tourne)

    Avec CLSCTX_REMOTE_SERVER, il ne cherchera pas en local.
    Conseil: utilise CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER dans ton serveur, et CLSCTX_ALL dans ton client...
    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.

  8. #8
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    J'ai fait ça, mais ça n'a rien changé.
    J'ai aussi essayé de faire tourner le client sur un autre PC. La aussi j'ai l'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EGDB_E_CLASSNOTREG: "CLSID is not properly registered. Can also indicate that the value you specified in dwClsContext is not in the registry."
    D'autre part,
    la classe n'est enregistrée que tant que le serveur tourne
    Ça veut dire que le .exe qui tourne coté serveur doit rester actif quand le client fait l'appel?

  9. #9
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Dans le .exe qui enregistre l'objet cote serveur, j'ai essayé ça:
    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
     
        TCOMITestServeurCOMT<TTestServeurCOM> serveur = CoTTestServeurCOM::Create();
        IUnknown * serveurPtr = serveur;
        LPDWORD objectNumber;
        //int reponse;
     
        if(SUCCEEDED(CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, objectNumber)))
                        std::cout << "Serveur enregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON enregistre."  << std::endl;
     
        std::cout << std::endl;
     
        system("PAUSE");
     
        if(SUCCEEDED(CoRevokeClassObject(*objectNumber)))
                        std::cout << "Serveur desenregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON desenregistre."  << std::endl;
     
        system("PAUSE");
    Je supprime donc l'objet que je viens juste d'enregistrer.
    Seulement voila, il échoue.
    Je pense que malgré la réponse S_OK de CoRegisterClassObject(), le serveur est mal enregistré.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    #8 : Oui. C'est le principe d'un serveur out-of-process qui n'a pas d'enregistrement permanent.
    #9 : objectNumber ne pointe sur rien du tout. Un miracle que ça n'ait (hélas) pas planté...
    Comme indiqué dans ce blog, tu as appelé la fonction sans même chercher à savoir à quoi servait ce paramètre. Naturellement, beaucoup de gens font cette erreur en débutant, mais ça reste une très mauvaise pratique.
    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.

  11. #11
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Effectivement, j'ai fait une erreur de débutant. J'avais pas fait gaffe que c'était un pointeur au début. Et pourtant je l'utilise bien comme un pointeur après.

    Sinon, cette fois j'arrive bien à enregistrer et désenregistrer le serveur (enfin en tout cas j'ai S_OK à chaque fois).

    Par contre, coté client, le programme bloque pendant l'exécution de CoGetClassObject.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Ah, en effet, ton serveur doit faire autre chose que system("pause"): Il faut qu'il fasse une boucle de messages (qui sera sûrement infinie ici puisque ce n'est pas si simple de quitter tant que tu n'as pas une seconde fenêtre).
    Ou bien, juste afficher une MessageBox(), qui contient une boucle de messages tant qu'elle est affichée.

    Par exemple, remplace ton system("pause") (celui entre le register et le revoke) par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox(NULL, TEXT("Cliquer OK pour quitter"), TEXT("Serveur COM"), MB_OK);
    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.

  13. #13
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    J'ai remarqué que si je mettais CLSCTX_ALL dans CoGetClassObject, le client ne trouve pas le serveur.
    Par contre, si je met CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER (ce qu'il y a cote serveur), le client le trouve.
    Je trouve ça bizarre, parce que apparemment, CLSCTX_ALL veut dire qu'il doit chercher partout. Non?

    De plus, quand j'exécute en mode release, au moment où j'appelle la fonction de mon interface, j'ai un EAccessViolation.
    Du coup, j'ai mis un try{appel fct} catch(...){afficher msg erreur}, mais il ne passe pas dans le catch et me donne une erreur de violation d'accès.
    En mode debug, je n'ai pas d'exception, mais je n'ai pas non plus de réponse. Ça sort du programme tout seul sans rien dire.

    Exe serveur:
    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
     
        TCOMITestServeurCOMT<TTestServeurCOM> serveur = CoTTestServeurCOM::Create();
        IUnknown * serveurPtr = serveur;
        LPDWORD objectNumber = new DWORD;
        //int reponse;
     
        if(SUCCEEDED(CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, objectNumber)))
                        std::cout << "Serveur enregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON enregistre."  << std::endl;
     
        BSTR nbProc;
        serveur.get_Nombre(&nbProc);
        std::wcout << std::endl << "Nb processeurs: " << nbProc << " et voila." << std::endl << std::endl;
     
        MessageBox(NULL, TEXT("Cliquer OK pour quitter"), TEXT("Serveur COM"), MB_OK);
     
        if(SUCCEEDED(CoRevokeClassObject(*objectNumber)))
                        std::cout << "Serveur desenregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON desenregistre."  << std::endl;
     
        system("PAUSE");
    Exe client:
    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
     
      HRESULT reponse; 
      TCOMITestServeurCOMT<TTestServeurCOM> serveur; 
      void * distributedObject = ((void*)serveur);
     
      //Sur le reseau
      std::cout<< "Initialize: " << std::endl;
      if(!SUCCEEDED(reponse=CoInitialize(NULL)))  
          switch(reponse){
                          case S_OK:
                               std::cout << "The COM library was initialized successfully on this thread." << std::endl;
                               break;  
                          case S_FALSE:
                               std::cout << "The COM library is already initialized on this thread.." << std::endl;
                               break;
                          case RPC_E_CHANGED_MODE:
                               std::cout << "A previous call to CoInitializeEx specified the concurrency model for this thread as multithread apartment (MTA). If running Windows 2000, this could also mean that a change from neutral-threaded apartment to single-threaded apartment occurred." << std::endl;
                               break;
                          default:
                               std::cout << "Reponse inconnue???: " << reponse << std::endl;
                               break;
          }
      else
          std::cout << "The COM library was initialized successfully on this thread." << std::endl;
     
      std::cout<< std::endl << "Get Object: " << std::endl;
      reponse=CoGetClassObject(CLSID_TTestServeurCOM, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, NULL, IID_ITestServeurCOM, &distributedObject);
      if(!SUCCEEDED(reponse))
          switch(reponse){ 
                          case REGDB_E_CLASSNOTREG:
                               std::cout << "CLSID is not properly registered. Can also indicate that the value you specified in dwClsContext is not in the registry." << std::endl;
                               break;
                          case E_NOINTERFACE:
                               std::cout << "Either the object pointed to by ppv does not support the interface identified by riid, or the QueryInterface operation on the class object returned E_NOINTERFACE." << std::endl;
                               break;
                          case REGDB_E_READREGDB:
                               std::cout << "Error reading the registration database." << std::endl;
                               break;
                          case CO_E_DLLNOTFOUND:
                               std::cout << "In-process DLL or handler DLL not found (depends on context)." << std::endl;
                               break;
                          case CO_E_APPNOTFOUND:
                               std::cout << "EXE not found (CLSCTX_LOCAL_SERVER only)." << std::endl;
                               break;
                          case E_ACCESSDENIED:
                               std::cout << "General access failure (returned from LoadLib/CreateProcess)." << std::endl;
                               break;
                          case CO_E_ERRORINDLL:
                               std::cout << "EXE has error in image." << std::endl;
                               break; 
                          case CO_E_APPDIDNTREG:
                               std::cout << "EXE was launched, but it didn't register class object (may or may not have shut down)." << std::endl;
                               break;
                          case CO_E_NOTINITIALIZED:
                               std::cout << "CO_E_NOTINITIALIZED." << std::endl;
                               break;
                          default:
                               std::cout << "Reponse inconnue???: " << reponse << std::endl;
                               break;
          } 
      else
           std::cout << "Location and connection to the specified class object was successful." << std::endl;
     
      if(reponse == S_OK){
                 try{ 
                      std::wcout << std::endl << "Nombre de processeurs: " << serveur.Nombre << " et voila." << std::endl; //C'est ici que ca plante
                 }
                 catch(...){
                      std::cout << std::endl << "Violation d'accès." << std::endl; 
                 }
      }
     
      system("PAUSE");

  14. #14
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Ne devrais-je pas plutôt utiliser CoCreateInstanceEx() plutôt que CoCreateObjectClass() (qui est appelé par CoCreateInstanceEx).

    Si oui, je n'ai pas compris qu'est-ce qu'il faut mettre dans le paramètre COSERVERINFO * pServerInfo.

    Pour l'instant j'ai essayé avec NULL, mais ça ne marche pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    E_NOINTERFACE: "Either the object pointed to by ppv does not support the interface identified by riid, or the QueryInterface operation on the class object returned E_NOINTERFACE."

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    CoGetClassObject ne retourne pas directement un nouvel objet, mais un objet implémentant l'interface IClassFactory.

    Je pense que ça ira mieux si tu utilises simplement CoCreateInstanceEx(), voire CoCreateInstance() tout court pour tester en local...
    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.

  16. #16
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Quand j'essaie d'appeler CoCreateInstance, j'ai l'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    E_NO_INTERFACE: "The specified class does not implement the requested interface, or the controlling IUnknown does not expose the requested interface."
    Dans la doc, ils donnent les fonctions qui sont appelées par CoCreateInstance. Du coup, j'ai codé avec celles-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    HRESULT reponse; 
    TCOMITestServeurCOMT<TTestServeurCOM> serveur; 
    void * distributedObject = ((void*)serveur);
     
    CoInitialize(NULL)
     
    reponse=CoGetClassObject(CLSID_TTestServeurCOM, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, NULL, IID_ITestServeurCOM, &distributedObject);
     
    void * ppvObj;        // A modifier  
    reponse = serveur->CreateInstance(NULL, IID_ITestServeurCOM, ppvObj);
     
    serveur->Release();
    Mais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    [BCC32 Erreur] testClient.cpp(98): E2316 'CreateInstance' n est pas un membre de 'ITestServeurCOM'
    Dois-je coder cette méthode moi-même (je suppose et espère que non)?
    Si oui, que doit-elle faire?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    CoGetClassObject ne retourne pas directement un nouvel objet, mais un objet implémentant l'interface IClassFactory.
    Donc, soit tu utilises CoCreateInstanceEx() à la plce de CoGetClassObject, soit tu utilises CoGetClassObject comme il faut:
    Code C++ : 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
    HRESULT reponse; 
    TCOMITestServeurCOMT<TTestServeurCOM> serveur; 
     
    CoInitialize(NULL);
     
    //Création de la ClassFactory
    IClassFactory * pFactory = NULL;
    reponse=CoGetClassObject(CLSID_TTestServeurCOM, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, reinterpret_cast<void**>(&pFactory));
     
    if(FAILED(reponse))
    {
    	//Traiter l'erreur et ne pas exécuter la suite
    }
     
    //Création de l'objet
    void * pvObj = NULL;
    reponse = pFactory->CreateInstance(NULL, IID_ITestServeurCOM, &pvObj);
    pFactory->Release(), pFactory=NULL;
     
    if(FAILED(reponse))
    {
    	//Traiter l'erreur et ne pas exécuter la suite
    }
     
    //Je ne sais pas comment on assigne un pointeur de référence à un pointeur intelligent Borland.
    //Mais ce doit être un truc de ce genre
    serveur = pvObj;
    //ou
    serveur.Attach(pvObj);
    //ou
    serveur = static_cast< ITestServeurCOM * >(pvObj);
    //ou
    serveur.Attach(static_cast< ITestServeurCOM * >(pvObj));
    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.

  18. #18
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Et si tu donnes le code d'erreur, donne-le en hexadécimal.
    Je vais encore passer pour un con, mais comment je fais pour me l'afficher en hexa?

    En fait c'est bon j'ai trouvé (mais j'ai galeré), il suffit de faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::cout << std::hex << codeErreur;

  19. #19
    Membre éclairé Avatar de sylvain.cool
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2006
    Messages : 242
    Par défaut
    C'est bon, ça marche en local avec CoCreateInstanceEx.

    Par contre, depuis un autre PC, non. J'obtiens l'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    E_NOINTERFACE: "None of the interfaces requested in the pResults array were successfully retrieved."
    Je donne à la fonction CoCreateInstanceEx le nom du PC sur lequel il doit aller chercher l'objet. Par contre, je ne lui donne aucune infos sur comment se connecter au PC (login et autres).

    Ce qui est sur, c'est qu'il trouve le PC puisque si je donne un mauvais nom, il me le dit.
    Mais si il n'arrivait pas à s'y connecter pour trouver l'objet, il devrait me le dire aussi, non?



    De plus, quand j'enregistre l'objet sur le serveur avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, objectNumber)
    Avec cela, j'obtiens l'erreur ci-dessus.
    Mais maintenant que j'essaie depuis un autre PC, je met:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE, objectNumber)
    Et la, depuis le client je ai une autre erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    REGDB_E_CLASSNOTREG: "A specified class is not registered in the registration database. Also can indicate that the type of server you requested in the CLSCTX enumeration is not registered or the values for the server types in the registry are corrupt."
    Je trouve ça bizarre qu'en enlevant le LOCAL, ça change quelque chose sur le client situé sur un autre PC.


    Code actuel:
    Serveur:
    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
     
        TCOMITestServeurCOMT<TTestServeurCOM> serveur = CoTTestServeurCOM::Create();
        IUnknown * serveurPtr = serveur;
        LPDWORD objectNumber = new DWORD;
        //int reponse;
     
        // On enregistre le serveur
        if(SUCCEEDED(CoRegisterClassObject(CLSID_TTestServeurCOM, serveurPtr, CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE, objectNumber)))
                        std::cout << "Serveur enregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON enregistre."  << std::endl;
     
        // On attend une connexion
        MessageBox(NULL, TEXT("Cliquer OK pour quitter"), TEXT("Serveur COM"), MB_OK);
     
        std::cout << std::endl;
     
        // On dereference l'objet
        if(SUCCEEDED(CoRevokeClassObject(*objectNumber)))
                        std::cout << "Serveur desenregistre: " << *objectNumber << std::endl;
        else
                        std::cout << "Serveur NON desenregistre."  << std::endl;
     
        system("PAUSE");
    client:
    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
    76
    77
     
      HRESULT reponse; 
      TCOMITestServeurCOMT<TTestServeurCOM> serveur; 
     
     
     
      std::cout<< "Initialize: " << std::endl;
      if(!SUCCEEDED(reponse=CoInitialize(NULL)))  
           switch(reponse){
                          case S_OK:
                               std::cout << "The COM library was initialized successfully on this thread." << std::endl;
                               break;  
                          case S_FALSE:
                               std::cout << "The COM library is already initialized on this thread.." << std::endl;
                               break;
                          case RPC_E_CHANGED_MODE:
                               std::cout << "A previous call to CoInitializeEx specified the concurrency model for this thread as multithread apartment (MTA). If running Windows 2000, this could also mean that a change from neutral-threaded apartment to single-threaded apartment occurred." << std::endl;
                               break;
                          default:
                               std::cout << "Reponse inconnue???: 0x" << std::hex << reponse << std::endl;
                               break;
           }
      else
          std::cout << "The COM library was initialized successfully on this thread." << std::endl;
     
     
     
      std::cout << std::endl << "CoCreateInstanceEx: " << std::endl;
     
      // Création de la structure MULTI_QI
      MULTI_QI multiQiRes;
      multiQiRes.pIID = &IID_ITestServeurCOM, //& IID_IUnknown;
      multiQiRes.pItf = NULL;   
      multiQiRes.hr = 0;
     
      //Creation du COSERVERINFO
      COSERVERINFO serveurInfo;
      wchar_t serveurName[] = L"UC06P1556.fr.pierre-fabre.lcl";  
      serveurInfo.pwszName = serveurName;
      serveurInfo.pAuthInfo = NULL;
      serveurInfo.dwReserved1 = 0; 
      serveurInfo.dwReserved2 = 0;
     
      reponse=CoCreateInstanceEx(CLSID_TTestServeurCOM, NULL, CLSCTX_REMOTE_SERVER, &serveurInfo, 1, &multiQiRes);
      //CLSCTX_REMOTE_SERVER|CLSCTX_LOCAL_SERVER
     
      if(!SUCCEEDED(reponse))
          switch(reponse){ 
    					  case REGDB_E_CLASSNOTREG:
                               std::cout << "A specified class is not registered in the registration database. Also can indicate that the type of server you requested in the CLSCTX enumeration is not registered or the values for the server types in the registry are corrupt." << std::endl;
                               break;
    					  case E_NOINTERFACE:
                               std::cout << "None of the interfaces requested in the pResults array were successfully retrieved." << std::endl;
    						   break;
    					  case CLASS_E_NOAGGREGATION:
    						   std::cout << "This class cannot be created as part of an aggregate." << std::endl;
    						   break; 
    					  case CO_S_NOTALLINTERFACES:
    						   std::cout << "At least one, but not all of the interfaces requested in the pResults array were successfully retrieved. The hr field of each of the MULTI_QI structures in pResults indicates with S_OK or E_NOINTERFACE whether the specific interface was returned." << std::endl;
    						   break;
                          default:
    						   std::cout << "Reponse inconnue???: 0x" << std::hex << reponse << std::endl;
                               break;
          } 
      else{
           std::cout << "Location and connection to the specified class object was successful." << std::endl;
           serveur = static_cast< ITestServeurCOM * >(multiQiRes.pItf);
      }
     
     
     
      if( SUCCEEDED(reponse) ){  
                 std::cout << std::endl << "Appel de l'objet distant:" << std::endl;
                 std::wcout << "Nombre de processeurs: " << serveur.Nombre << " et voila." << std::endl;
      }
     
      system("PAUSE");

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Typiquement, il faut que la DLL contenant le proxy de ton interface soit installée et enregistrée sur le poste client.
    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Probleme avec la copie des surfaces
    Par Black_Daimond dans le forum DirectX
    Réponses: 3
    Dernier message: 09/01/2003, 10h33
  2. Problèmes avec le filtrage des ip
    Par berry dans le forum Réseau
    Réponses: 9
    Dernier message: 30/12/2002, 07h51
  3. probleme avec la touche F10
    Par b.grellee dans le forum Langage
    Réponses: 2
    Dernier message: 15/09/2002, 22h04
  4. Probleme avec fseek
    Par Bjorn dans le forum C
    Réponses: 5
    Dernier message: 04/08/2002, 07h17
  5. [Kylix] probleme avec un imagelist
    Par NicoLinux dans le forum EDI
    Réponses: 4
    Dernier message: 08/06/2002, 23h06

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