Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette rubrique décrit ce que vous devez réfléchir lors de l’écriture d’outils de diagnostic qui analysent le code managé exécuté dans une application du Windows Store. Il fournit également des instructions pour modifier vos outils de développement existants afin qu’ils continuent à fonctionner lorsque vous les exécutez sur des applications du Windows Store. Pour comprendre ces informations, il est préférable de vous familiariser avec l’API de profilage Common Language Runtime. Vous avez déjà utilisé cette API dans un outil de diagnostic qui s’exécute correctement sur les applications de bureau Windows et que vous souhaitez maintenant modifier l’outil pour qu’il s’exécute correctement sur les applications du Windows Store.
Introduction
Si vous l’avez fait au-delà du paragraphe d’introduction, vous êtes familiarisé avec l’API de profilage CLR. Vous avez déjà écrit un outil de diagnostic qui fonctionne bien sur les applications de bureau managées. Maintenant, vous êtes curieux de savoir ce qu’il faut faire pour que votre outil fonctionne avec une application du Windows Store managée. Peut-être avez-vous déjà essayé de faire ce travail, et vous avez découvert que ce n’est pas une tâche simple. En effet, il existe un certain nombre de considérations qui peuvent ne pas être évidentes pour tous les développeurs d’outils. For example:
- Les applications du Windows Store s’exécutent dans un contexte avec des autorisations sévèrement réduites.
- Les fichiers de métadonnées Windows ont des caractéristiques uniques par rapport aux modules managés traditionnels.
- Les applications du Windows Store ont l’habitude de se suspendre quand l’interactivité tombe en panne.
- Vos mécanismes de communication interprocessus peuvent ne plus fonctionner pour diverses raisons.
Cet article répertorie les éléments dont vous avez besoin pour connaître et comment les traiter correctement.
Si vous débutez avec l’API de profilage CLR, passez aux ressources à la fin de cette rubrique pour trouver de meilleures informations d’introduction.
Fournir des détails sur des API Windows spécifiques et la façon dont elles doivent être utilisées est également en dehors de l’étendue de cette rubrique. Considérez cette rubrique comme point de départ et reportez-vous à MSDN pour en savoir plus sur les API Windows référencées ici.
Architecture et terminologie
En règle générale, un outil de diagnostic a une architecture semblable à celle illustrée dans l’illustration suivante. Il utilise le terme « profileur », mais de nombreux outils de ce type vont bien au-delà du profilage des performances ou de la mémoire standard dans des domaines tels que la couverture du code, les frameworks d’objets fictifs, le débogage de voyage dans le temps, la surveillance des applications, etc. Par souci de simplicité, cette rubrique continuera de faire référence à tous ces outils en tant que profils.
La terminologie suivante est utilisée dans cette rubrique :
Application
Il s’agit de l’application que le profileur analyse. En règle générale, le développeur de cette application utilise désormais le profileur pour diagnostiquer les problèmes liés à l’application. Traditionnellement, cette application serait une application de bureau Windows, mais dans cette rubrique, nous examinons les applications du Windows Store.
Profiler DLL
Il s’agit du composant qui se charge dans l’espace de processus de l’application en cours d’analyse. Ce composant, également appelé « agent » du profileur, implémente les interfaces ICorProfilerCallback ICorProfilerCallback(2,3,etc.) et consomme les interfaces ICorProfilerInfo(2,3,etc.) pour collecter des données sur l’application analysée et éventuellement modifier les aspects du comportement de l’application.
Profiler UI
Il s’agit d’une application de bureau avec laquelle l’utilisateur profileur interagit. Il est chargé d’afficher l’état de l’application à l’utilisateur et de donner à l’utilisateur les moyens de contrôler le comportement de l’application analysée. Ce composant s’exécute toujours dans son propre espace de processus, séparé de l’espace de processus de l’application profilée. L’interface utilisateur de Profiler peut également agir comme « déclencheur d’attachement », qui est le processus qui appelle la méthode ICLRProfiling ::AttachProfiler , pour provoquer le chargement de la DLL profileur dans les cas où la DLL du profileur ne s’est pas chargée au démarrage.
Important
Votre interface utilisateur de Profiler doit rester une application de bureau Windows, même lorsqu’elle est utilisée pour contrôler et signaler une application du Windows Store. Ne vous attendez pas à être en mesure de empaqueter et d’expédier votre outil de diagnostic dans le Windows Store. Votre outil doit effectuer des opérations que les applications du Windows Store ne peuvent pas faire, et la plupart de ces choses résident dans votre interface utilisateur profileur.
Tout au long de ce document, l’exemple de code suppose que :
- Votre DLL Profiler est écrite en C++, car elle doit être une DLL native, conformément aux exigences de l’API de profilage CLR.
- Votre interface utilisateur profileur est écrite en C#. Cela n’est pas nécessaire, mais parce qu’il n’y a aucune exigence sur la langue du processus de votre interface utilisateur de Profiler, pourquoi ne pas choisir une langue concise et simple ?
Appareils Windows RT
Les appareils Windows RT sont assez verrouillés. Les profils tiers ne peuvent simplement pas être chargés sur ces appareils. Ce document se concentre sur les PC Windows 8.
Consommation d’API Windows Runtime
Dans plusieurs scénarios décrits dans les sections suivantes, votre application de bureau Profiler UI doit consommer de nouvelles API Windows Runtime. Vous souhaiterez consulter la documentation pour comprendre quelles API Windows Runtime peuvent être utilisées à partir d’applications de bureau et si leur comportement est différent lorsqu’ils sont appelés à partir d’applications de bureau et d’applications du Windows Store.
Si votre interface utilisateur Profiler est écrite en code managé, vous devez effectuer quelques étapes pour faciliter l’utilisation de ces API Windows Runtime. Pour plus d’informations, consultez l’article Applications de bureau managées et Windows Runtime .
Chargement de la DLL profileur
Cette section décrit comment votre interface utilisateur profileur entraîne le chargement de votre DLL Profiler par l’application du Windows Store. Le code décrit dans cette section appartient à votre application de bureau de l’interface utilisateur Profiler et implique donc l’utilisation d’API Windows sécurisées pour les applications de bureau, mais pas nécessairement sécurisées pour les applications du Windows Store.
L’interface utilisateur de Profiler peut entraîner le chargement de votre DLL Profiler dans l’espace de processus de l’application de deux façons :
Au démarrage de l’application, tel qu’il est contrôlé par les variables d’environnement.
En attachant à l’application une fois le démarrage terminé, appelez la méthode ICLRProfiling ::AttachProfiler .
L’un de vos premiers obstacles consiste à charger au démarrage et à attacher la charge de votre DLL Profiler pour fonctionner correctement avec les applications du Windows Store. Les deux formes de chargement partagent certaines considérations particulières en commun, donc commençons par eux.
Considérations courantes relatives au démarrage et à l’attachement des charges
Signature de votre DLL Profiler
Lorsque Windows tente de charger votre DLL Profiler, il vérifie que votre DLL Profiler est correctement signée. Si ce n’est pas le cas, la charge échoue par défaut. Il existe deux méthodes pour y parvenir :
Vérifiez que votre DLL Profiler est signée.
Indiquez à votre utilisateur qu’il doit installer une licence développeur sur son ordinateur Windows 8 avant d’utiliser votre outil. Cette opération peut être effectuée automatiquement à partir de Visual Studio ou manuellement à partir d’une invite de commandes. Pour plus d’informations, consultez Obtenir une licence de développeur.
Autorisations du système de fichiers
L’application du Windows Store doit avoir l’autorisation de charger et d’exécuter votre DLL Profiler à partir de l’emplacement dans lequel elle réside par défaut, l’application du Windows Store n’a pas cette autorisation sur la plupart des répertoires, et toute tentative de chargement de votre DLL Profiler génère une entrée dans le journal des événements de l’application Windows qui ressemble à ceci :
NET Runtime version 4.0.30319.17929 - Loading profiler failed during CoCreateInstance. Profiler CLSID: '{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}'. HRESULT: 0x80070005. Process ID (decimal): 4688. Message ID: [0x2504].
En règle générale, les applications du Windows Store sont uniquement autorisées à accéder à un ensemble limité d’emplacements sur le disque. Chaque application du Windows Store peut accéder à ses propres dossiers de données d’application, ainsi que quelques autres zones du système de fichiers pour lesquelles toutes les applications du Windows Store ont accès. Il est préférable d’installer votre DLL Profiler et ses dépendances quelque part sous Program Files ou Program Files (x86), car toutes les applications du Windows Store ont des autorisations de lecture et d’exécution là-bas par défaut.
Startup load
En règle générale, dans une application de bureau, votre interface utilisateur Profiler invite une charge de démarrage de votre DLL Profiler en initialisant un bloc d’environnement qui contient les variables d’environnement de l’API de profilage CLR requises (c’est-à-dire, COR_PROFILER, COR_ENABLE_PROFILINGet COR_PROFILER_PATH), puis en créant un processus avec ce bloc d’environnement. La même chose est vraie pour les applications du Windows Store, mais les mécanismes sont différents.
Ne pas exécuter avec élévation de privilèges
Si le processus A tente de générer le processus B de l’application du Windows Store, le processus A doit être exécuté à un niveau d’intégrité moyen, pas à un niveau d’intégrité élevé (autrement dit, pas élevé). Cela signifie que l’interface utilisateur de Profiler doit s’exécuter au niveau d’intégrité moyen, ou qu’elle doit générer un autre processus de bureau au niveau d’intégrité moyen pour prendre en charge le lancement de l’application du Windows Store.
Choix d’une application du Windows Store à profiler
Tout d’abord, vous devez demander à l’utilisateur de votre profileur quelle application du Windows Store lancer. Pour les applications de bureau, vous affichez peut-être une boîte de dialogue Parcourir un fichier, et l’utilisateur trouve et sélectionne un fichier .exe. Toutefois, les applications du Windows Store sont différentes et l’utilisation d’une boîte de dialogue Parcourir n’est pas logique. Au lieu de cela, il est préférable d’afficher à l’utilisateur une liste d’applications du Windows Store installées pour cet utilisateur.
Vous pouvez utiliser la PackageManager classe pour générer cette liste.
PackageManager est une classe Windows Runtime disponible pour les applications de bureau, et en fait elle est uniquement disponible pour les applications de bureau.
L’exemple de code suivant à partir d’une interface utilisateur de Profiler hypothétique écrite en tant qu’application de bureau en C# utilise la PackageManager liste des applications Windows :
string currentUserSID = WindowsIdentity.GetCurrent().User.ToString();
IAppxFactory appxFactory = (IAppxFactory) new AppxFactory();
PackageManager packageManager = new PackageManager();
IEnumerable<Package> packages = packageManager.FindPackagesForUser(currentUserSID);
Spécification du bloc d’environnement personnalisé
Une nouvelle interface COM, IPackageDebugSettings, vous permet de personnaliser le comportement d’exécution d’une application du Windows Store pour faciliter certaines formes de diagnostic. L’une de ses méthodes , EnableDebugging, vous permet de passer un bloc d’environnement à l’application du Windows Store lors du lancement, ainsi que d’autres effets utiles, comme la désactivation de la suspension automatique du processus. Le bloc d’environnement est important, car c’est là que vous devez spécifier les variables d’environnement (COR_PROFILERet COR_ENABLE_PROFILINGCOR_PROFILER_PATH)) utilisées par le CLR pour charger votre DLL Profiler.
Prenez l'exemple de l'extrait de code suivant :
IPackageDebugSettings pkgDebugSettings = new PackageDebugSettings();
pkgDebugSettings.EnableDebugging(packageFullName, debuggerCommandLine,
(IntPtr)fixedEnvironmentPzz);
Il existe quelques éléments dont vous aurez besoin :
packageFullNamepeut être déterminé lors de l’itération sur les packages et depackage.Id.FullNamela saisie .debuggerCommandLineest un peu plus intéressant. Pour passer le bloc d’environnement personnalisé à l’application du Windows Store, vous devez écrire votre propre débogueur factice simpliste. Windows génère l’application Du Windows Store suspendue, puis attache votre débogueur en lançant votre débogueur avec une ligne de commande comme dans cet exemple :MyDummyDebugger.exe -p 1336 -tid 1424où
-p 1336signifie que l’application du Windows Store a l’ID de processus 1336, et-tid 1424signifie que l’ID de thread 1424 est le thread suspendu. Votre débogueur factice analyse le ThreadID à partir de la ligne de commande, reprend ce thread, puis quitte.Voici un exemple de code C++ à effectuer (veillez à ajouter la vérification des erreurs !) :
int wmain(int argc, wchar_t* argv[]) { // … // Parse command line here // … HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE /* bInheritHandle */, nThreadID); ResumeThread(hThread); CloseHandle(hThread); return 0; }Vous devez déployer ce débogueur factice dans le cadre de votre installation de l’outil de diagnostic, puis spécifier le chemin d’accès à ce débogueur dans le
debuggerCommandLineparamètre.
Lancement de l’application du Windows Store
Le moment de lancer l’application du Windows Store est enfin arrivé. Si vous avez déjà essayé de le faire vous-même, vous avez peut-être remarqué que CreateProcess n’est pas la façon dont vous créez un processus d’application du Windows Store. Au lieu de cela, vous devez utiliser la méthode IApplicationActivationManager ::ActivateApplication . Pour ce faire, vous devez obtenir l’ID de modèle utilisateur de l’application du Windows Store que vous lancez. Et cela signifie que vous devrez faire un peu creuser dans le manifeste.
Lors de l’itération sur vos packages (voir « Choix d’une application du Windows Store à profiler » dans la section Chargement de démarrage précédemment), vous devez récupérer l’ensemble d’applications contenues dans le manifeste du package actuel :
string manifestPath = package.InstalledLocation.Path + "\\AppxManifest.xml";
AppxPackaging.IStream manifestStream;
SHCreateStreamOnFileEx(
manifestPath,
0x00000040, // STGM_READ | STGM_SHARE_DENY_NONE
0, // file creation attributes
false, // fCreate
null, // reserved
out manifestStream);
IAppxManifestReader manifestReader = appxFactory.CreateManifestReader(manifestStream);
IAppxManifestApplicationsEnumerator appsEnum = manifestReader.GetApplications();
Oui, un package peut avoir plusieurs applications et chaque application a son propre ID de modèle utilisateur d’application. Vous devez donc demander à votre utilisateur quelle application profiler et saisir l’ID de modèle utilisateur de l’application à partir de cette application particulière :
while (appsEnum.GetHasCurrent() != 0)
{
IAppxManifestApplication app = appsEnum.GetCurrent();
string appUserModelId = app.GetAppUserModelId();
//...
}
Enfin, vous avez maintenant ce dont vous avez besoin pour lancer l’application du Windows Store :
IApplicationActivationManager appActivationMgr = new ApplicationActivationManager();
appActivationMgr.ActivateApplication(appUserModelId, appArgs, ACTIVATEOPTIONS.AO_NONE, out pid);
N’oubliez pas d’appeler DisableDebugging
Lorsque vous avez appelé IPackageDebugSettings ::EnableDebugging, vous avez fait une promesse que vous feriez le nettoyage après vous-même en appelant la méthode IPackageDebugSettings ::D isableDebugging , veillez à le faire lorsque la session de profilage est terminée.
Attach load
Lorsque votre interface utilisateur de Profiler souhaite attacher sa DLL Profiler à une application qui a déjà commencé à s’exécuter, elle utilise ICLRProfiling ::AttachProfiler. La même chose est vraie avec les applications du Windows Store. En plus des considérations courantes répertoriées précédemment, assurez-vous que l’application du Windows Store cible n’est pas suspendue.
EnableDebugging
Comme pour le chargement de démarrage, appelez la méthode IPackageDebugSettings ::EnableDebugging . Vous n’en avez pas besoin pour passer un bloc d’environnement, mais vous avez besoin de l’une de ses autres fonctionnalités : désactivation de la suspension automatique du processus. Sinon, lorsque votre interface utilisateur profileur appelle AttachProfiler, l’application windows Store cible peut être suspendue. En fait, cela est probable si l’utilisateur interagit maintenant avec votre interface utilisateur profileur et que l’application du Windows Store n’est active sur aucun des écrans de l’utilisateur. Et si l’application du Windows Store est suspendue, elle ne pourra pas répondre à tout signal envoyé par le CLR pour attacher votre DLL Profiler.
Vous voudrez donc faire quelque chose comme ceci :
IPackageDebugSettings pkgDebugSettings = new PackageDebugSettings();
pkgDebugSettings.EnableDebugging(packageFullName, null /* debuggerCommandLine */,
IntPtr.Zero /* environment */);
Il s’agit du même appel que vous effectueriez pour le cas de chargement de démarrage, sauf que vous ne spécifiez pas de ligne de commande du débogueur ou d’un bloc d’environnement.
DisableDebugging
Comme toujours, n’oubliez pas d’appeler IPackageDebugSettings ::D isableDebugging lorsque votre session de profilage est terminée.
Exécution à l’intérieur de l’application du Windows Store
Par conséquent, l’application du Windows Store a enfin chargé votre DLL Profiler. Maintenant, votre DLL Profiler doit être enseignée comment jouer par les différentes règles requises par les applications du Windows Store, y compris les API qui sont autorisées et comment s’exécuter avec des autorisations réduites.
Coller aux API d’application du Windows Store
Lorsque vous parcourez l’API Windows, vous remarquerez que chaque API est documentée comme applicable aux applications de bureau, aux applications du Windows Store ou aux deux. Par exemple, la section Exigences de la documentation relative à la fonction InitializeCriticalSectionAndSpinCount indique que la fonction s’applique uniquement aux applications de bureau. En revanche, la fonction InitializeCriticalSectionEx est disponible pour les applications de bureau et les applications du Windows Store.
Lors du développement de votre DLL Profiler, traitez-le comme s’il s’agit d’une application du Windows Store et utilisez uniquement des API documentées comme disponibles pour les applications du Windows Store. Analysez vos dépendances (par exemple, vous pouvez exécuter link /dump /imports sur votre DLL Profiler pour auditer), puis rechercher dans la documentation pour voir quelles dépendances sont correctes et qui ne le sont pas. Dans la plupart des cas, vos violations peuvent être corrigées en les remplaçant simplement par une forme plus récente de l’API documentée comme sécurisée (par exemple, en remplaçant InitializeCriticalSectionAndSpinCount par InitializeCriticalSectionExEx).
Vous remarquerez peut-être que votre DLL Profiler appelle certaines API qui s’appliquent uniquement aux applications de bureau et qu’elles semblent fonctionner même lorsque votre DLL Profiler est chargée dans une application du Windows Store. N’oubliez pas qu’il est risqué d’utiliser une API non documentée pour une utilisation avec les applications du Windows Store dans votre DLL Profiler lors du chargement dans un processus d’application du Windows Store :
Ces API ne sont pas garanties de fonctionner lorsqu’elles sont appelées dans le contexte unique dans lequel les applications du Windows Store s’exécutent.
Ces API peuvent ne pas fonctionner de manière cohérente lorsqu’elles sont appelées à partir de différents processus d’application du Windows Store.
Ces API peuvent sembler fonctionner correctement à partir d’applications du Windows Store dans la version actuelle de Windows, mais peuvent s’interrompre ou être désactivées dans les futures versions de Windows.
Le meilleur conseil est de corriger toutes vos violations et d’éviter le risque.
Vous pouvez constater que vous ne pouvez absolument pas faire sans une API particulière et ne peut pas trouver de remplacement adapté aux applications du Windows Store. Dans ce cas, au minimum :
Testez, testez les jours d’été vivants de votre utilisation de cette API.
Comprenez que l’API peut soudainement interrompre ou disparaître si elle est appelée à partir d’applications du Windows Store dans les versions ultérieures de Windows. Cela ne sera pas considéré comme un problème de compatibilité par Microsoft, et la prise en charge de votre utilisation ne sera pas une priorité.
Reduced permissions
Il est en dehors de l’étendue de cette rubrique pour répertorier toutes les façons dont les autorisations d’application du Windows Store diffèrent des applications de bureau. Mais certainement, le comportement sera différent chaque fois que votre DLL Profiler (lorsqu’elle est chargée dans une application du Windows Store par rapport à une application de bureau) tente d’accéder à toutes les ressources. Le système de fichiers est l’exemple le plus courant. Il existe toutefois quelques emplacements sur le disque auxquels une application du Windows Store donnée est autorisée à accéder (voir Accès aux fichiers et autorisations (applications Windows Runtime), et votre DLL Profiler sera soumise aux mêmes restrictions. Testez votre code de manière approfondie.
Inter-process communication
Comme indiqué dans le diagramme au début de ce document, votre DLL Profiler (chargée dans l’espace de processus d’application du Windows Store) devra probablement communiquer avec votre interface utilisateur Profiler (exécutée dans un espace de processus d’application de bureau distinct) via votre propre canal de communication interprocessus personnalisé (IPC). L’interface utilisateur du Profileur envoie des signaux à la DLL Profiler pour modifier son comportement, et la DLL Profiler envoie des données de l’application du Windows Store analysée à l’interface utilisateur du Profileur pour le post-traitement et l’affichage à l’utilisateur du profileur.
La plupart des profils doivent fonctionner de cette façon, mais vos choix pour les mécanismes IPC sont plus limités lorsque votre DLL Profiler est chargée dans une application du Windows Store. Par exemple, les canaux nommés ne font pas partie du Kit de développement logiciel (SDK) de l’application du Windows Store. Vous ne pouvez donc pas les utiliser.
Mais bien sûr, les fichiers sont toujours en cours, bien qu’ils soient plus limités. Les événements sont également disponibles.
Communication via des fichiers
La plupart de vos données passeront probablement entre la DLL Profiler et l’interface utilisateur profileur via des fichiers. La clé consiste à choisir un emplacement de fichier auquel votre DLL Profiler (dans le contexte d’une application du Windows Store) et l’interface utilisateur profileur ont accès en lecture et en écriture. Par exemple, le chemin du dossier temporaire est un emplacement auquel votre DLL Profiler et l’interface utilisateur profileur peuvent accéder, mais aucun autre package d’application du Windows Store ne peut accéder (ce qui protège les informations que vous connectez à partir d’autres packages d’applications du Windows Store).
L’interface utilisateur de Profiler et la DLL Profiler peuvent déterminer ce chemin indépendamment. Votre interface utilisateur de Profiler, lorsqu’elle effectue une itération dans tous les packages installés pour l’utilisateur actuel (voir l’exemple de code précédemment), obtient l’accès à la PackageId classe, à partir de laquelle le chemin du dossier temporaire peut être dérivé avec du code similaire à cet extrait de code. (Comme toujours, la vérification des erreurs est omise pour la concision.)
// C# code for the Profiler UI.
ApplicationData appData =
ApplicationDataManager.CreateForPackageFamily(
packageId.FamilyName);
tempDir = appData.TemporaryFolder.Path;
Pendant ce temps, votre DLL Profiler peut faire essentiellement la même chose, bien qu’elle puisse plus facilement accéder à la ApplicationData classe à l’aide de la propriété ApplicationData.Current .
Communication par le biais d’événements
Si vous souhaitez une sémantique de signalisation simple entre l’interface utilisateur de Profiler et la DLL Profiler, vous pouvez utiliser des événements dans des applications du Windows Store ainsi que des applications de bureau.
À partir de votre DLL Profiler, vous pouvez simplement appeler la fonction CreateEventEx pour créer un événement nommé avec n’importe quel nom de votre choix. For example:
// Profiler DLL in Windows Store app (C++).
CreateEventEx(
NULL, // Not inherited
"MyNamedEvent"
CREATE_EVENT_MANUAL_RESET, /* explicit ResetEvent() required; leave initial state unsignaled */
EVENT_ALL_ACCESS);
L’interface utilisateur de Profiler doit ensuite rechercher cet événement nommé sous l’espace de noms de l’application Du Windows Store. Par exemple, votre interface utilisateur de Profiler peut appeler CreateEventEx, en spécifiant le nom de l’événement en tant que
AppContainerNamedObjects\<acSid>\MyNamedEvent
<acSid> est le SID AppContainer de l’application Du Windows Store. Une section antérieure de cette rubrique a montré comment itérer sur les packages installés pour l’utilisateur actuel. À partir de cet exemple de code, vous pouvez obtenir l’id de package. Et à partir du packageId, vous pouvez obtenir le <acSid> code similaire à ce qui suit :
IntPtr acPSID;
DeriveAppContainerSidFromAppContainerName(packageId.FamilyName, out acPSID);
string acSid;
ConvertSidToStringSid(acPSID, out acSid);
string acDir;
GetAppContainerFolderPath(acSid, out acDir);
Aucune notification d’arrêt
Lors de l’exécution à l’intérieur d’une application du Windows Store, votre DLL Profiler ne doit pas s’appuyer sur ICorProfilerCallback ::Shutdown ou même DllMain (avec DLL_PROCESS_DETACH) appelée pour avertir votre DLL Profiler que l’application du Windows Store quitte. En fait, vous devriez vous attendre à ce qu’ils ne soient jamais appelés. Historiquement, de nombreuses DLL Profiler ont utilisé ces notifications comme des endroits pratiques pour vider les caches sur le disque, fermer des fichiers, renvoyer des notifications à l’interface utilisateur de Profiler, etc. Mais maintenant, votre DLL Profiler doit être organisée un peu différemment.
Votre DLL Profiler doit journaliser les informations telles qu’elles se passent. Pour des raisons de performances, vous souhaiterez peut-être traiter les informations par lot en mémoire et les vider sur le disque à mesure que le lot augmente au-delà d’un certain seuil. Toutefois, supposons que toutes les informations qui ne sont pas encore vidées sur le disque peuvent être perdues. Cela signifie que vous souhaitez choisir votre seuil de manière judicieuse et que votre interface utilisateur de Profiler doit être renforcée pour gérer les informations incomplètes écrites par la DLL Profiler.
Fichiers de métadonnées Windows Runtime
Il n’est pas dans l’étendue de ce document pour entrer en détail sur les fichiers de métadonnées Windows Runtime (WinMD). Cette section est limitée à la façon dont l’API de profilage CLR réagit lorsque les fichiers WinMD sont chargés par l’application du Windows Store que votre DLL Profiler analyse.
WinMD gérés et non managés
Si un développeur utilise Visual Studio pour créer un projet de composant Windows Runtime, une build de ce projet produit un fichier WinMD qui décrit les métadonnées (les descriptions de type des classes, interfaces, etc.) créées par le développeur. Si ce projet est un projet de langage managé écrit en C# ou Visual Basic, ce même fichier WinMD contient également l’implémentation de ces types (ce qui signifie qu’il contient tous les il compilés à partir du code source du développeur). Ces fichiers sont appelés fichiers WinMD managés. Ils sont intéressants dans le fait qu’ils contiennent à la fois les métadonnées Windows Runtime et l’implémentation sous-jacente.
En revanche, si un développeur crée un projet de composant Windows Runtime pour C++, une build de ce projet produit un fichier WinMD qui contient uniquement des métadonnées et l’implémentation est compilée dans une DLL native distincte. De même, les fichiers WinMD fournis dans le Kit de développement logiciel (SDK) Windows contiennent uniquement des métadonnées, avec l’implémentation compilée en DLL natives distinctes fournies dans le cadre de Windows.
Les informations ci-dessous s’appliquent aux winMD managés, qui contiennent des métadonnées et une implémentation, ainsi qu’aux WinMD non managés, qui contiennent uniquement des métadonnées.
Les fichiers WinMD ressemblent aux modules CLR
En ce qui concerne le CLR, tous les fichiers WinMD sont des modules. L’API de profilage CLR indique donc à votre DLL Profiler quand les fichiers WinMD chargent et quelles sont leurs MODULES, de la même façon que pour d’autres modules managés.
Votre DLL Profiler peut distinguer les fichiers WinMD d’autres modules en appelant la méthode ICorProfilerInfo3 ::GetModuleInfo2 et en inspectant le pdwModuleFlags paramètre de sortie pour l’indicateur de COR_PRF_MODULE_WINDOWS_RUNTIME . (Elle est définie si et uniquement si le ModuleID représente un WinMD.)
Lecture de métadonnées à partir de WinMDs
Les fichiers WinMD, comme les modules standard, contiennent des métadonnées qui peuvent être lues via les API de métadonnées. Toutefois, le CLR mappe les types Windows Runtime aux types .NET Framework lorsqu’il lit des fichiers WinMD afin que les développeurs qui programment dans le code managé et consomment le fichier WinMD peuvent avoir une expérience de programmation plus naturelle. Pour obtenir des exemples de ces mappages, consultez la prise en charge de .NET Framework pour les applications du Windows Store et Windows Runtime.
Par conséquent, quelle vue votre profileur obtiendra-t-il lorsqu’il utilise les API de métadonnées : la vue Windows Runtime brute ou la vue .NET Framework mappée ? La réponse : c’est à toi.
Lorsque vous appelez la méthode ICorProfilerInfo ::GetModuleMetaData sur un WinMD pour obtenir une interface de métadonnées, telle que IMetaDataImport, vous pouvez choisir de définir ofNoTransform dans le dwOpenFlags paramètre pour désactiver ce mappage. Sinon, par défaut, le mappage sera activé. En règle générale, un profileur conserve le mappage activé, afin que les chaînes obtenues par la DLL Profiler à partir des métadonnées WinMD (par exemple, les noms de types) soient familières et naturelles à l’utilisateur du profileur.
Modification des métadonnées à partir de WinMDs
La modification des métadonnées dans WinMDs n’est pas prise en charge. Si vous appelez la méthode ICorProfilerInfo ::GetModuleMetaData pour un fichier WinMD et spécifiez ofWrite dans le dwOpenFlags paramètre ou demandez une interface de métadonnées accessible en écriture telle que IMetaDataEmit, GetModuleMetaData échoue. Il s’agit d’une importance particulière pour les profileurs de réécriture il, qui doivent modifier les métadonnées pour prendre en charge leur instrumentation (par exemple, pour ajouter AssemblyRefs ou de nouvelles méthodes). Vous devez donc rechercher COR_PRF_MODULE_WINDOWS_RUNTIME premier (comme indiqué dans la section précédente) et vous abstenir de demander des interfaces de métadonnées accessibles en écriture sur ces modules.
Résolution des références d’assembly avec WinMDs
De nombreux profileurs doivent résoudre manuellement les références de métadonnées pour faciliter l’instrumentation ou l’inspection de type. Ces profils doivent être conscients de la façon dont le CLR résout les références d’assembly qui pointent vers winMD, car ces références sont résolues d’une manière complètement différente des références d’assembly standard.
Memory profilers
Le garbage collector et le tas géré ne sont pas fondamentalement différents dans une application du Windows Store et une application de bureau. Toutefois, il existe des différences subtiles dont les auteurs de profileurs doivent être conscients.
ForceGC crée un thread managé
Lorsque vous effectuez le profilage de la mémoire, votre DLL Profiler crée généralement un thread distinct à partir duquel appeler la méthode ForceGC Method . C’est rien de nouveau. Mais ce qui peut être surprenant est que l’acte d’effectuer un garbage collection à l’intérieur d’une application du Windows Store peut transformer votre thread en thread managé (par exemple, un THREAD d’API de profilage sera créé pour ce thread).
Pour comprendre les conséquences de ce problème, il est important de comprendre les différences entre les appels synchrones et asynchrones tels que définis par l’API de profilage CLR. Notez que cela est très différent du concept d’appels asynchrones dans les applications du Windows Store. Consultez le billet de blog Pourquoi nous avons CORPROF_E_UNSUPPORTED_CALL_SEQUENCE pour plus d’informations.
Le point pertinent est que les appels effectués sur les threads créés par votre profileur sont toujours considérés comme synchrones, même si ces appels sont effectués en dehors d’une implémentation de l’une des méthodes ICorProfilerCallback de votre DLL Profiler. Au moins, c’était le cas. Maintenant que le CLR a transformé le thread de votre profileur en thread managé en raison de votre appel à forceGC, ce thread n’est plus considéré comme le thread de votre profileur. Par conséquent, le CLR applique une définition plus stricte de ce qui se qualifie comme synchrone pour ce thread, à savoir qu’un appel doit provenir de l’une des méthodes ICorProfilerCallback de votre DLL Profiler pour qu’elles soient considérées comme synchrones.
Qu’est-ce que cela signifie dans la pratique ? La plupart des méthodes ICorProfilerInfo sont uniquement sécurisées pour être appelées de manière synchrone et échouent immédiatement dans le cas contraire. Par conséquent, si votre DLL Profiler réutilise votre thread de méthode ForceGC pour d’autres appels généralement effectués sur des threads créés par profileur (par exemple, pour RequestProfilerDetach, RequestReJIT ou RequestRevert), vous aurez des problèmes. Même une fonction asynchrone sécurisée telle que DoStackSnapshot a des règles spéciales lorsqu’elle est appelée à partir de threads managés. (Consultez la pile du billet de blog Profiler : Informations de base et au-delà pour plus d’informations.)
Par conséquent, nous vous recommandons de créer un thread que votre DLL Profiler crée pour appeler la méthode ForceGCuniquement pour déclencher des contrôleurs de groupe, puis de répondre aux rappels GC. Il ne doit pas appeler l’API de profilage pour effectuer d’autres tâches telles que l’échantillonnage de pile ou le détachement.
ConditionalWeakTableReferences
À compter de .NET Framework 4.5, il existe un nouveau rappel GC, ConditionalWeakTableElementReferences, qui donne au profileur des informations plus complètes sur les handles dépendants. Ces handles ajoutent efficacement une référence d’un objet source à un objet cible à des fins de gestion de la durée de vie gc. Les handles dépendants ne sont rien de nouveau, et les développeurs qui programment dans le code managé ont pu créer leurs propres handles dépendants à l’aide de la System.Runtime.CompilerServices.ConditionalWeakTable<TKey,TValue> classe même avant Windows 8 et .NET Framework 4.5.
Toutefois, les applications du Windows Store XAML gérées utilisent désormais fortement les handles dépendants. En particulier, le CLR les utilise pour faciliter la gestion des cycles de référence entre les objets managés et les objets Windows Runtime non managés. Cela signifie qu’il est plus important que jamais pour les profileurs de mémoire d’être informés de ces handles dépendants afin qu’ils puissent être visualisées avec le reste des bords dans le graphique de tas. Votre DLL Profiler doit utiliser RootReferences2, ObjectReferences et ConditionalWeakTableElementReferences ensemble pour former une vue complète du graphique de tas.
Conclusion
Il est possible d’utiliser l’API de profilage CLR pour analyser le code managé s’exécutant dans les applications du Windows Store. En fait, vous pouvez prendre un profileur existant que vous développez et apporter des modifications spécifiques afin qu’il puisse cibler des applications du Windows Store. Votre interface utilisateur de Profiler doit utiliser les nouvelles API pour activer l’application du Windows Store en mode débogage. Assurez-vous que votre DLL Profiler consomme uniquement ces API applicables aux applications du Windows Store. Le mécanisme de communication entre votre DLL Profiler et l’interface utilisateur profileur doit être écrit avec les restrictions de l’API d’application du Windows Store à l’esprit et avec connaissance des autorisations restreintes en place pour les applications du Windows Store. Votre DLL Profiler doit être consciente de la façon dont le CLR traite winMDs et comment le comportement du garbage collector est différent en ce qui concerne les threads managés.
Resources
The Common Language Runtime
Interaction du CLR avec Windows Runtime
applications du Windows Store