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

FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013  Ajouter une question

 

Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++

Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.

Sur ce, je vous souhaite une bonne lecture. Farscape

SommaireISAPI (8)
précédent sommaire suivant
 

En définissant l'opérateur de flux pour un BYTE dans une classe:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
// BinaryHtmlStream.h: interface for the CBinaryHtmlStream class. 
// 
////////////////////////////////////////////////////////////////////// 
  
#if !defined(AFX_BINARYHTMLSTREAM_H__E8E5B559_A8D3_4DEE_B38D_2ABF4D319672__INCLUDED_) 
#define AFX_BINARYHTMLSTREAM_H__E8E5B559_A8D3_4DEE_B38D_2ABF4D319672__INCLUDED_ 
  
#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
  
class CBinaryHtmlStream : public CHtmlStream 
{ 
public: 
// we have a special overload of << to allow for a single byte 
CBinaryHtmlStream& operator<<(BYTE b) { Write(&b, 1); return *this; } 
}; 
  
#endif // !defined BINHTMSTREAM_H

Mis à jour le 4 avril 2005 matazz

En utilisant la classe CBinaryHtmlStream ci-dessus :

Code C++ : Sélectionner tout
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
//******************************************************************* 
// Renvoi une resource du workspace 
//******************************************************************* 
void ClsMyServerExtension::SendResource(CHttpServerContext *pCtxt, int ID_RS) 
{ 
    CBinaryHtmlStream* pStream = new CBinaryHtmlStream(); 
    CString ContentSize; 
    CString RSNumb; 
    unsigned int Size = 0; 
    HINSTANCE hIn = NULL; 
    HRSRC tSrc = NULL; 
    HGLOBAL hImage = NULL; 
    BYTE* pImage = NULL; 
  
    //Attention ajouter le type mime du flux de retour en fonction du type de Resource A modifier 
    AddHeader(pCtxt ,_T("Content-Type: image/jpeg\r\n")); 
    //AddHeader(pCtxt ,_T("Content-Type: application/x-shockwave-flash\r\n"));} 
  
    RSNumb.Format("#%d",ID_RS); 
  
    hIn= AfxGetResourceHandle(); 
         //Où BINARY est un groupe de resource comme Dialog, Menu... 
    tSrc = ::FindResource (hIn,RSNumb.GetBuffer(0),"BINARY"); 
    hImage = ::LoadResource(hIn,tSrc); 
    Size = ::SizeofResource(hIn,tSrc); 
    pImage = (BYTE*) ::LockResource(hImage); 
  
    ContentSize.Format( "Content-length: %d\r\n", Size); 
    AddHeader( pCtxt, _T(ContentSize)); 
  
    for (int Ind = 0; Ind <Size; Ind++){ *pStream << pImage[Ind]; } 
  
    *pCtxt << *pStream; 
    delete pStream; 
    //delete pImage; Supprimé à la destruction du Thread(Voire MSDN)  
}

Mis à jour le 4 avril 2005 matazz

La séquence Escape c'est une forme de codage des caractères non alpha-numérique du style "-1" en Séquence Escape sera "%2D1". En gros c'est % + code Hexa du car.

Le problème c'est que si Dans une DLL extension ISAPI vous définissez une fonction comme suite :

Code c++ : Sélectionner tout
1
2
3
  
ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR ITS_R4 ) 
ON_PARSE_COMMAND_PARAMS("String=Str Double=-1.54")
Si vous appelez votre DLL comme suit : où %2D25%2E12 correspond à -25.12.
Vous recevrez dans la DLL comme valeur de Double 25.00 et non -25.12

Pou corriger ce bug de IIS :

Code c++ : Sélectionner tout
1
2
3
  
ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR ITS_PSTR ) 
ON_PARSE_COMMAND_PARAMS("String=Str Double=-1.54")
Double devient une String et la séquence Escape sera correctement traduite, charge à vous de faire un atof(...) pour récupérer un double...

Mis à jour le 4 avril 2005 matazz

L'environnement IIS (ou 2IS) est MultiThread à savoir que chaque requête Http est parsée puis exécutée sur un thread (Attention aux variables globales de la classe car tous les thread vont y accéder).
Ainsi si vous voulez utiliser ADO dans une DLL ISAP il faut effectuer le CoInitialize et CoUninitialize dans chaque Function appelable par IIS :

Imaginons que vous ayez deux fonctions appelables depuis une requête http

Code C++ : Sélectionner tout
1
2
3
4
5
ON_PARSE_COMMAND(GetRaster, ClsMyServerExtension, ITS_PSTR ) 
ON_PARSE_COMMAND_PARAMS("D=DataBase") 
  
ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR) 
ON_PARSE_COMMAND_PARAMS("R=r")

Il faudra faire dans chacune des fonctions qui utilisent ADO :

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
//******************************************************************* 
// Recharge la config 
//******************************************************************* 
void ClsMyServerExtension::Reload(CHttpServerContext *pCtxt, LPTSTR R) 
{ 
    HRESULT hres = ::CoInitializeEx(NULL,COINIT_MULTITHREADED ); 
    ... //traitement plus renvoi de texte ou dat dans le flux... 
    ::CoUninitialize(); 
}

Pour utiliser le Flag COINIT_MULTITHREADED il faut définir dans le .h de votre extension serveur .

Code C++ : Sélectionner tout
1
2
#define _WIN32_DCOM 
#include "objbase.h"

Remarque : vous pouvez mettre simplement ::CoInitialize(NULL) mais si vous avez des retours de HTML avec un code du genre -2147417842 (0x8001010e) vous devrez utiliser le flag COINIT_MULTITHREADED.

Mis à jour le 4 avril 2005 matazz

Cela peut paraître trivial comme question, mais c'est pas forcément clair lorsque l'on fait un nouveau workspace en choisissant ISAPI extension Server.

En fait on peut avoir si l'on veut deux types de fonctions :

Les fonctions points d'entrée HTTP et les autres à savoir celles qui vont servir aux fonctions points d'entrée.

Pour la clarté il paraît plus simple de faire une ou plusieurs classes qui réalisent les traitement désirés sur les appels et laisser dans la classe générée par Visual Studio que les fonctions point d'entrées...
Après chacun fait comme il veut...

Donc, pour faire une fonction point d'entrée HTTP il faut faire comme suit :
Ajouter une fonction classiquement mais en mettant toujours comme premier paramètre un pointeur sur un CHttpServerContext :

dans le .h

Code c++ : Sélectionner tout
1
2
  
void GetData(CHttpServerContext *pCtxt, int Integer, LPTSTR String)
et dans le .cpp

Code c++ : Sélectionner tout
1
2
3
4
5
  
void CMyServerExtension::GetData(CHttpServerContext *pCtxt, int Integer, LPTSTR String) 
  { 
  ... 
  }
Ensuite : dans le .cpp (au tout début de ce dernier) il y a une zone définie par :

Code c++ : Sélectionner tout
BEGIN_PARSE_MAP(ClsMyServerExtension, CHttpServer)
Dans cette zone se trouve toutes les données pour que IIS redirige les appels HTTP sur les fonctions de la DLL.
Si vous n'ajoutez pas votre fonction ici vous ne pourrez jamais l'appeller sur une requette HTTP.
Dans notre cas il faut ajouter :

Code c++ : Sélectionner tout
1
2
3
  
ON_PARSE_COMMAND(GetData, ClsMyServerExtension, ITS_I4 ITS_PSTR) 
ON_PARSE_COMMAND_PARAMS("Integer=12 String=MaString")
La première balise correspond à une sorte de prototypage pour IIS et la seconde donne des valeurs par défaut à passer à la fonction si les paramètres ne sont pas présents dans la requette HTTP.

Remarque :
Les types définissables pour le Parse_Command sont :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
//pour les fonctions sans paramètres: 
#define ITS_EMPTY           "\x06"      // no parameters 
//les autres types 
#define ITS_I2              "\x01"      // a 'short' 
#define ITS_I4              "\x02"      // a 'long' 
#define ITS_R4              "\x03"      // a 'float' 
#define ITS_R8              "\x04"      // a 'double' 
#define ITS_PSTR            "\x05"      // a 'LPCTSTR' 
#define ITS_RAW                         "\x07"          // exactly as received

Mis à jour le 4 avril 2005 matazz

C'est simple dans la fonction en utilisant le CHttpServerContext :

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
unsigned longSize = 250; 
LPTSTR ClientIP  = (LPTSTR) malloc(Size); 
  
pCtxt->GetServerVariable("REMOTE_ADDR", ClientIP, &Size); 
  
CStringIpClient = CString(ClientIP, Size); 
free(ClientIP);

Les autres paramètres sont (CF MSDN):



Value Meaning
AUTH_TYPE Contains the type of authentication used. If the string is empty, then no authentication is used.
CONTENT_LENGTH The number of bytes which the script can expect to receive from the client.
CONTENT_TYPE The content type of the information supplied in the body of a POST request.
GATEWAY_INTERFACE The revision of the CGI specification to which this server complies. The current version is CGI/1.1.
PATH_INFO Additional path information, as given by the client. This comprises the trailing part of the URL after the extension DLL (script) name but before the query string (if any).
PATH_TRANSLATED This is the value of PATH_INFO, but with any virtual path name expanded into a directory specification.
QUERY_STRING The information which follows the ? in the URL which referenced this extension DLL.
REMOTE_ADDR The IP address of the client.
REMOTE_HOST The hostname of the client.
REMOTE_USER This contains the username supplied by the client and authenticated by the server.
REQUEST_METHOD The HTTP request method.
SCRIPT_NAME The name of the extension DLL that is being executed.
SERVER_NAME The server's hostname (or IP address) as it should appear in self-referencing URLs.
SERVER_PORT The TCP/IP port on which the request was received.
SERVER_PROTOCOL The name and version of the information retrieval protocol relating to this request. Normally HTTP/1.0.
SERVER_SOFTWARE The name and version of the web server under which the ISA or server extension DLL program is running.
ALL_HTTP All HTTP headers that were not already parsed into one of the above variables.
These variables are of the form HTTP_<header field name>.
HTTP_ACCEPT : Special case HTTP header. Values of the Accept: fields are concatenated, separated by ", ".
For example, if the following lines are part of the HTTP header:
Code : Sélectionner tout
1
2
3
 accept: */*; q=0.1 
 accept: text/html 
 accept: image/jpeg
then the HTTP_ACCEPT variable will have a value of:

Code : Sélectionner tout
*/*; q=0.1, text/html, image/jpeg
Mise à jour : Ce n'est pas signalé dans la MSDN mais on peut récupérer le type de navigateur du client en utilisant la même procédure avec la valeur HTTP_USER_AGENT

Mis à jour le 4 avril 2005 matazz

Attention ceci peut poser des problèmes car sur des requêtes HTTP en Post le client appelle la DLL dans un premier temps et n'envoie les paramètres que dans un second temps , ce qui à pour conséquence de déclencher la fonction par défaut (Constaté avec IE6, j'ai pas d'autre infos sur les autres Browsers).

La fonction par défaut est la fonction appelée quand on tape un requête du type sans paramètres :

Sinon ça se passe dans la section BEGIN_PARSE_MAP, il suffit juste de rempacer le nom de la fonction qui va être appelée par défaut :

Code c++ : Sélectionner tout
1
2
3
  
ON_PARSE_COMMAND(MaFonctionParDefaut, ClsMyServerExtension, ITS_EMPTY) 
DEFAULT_PARSE_COMMAND(MaFonctionParDefaut, ClsMyServerExtension)

Mis à jour le 4 avril 2005 matazz

Adapté à VC++ depuis :  Débogage de DLL ISAPI
Merci à Sylvain James pour les copies d'écran…
C'est assez compliqué et tordu mais c'est possible :
il vous faut le server IIS, et le service de composant COM et COM+
Première chose il ne faut pas avoir XP Home ou alors allez regarder ce lien :  Installer IIS sous Windows XP Familial car il n'y a pas le serveur IIS sous XP home édition.

Pour savoir si vous avez IIS installé faite bouton droit "gérer" puis dans "services et applications" vous devez avoir "services Internet (IIS)"
Première étape :
Installer IIS si nécessaire.
dans votre site Web par défaut, créer un répertoire virtuel (Appelons-le DLL) en cochant bien à la fin "Exécuter (par exemple, CGI ou application ISAPI)".
Ensuite clic droit "Propriétés" sur le dossier crée.

Dans "Protection d'application" choisir "élevée (Isolée)"


Deuxième étape : Il faut maintenant ouvrir la gestion des services COM et COM+ :
(je vous conseille de faire un raccourci)

sous XP : "C:\WINDOWS\system32\Com\comexp.msc"


Dans "Services de composants"->"Ordinateurs"->"Poste de travail"->"Applications COM+"
vous devez avoirs plusieurs process dont quelques uns commençant par IIS dont un notamment portant le nom de votre répertoire virtuel. Sur ce dernier Clic droit "Propriétés".


Dans l'onglet "Général" vous avez en bas "ID de L'application :"
suivi du CLSID de votre répertoire Virtuel sélectionnez-le et copiez-le . (Cela ce présente sous la forme : {BFC384AE-C057-4C64-8A04-3FC3EBEB00AD}).


Ensuite dans l'onglet "Identité" vérifiez que "Compte Système" soit bien coché (utilisateur actuellement connecté).


Vous pouvez maintenant fermer le gestionnaire des services COM+.

Troisième et dernière étape :
Ouvrez votre projet dans Visual Studio.
Dans le Menu "Project"->"Settings" (ou ALt+F7)

Dans l'onglet "Debug" :

Dans l'Edit "Executable for debug session" mettre :
(sous XP, pour 2000 c'est C:\WINNT\...)
"C:\WINDOWS\system32\dllhost.exe"
Dans "Working directory" mettez le dossier physique sur lequel pointe votre dossier virtuel.
par exemple "C:\www\MonSite\Binary\DLL\"

Ensuite dans "Program Argument" mettez le CLSID que vous avez copié du gestionnaire de service COM+ comme suit :
"/ProcessID:{BFC384AE-C057-4C64-8A04-3FC3EBEB00AD}"

Enfin (C'est bientôt fini) dans l'onglet "Link" linkez votre exe dans le répertoire physique correspondant au répertoire virtuel :
"C:\www\MonSite\Binary\DLL\MyExtension.dll"
Fermer et faites "File"->"Save Workspace", ça serai bête de paumer les modifications.

Vous Pouvez maintenant lancer la version debug, mettez un point d'arrêt dans la fonction "Default", puis dans votre Browser tapez :
"http://localhost/DLL/MyExtension.dll?" et validez.

Remarque d'usage :

Si vous changez la protection d'application de votre répertoire virtuel, il faudra remettre dans le gestionnaire de services COM+ le compte Système.

Si vous voulez recompiler votre DLL suite à une modification, il vous faudra décharger la DLL de la mémoire afin de pouvoir réécrire sur la DLL sinon vous aurez un message du style "unable to link write error".
Pour décharger la DLL clic droit sur le répertoire virtuel "Propriétés" et il y a un bouton décharger.

Mis à jour le 4 avril 2005 matazz

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2022 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.