.NET in the pocket !

Bonjour à tous et bienvenue !

Ce blog est obsolète! Vous pouvez maintenant me retrouver sur: The .NET Frog


Suivez moi sur The .Net Frog!

Après une très longue période d'inactivité, j'ai décidé de recommencer à bloguer sur les technologies .Net et le développement en général.

C'est donc avec grand plaisir que je vous retrouverez sur un tout nouveau site, aux adresses suivantes:

Au programme:

et pleins d'autres choses!

Les liens de la semaine #2

Voici la 2eme édition des "liens de la semaine" (avec un peu de retard, désolé !). Le moins que je puisse dire, c'est que je n'ai pas vu grand chose de notable pour le commun des développeurs :).

Anglais :

Reconstruire l'arborescence des itérations d'un projet sans utiliser Olap

TFS fournit deux façons différentes pour accéder à sa warehouse : - Un cube, dont l'utilisation est fortement recommandée - Une base de données relationnelle sur laquelle se base le cube

La deuxième solution permet de contourner certaines limitations, mais encore faut-il avoir les bons outils à sa disposition pour consulter la base. Par exemple, comment faire pour reconstruire simplement l'arborescence des itérations d'un projet en une seule requête?

Heureusement pour nous, Microsoft à introduit dans Sql Server 2005 la notion de "Common Table Expressions" (ou CTE). Cette construction permet de construire une table qui n'existera que pendant la durée de vie de l'objet dans laquelle elle est déclarée. Jusque la, il n'y a rien de bien extraordinaire... Mais c'est sans compter sur le fait que les CTE supportent la récursivité !

Voici un exemple avec nos itérations :

  1. WITH cte_Iteration ([__ID], [Iteration Uri], [Iteration], [LEVEL]) AS
  2. (
  3. SELECT [Iteration].[__ID], [Iteration].[Iteration Uri],
  4. [Iteration].[Iteration], 1 AS [LEVEL]
  5. FROM [Iteration]
  6. WHERE [__ID] = 26
  7.  
  8. UNION ALL
  9.  
  10. SELECT [Iteration].[__ID], [Iteration].[Iteration Uri],
  11. [Iteration].[Iteration], [cte_Iteration].[LEVEL] + 1 AS [LEVEL]
  12. FROM [Iteration] INNER JOIN [cte_Iteration]
  13. ON [Iteration].[Parent Iteration Uri] = [cte_Iteration].[Iteration Uri]
  14. )
  15.  
  16. SELECT [__ID], [Iteration], [LEVEL]
  17. FROM [cte_Iteration]
  • La première ligne permet de déclarer les colonnes de notre CTE. Vous l'aurez remarqué, il n'est pas nécessaire de mettre un type.
  • La première requête permet de sélectionner les données qui vont servir de point de départ à la récursivité. Dans mon exemple, je choisis de partir de l'itération 26 et d'afficher ses enfants.
  • Les mots "UNION ALL" représentent le point central de la requête, ce sont eux qui rendent la récursivité possible.
  • La deuxième requête permet de lier chaque résultat parent à son enfant, grâce à la jointure. Le champ Level permet de voir à quel niveau on se trouve.
  • Enfin, notre dernier SELECT, qui se trouve en dehors du bloc WITH, permet d'exécuter le tout !

Le résultat est le suivant:

Il faut bien comprendre que la récursivité ne va pas se limiter au premier niveau. Au contraire, la requête va boucler sur elle même pour afficher tous les niveaux enfants. Le T-SQL permet d'ailleurs de limiter la profondeur la récursivité de la façon suivante :

  1. SELECT [__ID], [Iteration], [LEVEL]
  2. FROM [cte_Iteration]
  3. OPTION (MAXRECURSION 2);

Remarque : Si l'on ne précise pas l'option MAXRECURSION, Sql Server stoppe par défaut l'exécution de la requête après 100 récursions.

Remarque 2 : A exécuter sur la table TfsWarehouse

Les liens de la semaine #1

Etant donné que j'essaye chaque semaine de faire le tour des infos importantes autour de .NET, autant en faire profiter les quelques lecteurs qui viennent ici. Je vais donc essayer, chaque fin de semaine, de faire un petit récapitulatif des choses intéressantes que j'ai vu et vous les proposer. Attention, l'essentiel des liens redirigeront vers du contenu en anglais !

Pour le premier billet de la série, le nombre de lien sera particulièrement réduit étant donné que je n'ai pas pris la peine de noter au fur et à mesure les liens vers les articles intéressants. Je tenterai de faire attention à partir de Lundi :).

En anglais :

En français :

Girlfriend 6.0 vs. Wife 1.0

Pour une fois rien de technique dans ce billet, mais juste un lien vers un petit post qui m'a bien fait marrer : Girlfriend 6.0 vs. Wife 1.0. Je pense que nombre de personnes se reconnaitront dedans :).

P.S : C'est surement un vieux truc qui est remonté récemment, désolé si vous connaissez déjà !

Plugin pour Team Explorer : Tour d'horizon

J'ai passé quelques heures de plus sur un plugin pour Team Explorer, de quoi partager quelques informations supplémentaires...

Malheureusement, la première chose qui saute aux yeux est l'absence totale de documentation sur le sujet... A priori, aucune des classes des différents namespaces utilisés pour développer un plugin pour Team Explorer n'est documenté. Si bien que l'on se retrouve à ré implémenter des fonctions virtuelles d'une classe dont on hérite sans trop savoir ce que la dite fonction est censée faire... génial ;) ! Heureusement pour nous qu'il y a le sample sur lequel se baser. Toutefois, il y a quand même quelques topics intéressants sur les forums anglais de la msdn. A utiliser en cas de grosse galère ;).

Ceci étant dit, rentrons dans le vif du sujet. Pour ceci, nous avons besoin du SDK pour Visual Studio, CF mon post précédant et plus précisément d'ouvrir la solution "VisualStudioTeamSystemIntegration\Team Explorer and Project Creation\Sample Solution\PcwTESample\PcwTESample.sln".

La solution contient 2 projets : PcwTESample et PcwTESampleUI. Le second est un projet C++ contenant notamment un fichier de ressources (Ressource Files\PcwTESampleUI.rc) avec des chaines de caractères. A priori, je ne crois pas qu'il y ait quoique ce soit à faire sur les autres fichiers, faites moi savoir si je me trompe :). Comme vous vous en doutez, l'essentiel de l'implémentation de notre plugin va donc se trouver dans le premier projet, PcwTESample...

PcwTESample fournit en réalité deux fonctionnalités bien distinctes. Il y a tout d'abord un Wizard qui va être exécuté pendant la création d'un nouveau projet dont le process template fait appel au plugin. Il va, par exemple, permettre au chef de projet d'entrer un certain nombre d'informations qui pourraient être requises par le plugin plus tard. Le wizard est implémenté dans les fichiers PluginPcwSample.cs et PluginSampleWizardPage.cs (l'interface utilisateur). N'ayant pas besoin de cette feature pour le moment, je ne pourrai vous en dire beaucoup plus... La deuxième fonctionnalité est le plugin pour Team Explorer en lui même, que chaque membre de l'équipe pourra utiliser au quotidien.

Avant d'aller plus loin, voyons comment ces deux fonctionnalités sont exposées à Visual Studio. Le projet contient une classe HostPackage qui se charge de cette étape. Son rôle est donc de déclarer la présence du wizard et du plugin et de les instancier le moment voulu et en fonction du contexte. La déclaration est effectuée grâce aux attributs suivants :

  1. [ProvideService(typeof(TEPlugin))]
  2. [PluginRegistration(Catalogs.TeamProject, "Sample TE Plugin", typeof(TEPlugin))]
  3. [ProvideService(typeof(SamplePcwPlugin))]
  4. [PluginRegistration(Catalogs.ProjectCreation, "Sample PCW Plugin", typeof(SamplePcwPlugin))]

Elle s'effectue donc en 2 étapes. D'un coté on déclare un nouveau service avec ProvideService et de l'autre on enregistre ce fameux service comme un plugin. Cette deuxième étape permet d'ailleurs de déclarer le type de plugin que l'on enregistre à l'aide du premier paramètre. Catalogs peut donc prendre la valeur TeamProject (un plugin pour Team Explorer), ProjectCreation (un wizard actif lors de la création du projet) ou ClientLinking (Alors la, mystère étant donné l'absence de doc ! D'après le nom, on peut penser que c'est peut être pour déclarer un plugin qui doit faire interagir TeamExplorer avec un autre client installé sur la machine... Si quelqu'un trouve, je suis preneur :)) On le voit bien ici, il est tout à fait possible de déclarer plusieurs plugins dans le même package. La classe HostPackage va donc avoir pour principale mission d'instancier et d'initialiser nos différents plugins. L'instanciation est faite à l'aide de la méthode OnCreateService, et l'initialisation avec la méthode Initialize. Ces deux méthodes sont appelées par le framework de Visual Studio au moment ou celui-ci s'apprête à utiliser un plugin, de façon complètement autonome (Par exemple, lors de la création d'un nouveau projet pour un wizard, ou lors du chargement d'un projet dans l'interface de Team Explorer pour un plugin Team Explorer).

Exemple d'implémentations pour les fonctions OnCreateService et Initialize :

  1. public sealed class HostPackage : PluginHostPackage
  2. {
  3. protected override object OnCreateService(IServiceContainer container, Type serviceType)
  4. {
  5. if (serviceType == typeof(TEPlugin))
  6. {
  7. return new TEPlugin();
  8. }
  9. if (serviceType == typeof(SamplePcwPlugin))
  10. {
  11. return new SamplePcwPlugin();
  12. }
  13. throw new ArgumentException(serviceType.ToString());
  14. }
  15.  
  16.  
  17. protected override void Initialize()
  18. {
  19. Trace.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
  20. base.Initialize();
  21.  
  22. // Ce code permet par exemple de charger un control dans un onglet
  23. // à coté des documents ouverts, lorsque le plugin est chargé
  24. MSVSIP.ToolWindowPane pane = this.FindToolWindow(typeof(PlannificationPane), 0, true);
  25. if (pane == null)
  26. {
  27. throw new COMException("@101");
  28. }
  29. IVsWindowFrame frame = pane.Frame as IVsWindowFrame;
  30. if (frame == null)
  31. {
  32. throw new COMException("@102");
  33. }
  34. ErrorHandler.ThrowOnFailure(frame.Show());
  35.  
  36. }
  37.  
  38. [...]
  39. }

Maintenant que l'on sait comment est chargé le plugin, nous allons pouvoir regarder comment ce dernier est conçu. Il est implémenté dans la classe TEPlugin (fichier VsPkg.cs) et cette dernière doit hériter soit de BasicAsyncPlugin, soit de BasicPlugin. La encore, pas de documentation... Toutefois, d'après les noms, on peut penser qu'hériter de BasicAsyncPlugin permet de ne pas bloquer l'interface utilisateur lorsque le plugin réalise certaines actions. Deux fonctions sont significatives dans cette classe :

  • GetNewUIHierarchy : Je sais que cette fonction est appelée avant que Team Explorer affiche l'arborescence des répertoires. Pour autant, je suis honnêtement incapable de dire quelle est son utilité réelle :). Tout indice sur le sujet est le bienvenue :)
  • CreateNewTree : Cette fonction permet d'ajouter des éléments à l'arborescence affichée dans Team Explorer. C'est donc l'endroit rêvé pour fournir à l'utilisateur du plugin un point d'entrée vers la fonctionnalité que l'on souhaite exposer. CreateNewTree prend un objet BaseUIHierarchy en paramètre. Il va nous permettre d'accéder à quelques propriétés intéressantes, comme par exemple : le nom du serveur, l'URI du projet, le nom du projet, l'instance du package ayant construit le plugin, etc (respectivement les propriétés : ServerName, ProjectUri, ProjectName et HostPackage). Nous avons donc toutes les informations souhaitées pour afficher un nouveau dossier spécifique à notre plugin dans un projet de Team Explorer. Pour cela, plusieurs étapes :
    • D'abord, il est nécessaire d'instancier un nouvel objet de type TEPluginRoot (héritant de BaseRoot), symbolisant la racine de l'arborescence que nous souhaitons afficher.
    • Deuxièmement, nous devons déclarer quels seront les noeuds enfants de notre racine. Ceci peut être fait à l'aide des classes TEPluginFolder (un répertoire) et TEPluginLeaf (un élément n'ayant lui même pas de sous élément) dont le code est exposé plus bas. Ces deux classes héritent de BaseHierarchyNode qui représente un élément quelconque de l'arborescence, mais redéfinissent le comportement de base. Il est donc très facile de remplir l'arborescence, voici un exemple simple :
  1. protected override BaseHierarchyNode CreateNewTree(BaseUIHierarchy hierarchy)
  2. {
  3. TEPluginUIHierarchy uiHierarchy = (TEPluginUIHierarchy)hierarchy;
  4. TEPluginRoot root = new TEPluginRoot(hierarchy.ServerName + '/' + hierarchy.ProjectName);
  5.  
  6. TEPluginFolder myFolder = new TEPluginFolder(root.CanonicalName + "/MesSites", "Mes sites");
  7. myFolder.AddChild(new TEPluginLeaf(myFolder.CanonicalName + "/google", "Google", "http://www.google.fr"));
  8. myFolder.AddChild(new TEPluginLeaf(myFolder.CanonicalName + "/julien", "Blog julien", "http://julien.lavigneducadet.com"));
  9. root.AddChild(myFolder);
  10. return root;
  11. }

Et comme promis, le code de TEPluginFolder et TEPluginLeaf :

  1. public class TEPluginFolder : BaseHierarchyNode
  2. {
  3. public TEPluginFolder(string path, string name)
  4. : base(path, name)
  5. {
  6. InitAsFolder();
  7. }
  8.  
  9. public override String PropertiesClassName
  10. {
  11. get { return "Plugin Folder"; }
  12. }
  13. }
  14.  
  15.  
  16.  
  17. public class TEPluginLeaf : BaseHierarchyNode
  18. {
  19. public TEPluginLeaf(string path, string name, string uri)
  20. : base(path, name)
  21. {
  22. this.uri = uri;
  23. InitAsLeaf();
  24. }
  25.  
  26. public override void DoDefaultAction()
  27. {
  28. // Do something !
  29. }
  30.  
  31. public override string PropertiesClassName
  32. {
  33. get { return "Search Engine"; }
  34. }
  35.  
  36. private string uri;
  37. }

Nous sommes maintenant arrivés au stade ou nous avons pu afficher de nouveaux noeuds pour notre plugin. Il ne reste plus qu'a lancer une action quelconque lorsque l'utilisateur double clique dessus. Grace à la classe TEPluginLeaf, c'est très facile ! Il suffit de redéfinir la fonction DoDefaultAction et d'implémenter dedans l'action que l'on souhaite réaliser lors du double clique. Dans le cas du Sample, c'est par exemple d'ouvrir l'url correspondant au noeud en cours, avec le code suivant :

  1. LaunchVsBrowserWindow(this.uri);

Evidemment, ce pourrait aussi être quelque chose de plus intéressant comme ouvrir une nouvelle fenêtre dans Visual Studio, et y charger un control que nous avons développé pour prendre en charge une fonctionnalité non gérée par Team Explorer. Les possibilités sont assez colossales :).

En conclusion, si vous avez compris ce que j'ai essayé d'expliquer dans cet article, vous êtes paré pour développer un bon gros plugin pour Team Explorer, bon courage ! :)

Intellisense pour le SQL

Je ne sais plus ou j'ai vu cela, mais ça valait la peine d'être noté :

Une société du nom de Red Gate a publié un outil fort sympathique qui permet d'avoir l'intellisense avec SQL Server dans les éditeurs Microsoft. Cela inclus notamment Visual Studio et SQL Server Management Studio. Ca s'appelle Sql Prompt et franchement, c'est du tout bon ! A essayer d'urgence, d'autant que c'est gratuit jusqu'à fin Août.

Plugin pour Team Explorer

J'ai commencé à tester les possibilités d'extension de Team Explorer il y a quelques heures, je vais donc faire un point sur les quelques informations que j'ai pu trouver ici et la.

Premièrement, pour étendre Team Explorer, il est nécessaire d'installer le SDK de Visual studio. Il est disponible sur cette page, mais il faudra auparavant s'enregistrer dans le programme VSIP (Visual Studio Industry Partner). Cette opération est heureusement gratuite :)

Une fois le SDK installé, une nouvelle entrée apparaît dans le menu démarrer. Elle donne accès à certains éléments, dont 3 me semblent importants :

  • Le sample browser, qui permet d'accéder rapidement à des exemples de plugins et autres extensions
  • Un lien vers les répertoires dédiés à Visual Studio Team System. Il contient notamment un exemple de plugin pour Team Explorer
  • Un lien vers le programme "Reset the Visual Studio 2005 Experimental hive" qui permet de remettre l'environnement de test de Visual Studio dans sa configuration d'origine (C'est nécessaire pour tester les nouvelles versions de votre futur plugin :))

A mon avis, l'une des premières choses à faire est de jeter un oeil au dossier "Team Explorer and Project Creation" dans la section VSTS. La solution montre deux fonctionnalités intéressantes :

  • Comment créer un assistant accessible pendant la création d'un nouveau projet
  • Comment créer un nouveau dossier et des sous éléments dans Team Explorer (Le gros du travail se passe dans la classe "TEPlugin")

Le tout n'est pas très difficile à prendre en main, je ne détaille pas plus pour le moment :)

L'élément important à remarquer, est qu'un plugin Team Explorer n'est qu'un plugin Visual Studio. La principale différence vient du fait que dans le premier cas, il faudra hériter de la classe "PluginHostPackage" qui hérite elle-même de "Microsoft.VisualStudio.Shell.Package", alors que dans le second, on pourra hériter directement de "Microsoft.VisualStudio.Shell.Package". Cette information ouvre quelques perspectives intéressantes ! En effet, les différents exemples d'extension de Visual Studio fournis dans le SDK implémentent eux même cette classe. Nos plugins Team Explorer vont donc pouvoir implémenter le même spectre de fonctionnalités que n'importe quel plugin Visual Studio ! Et surtout, il suffit de combiner les divers exemples du SDK avec l'exemple de plugin pour Team Explorer pour avoir le résultat voulu. C'est en effet très facile, puisque les packages de base héritent de la même classe. Il n'y a qu'à faire du copier coller.

Si j'ai le temps, j'essaierai de fournir d'autres éléments d'informations et pourquoi pas des exemples concret dans les jours à venir :)

Edit : J'ai voulu poster ce billet avec Windows Live Writer Beta, c'est pas mal comme outil mais le code généré est tout sauf conforme au standard XHTML... Dommage !

Petit Powerpoint de présentation de TFS

Je viens de publier un powerpoint qui m'a servi de base pour une présentation de TFS. Attention, c'est essentiellement centré sur la notion de work item. Le repository, les builds et ce qui s'y rapporte (comme les tests) ne sont pas abordés.

Deux remarques donc :

  • J'ai fait ce powerpoint alors que je connaissais encore peu TFS.
  • Ce n'est absolument pas une présentation complète ! J'ai volontairement laissé de coté certaines fonctionnalités pour me concentrer sur des points spécifiquements importants dans le cadre d'un projet précis.

Quoiqu'il en soit, peut être que ca sera utile à quelqu'un :) N'hésitez pas à me contacter ici pour me dire si cette présentation vous à été utile ou pour me proposer une mise à jour.

J'en profite aussi pour vous dire que Rob Caron à publié les slides de nombreuses présentations sur Team System effectuées lors du dernier TechEd à Boston. Le tout ici.

Installation de TFS (bis) : Ce qu'il ne faut surtout pas faire.

Je suis tombé sur un problème relativement important dans l'installation de TFS, et je pense ne pas être le seul à me retrouver dans ce cas. Le serveur sur lequel j'ai installé TFS héberge déjà certains sites web. Pour tout dire, il y en à même sur différents ports, dont deux sur le port 80. Le premier est le site par défaut, tandis que le second est en fait arrêté : une équipe en à eu besoin à une époque pour faire des tests, mais il n'est plus utilisé.

Jusque la tout va bien, tout semble compatible avec notre installation de TFS... Mais non ! Ne me demandez pas pourquoi, mais lors de l'installation, SharePoint a été activé sur le mauvais site ! C'est à dire sur celui des deux qui n'est pas lancé et que personne n'utilise !

J'ai donc des erreurs 404 dans l'assistant de création de projet, car Team Explorer ne trouve pas le web service _vti_bin/Sites.asmx. Evidemment, comme SharePoint est installé sur un site arrêté, ce n'est pas très étonnant...

Conclusion : Ne jamais essayer d'installer TFS si vous avez deux sites configurés pour écouter le port 80.

Installation de TFS : erreur 32000

La journée commençait bien, nous avions décidé d’installer TFS sur un vrai serveur pour continuer nos tests, en lieu et place d'une machine virtuelle. Je m’appretais donc à faire passer notre TFS d'une VM hébergé sur un p4 2,4Ghz, 1Go de ram vers un quadri-xeon, 4Go de ram : avec cela, on ne devrait plus ramer :). C'était sans compter sur la fameuse erreur 32000...

L'erreur 32000 est un peu l'écran bleu du setup de TFS :) On sait que ca plante, mais vogue la galère pour trouver la source exacte ! Dans mon cas, le message d'erreur exact était le suivant :

The Commandline '"c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\Bin\Stsadm.exe" ...' returned non-zero value: -2130246318.

En fait, la solution était simple ce coup ci, les comptes étaient justes mal configurés. La documentation précise qu'il faut ajouter la permissions "Log on locally" aux comptes TFSSERVICE et TFSREPORTS, mais sous certaines conditions, il semblerait que ce ne soit pas suffisant ! En effet, il m'a aussi fallut ajouter la permissions "Log on as a service" à TFSSETUP, TFSSERVICE et TFSREPORTS. TFSSERVICE était d'ailleurs déjà présent dans la liste, et je suppose qu'il suffit d'ajouter uniquement TFSSETUP. Mais dans le doute, j'ai mis les trois !

C# 3 : Vers la dérive?

J'ai parcouru rapidement l'article de présentation de C# 3 et Linq de Thomas Lebrun, avec qui je suis de la même promo. Je dois dire que j'ai hate de le lire en entier ! Par contre, après cette lecture en diagonale, je m'interroge sur l'avenir du C# et sur ce qui pourrait être apparenté à des dérives...

C# 3 introduit la notion "d'initialisateur d'objets". A première vue, le nom fait penser à un constructeur... Quelle fonctionnalité se cache donc derrière? Et bien reprenons l'exemple de Thomas (très légèrement modifié, pour simplifier l'exemple). Le voici :

  1. //C# 1 ou 2 :
  2. User u1 = new User();
  3. u1.FirstName = "Thomas";
  4. u1.LastName = "LEBRUN";
  5. u1.Age = 24;
  6. // Ou alors
  7. User u2 = new User("Thomas", "LEBRUN", 24);
  8.  
  9.  
  10. // Version C# 3
  11. var u3 = new User { FirstName = "Thomas", LastName = "LEBRUN", Age = 24 };

Remarque : le mot clef var est une nouvelle façon de définir une variable, lisez l'article de Thomas pour plus d'infos.

Avec C# 3, nous venons de gagner 10 lettres par rapport à la première déclaration. Palpitant... Evidemment, chaque programmeur va commencer à utiliser la forme de déclaration ayant sa faveur : vive la lisibilité du code ! C'est donc un nouveau concept à intégrer dans les coding standards des projets. Et pour quel interêt? Je me le demande ! Peut être que quelqu'un pourra m'éclairer? :)

Est ce le début d'une dérive? A force de vouloir contenter tout le monde, est ce que Microsoft ne va pas finir par détruire la cohérence de ce beau langage? A suivre...

IE 7 beta et Reporting Services...

Voici juste un petit mot pour dire que IE 7 beta 3 plante complètement avec certains reports (la consommation CPU monte à 100% et le programme ne répond plus, il faut tuer le process...). Donc si vous utilisez Reporting Services, passez votre chemin et rester sous IE 6! Par ailleurs, inutile d'utiliser Firefox, car le moins que l'on puisse dire, c'est que les reports peuvent parfois apparaître de façon étrange...

Afficher les erreurs du serveur de report lors de connexions distantes

Après avoir déployé un report, je me suis retrouvé avec un message ressemblant à cela :

An error has occurred during report processing.
Query execution failed for data set 'IterationParam'.
For more information about this error navigate to the report server on the local server machine, or enable remote errors 

La manipulation pour activer l'affichage des erreurs lors de connexions distantes est en fait très simple. Il suffit de créer un fichier EnableRemoteErrors.rss sur le serveur en question, et d'y placer le code suivant :

  1. Public Sub Main()
  2. Dim P As New [Property]()
  3. P.Name = "EnableRemoteErrors"
  4. P.Value = True
  5. Dim Properties(0) As [Property]
  6. Properties(0) = P
  7. Try
  8. rs.SetSystemProperties(Properties)
  9. Console.WriteLine("Affichage des erreurs à distance activé.")
  10. Catch SE As SoapException
  11. Console.WriteLine(SE.Detail.OuterXml)
  12. End Try
  13. End Sub

Ensuite, tapez la ligne suivante dans une fenêtre de commande (en prenant soin de mettre la bonne adresse pour votre fichier EnableRemoteErrors.rss) :

rs -i "C:\EnableRemoteErrors.rss" -s http://localhost/ReportServer

Le tour est joué, les erreurs vont désormais s'afficher :)

Pour les désactiver, modifiez "P.Value = True" par "P.Value = False" dans le fichier, et relancez la commande.

Reconstruire la Warehouse

Un petit utilitaire fort sympathique permet de reconstruire la warehouse de TFS en cas de pépin : SetupWarehouse.exe. C'est par exemple très utile si vous avez fait des modifications sur la BDD Olap de TFS et que vous voulez revenir à la version d'origine.

La documentation de ce petit outils est disponible en anglais ici.


Deux exemples de commandes tout de même (remplacez TFSUser et TFSReportingAccount par vos propres comptes) :

  • Reconstruire uniquement la base OLAP (celle qui apparait dans Analysis Services):

"C:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Tools\SetupWarehouse.exe" -o -s localhost -d TFSWarehouse -c warehouseschema.xml -a TFSUser -ra TFSReportAccount

  • Reconstruire la base relationnelle (celle qui apparait dans Database Services):

"C:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Tools\SetupWarehouse.exe" -rebuild -mturl http://localhost:8080 -s localhost -d TFSWarehouse -c warehouseschema.xml -a TFSUser -ra TFSReportAccount -edt TfsBuild