Archive for the ‘Informatique’ Category

Sauvegardes : back to basics !

5 octobre 2013

Les sauvegardes sont des choses que trop peu de personne mettent en place… et pour cause, c’est souvent compliqué, et trouver le soft qui convienne bien est souvent une longue quête. Ensuite, il faut configurer des logiciels, et obtenir exactement ce que l’on veux est souvent une gageure…

Pour ma part, j’avais besoin de sauvegardes pour différentes choses :

  • mes sauvegardes perso (de la photo numérique et des données diverses, au total plusieurs dizaines de Go), je souhaite les faire sur mon NAS et aussi sur un support distant dans le cloud afin de me prémunir du vol notamment
  • des sauvegardes des données bureautiques de mes parents, pour ne pas les embêter avec des supports amovibles, la sauvegarde doit se faire à distance (quelques dizaines de Mo)
  • des sauvegardes de photo numériques sur disque dur externe pour des proches, en local

J’ai testé plusieurs solutions, Cobian Backup, Duplicati…

Cobian Backup fonctionne pas mal, je l’ai utilisé sur le PC de ma maman pour des sauvegardes sur une deuxième machine du foyer, via le réseau. Sauvegarde contraignante car il fallait que cette seconde machine soit allumée heure fixe pour que le sauvegarde se fasse… la sauvegarde devait donc passer à l’as assez souvent. Puis, cette seconde machine  à fini par être supprimée, exit la sauvegarde sur le réseau local donc. Comme j’ai un NAS connecté sur net via mon Raspberry Pi chez moi, je souhaitais donc transformer cette sauvegarde réseau local en sauvegarde à distance sur mon NAS via l’Internet. Je ne voulais pas que les données transitent en clair, exit donc cette solution qui ne sais faire que via FTP (non chiffré) ou via le système de fichier. Par ailleurs, Cobian Backup ne dispose d’aucun moyen de restauration simple, et selon le mode de sauvegarde, il ne conserve pas forcément arborescence… bonjour le boulot en cas de restauration…

J’ai testé sur ma machine Duplicati, solution qui paraissait complète, mais la aussi, pas assez paramétrable à mon gout… un miroir me suffit et il ne sais pas le faire à priori… il fait des archives ZIP avec les fichiers : ça consomme du temps et de la puissance pour rien, et en cas de corruption d’une archive c’est toutes les données contenues dans l’archive (100 Mo) qui sont perdues…

Enfin, il est difficile d’utiliser ces solutions dans le cadre de sauvegardes « à la demande » : dans tous les cas, il faut plusieurs cliques pour lancer la sauvegarde… je veux quelque chose qui fonctionne en un seul clic : on branche le disque externe, on double clique sur une icone et ça sauvegarde sans poser de questions !).

Bref, je trouve ces solutions trop complexes, et elles consomment toutes je trouve beaucoup trop de RAM pour leur « agent ».

J’ai donc remis le nez dans les solutions existantes, et je me suis arrêté sur… rsync ! Simple à configurer (on indique le répertoire source, la destination, et les éventuelles quelques options que l’on souhaite), il sait faire de la sauvegarde distante et via un canal chiffré sur n’importe quel serveur SSH, il ne consomme absolument aucune RAM en dehors des phases de sauvegarde puisqu’il n’est pas lancé. Enfin, on peut soit faire de la sauvegarde automatique (via les fonctions de tâche planifiées : planificateur de tâches sous Windows, cron sous Linux like), soit de la sauvegarde manuelle (double-clique sur une icone qui lance le script).

Chez moi, ma machine est sauvegardée sur mon NAS avec rsync, puis chaque nuit, mon serveur Raspberry Pi récupère ces data sur le NAS pour les envoyer en ligne sur mon compte Hubic, toujours avec rsync. Ça fonctionne bien, même si évidement la première sauvegarde prend du temps (plusieurs jours, on envoie pas comme ça des dizaines de Go sur une ligne ADSL…).

Sous Windows, j’ai recours à cwRsync.

Lenteur avec VNC

26 août 2013

J’ai récemment déménagé à 800 km de ma famille, et avant mon départ, j’ai installé sur leurs machines UltraVNC pour me permettre de les dépanner (j’ai également découvert Ultra VNC Simple Clic, une version du serveur qui se connecte sur le client lorsque l’on clique dessus. L’avantage, c’est qu’il n’y a aucune config à faire côté client, pas de redirection de port dans les box notamment. L’exécutable UVNC SC contient les informations qui permettent de joindre ma machine sur laquelle s’exécute le client VNC ne mode écoute. C’est de mon côté que les redirections de ports sont paramétrées. Il suffit que je donne le lien vers mon exécutable configuré, exécutable hébergé sur mon site Web, et en un clic et aucune config du côté serveur, je peux prendre la main sur la machine distante, magique et pratique pour prendre la main sur une nouvelle machine par exemple !).

UltraVNC

UltraVNC

Bref, sur au moins 2 machines, la prise à distance (que ça soit via VNC Server ou via VNC SC) était quasi inutilisable car l’image de la machine distante ne se rafraîchissait pas de mon côté (j’était obligé de forcer le rafraîchissement via la fonction idoine de VNC Viewer, et même via ce biais, ça ne se rafraîchissait pas rapidement). Le bug est apparu sur Windows XP et Windows 7, j’imagine donc que c’est indépendant des versions de Windows.

Le problème vient en fait du driver de capture vidéo de VNC qui gère mal l’acquisition sur des affichages paramétrés en 24 ou 32 bits. La solution est donc de modifier le paramétrage de l’affichage de la machine distante en la diminuant sur 16 bits. A partir de la, tout est fluide chez moi.

Retour OVH ADSL

29 mars 2013

J’ai récemment déménagé dans la région de Bordeaux pour mon stage de fin d’études. J’avais entendu parler du FAI OVH, et comme la région de Bordeaux fait partie des quelques zones françaises dégroupées par le FAI, j’ai décidé de sauter le pas. Par rapport à mon ancien FAI (SFR), ce qui m’as fait sauter le pas sont les élements suivantes

  • Pas de TV ADSL que je n’utilisait presque pas
  • L’IP fixe
  • Les engagements sur la neutralié du net proné par OVH. J’en ai ras le bol de ces FAI qui brident différents services (le cas de Youtube chez Free est le plus médiatique, mais le soucis existait aussi chez SFR, il m’était impossible de regarder des vidéo dans une qualité correcte, pourtant, j’avais 1,5 Mo/s en descente…)
  • Et enfin, un tarif pas plus cher que la concurrence, voir moins cher (moins de 30€ TTC alors qu’il m’en coûtait près de 35€ chez SFR)

En arrivant sur Bordeaux, j’avais donc plusieurs solutions :

  1. Mon immeuble est câblé par Numéricable, on nous annonce un débit de 100 Mbps mais dans la réalité, le débit réel de connexion est de 30 Mbps dans l’immeuble, donc pas beaucoup plus interessant que l’ADSL (quoi que on serait mieux positionné en terme de débitant montant). Et puis Numéricable n’est absolument pas neutre, ils interdisent notamment l’auto-hébergement dans leurs CGV et on mis en place des mesures techniques pour le rendre effectivement impossible (sauf à les contourner avec des ruses de sioux)
  2. SFR : comme je le disais, j’ai eu des soucis de débit sur certains sites avec eux, et surtout pas d’IP fixe donc exit
  3. Free : IP fixe disponible mais gros soucis quand à la neutralité du net avec eux… je ne serais pas client Internet chez eux tant qu’ils n’auront pas clarifié la situation
  4. Restait donc OVH qui remplissait tous mes critères, et mon petit côté baroudeur m’a motivé pour tester ce FAI récemment arrivé sur le marché

Bref, je vais souscrire sur le net. Je dispose de l’ancien numéro de fixe des précédents locataires, ça sera donc une activation de ligne sur numéro existant. J’adore la page de test d’OVH qui indique le débit maximum théorique de la ligne, mais aussi et surtout les statistiques qui indiquent que le débit dépend de la qualité réelle de la ligne. Je peux donc espérer dans le meilleur des cas un peu plus de 18 Mbps ATM (5% des cas), mais que j’ai plus de chance d’avoir un débit de l’ordre de 13,35 Mbps ATM (50% des cas). Un réel effort de transparence. Les autres FAI devraient prendre de la graine et ce genre de fiche technique devrait être obligatoire. Voici quelques screen de cette page technique :

Récapitulatif de la ligne

Récapitulatif de la ligne

Les débits théoriques

Les débits théoriques

Estimation des débits réels

Estimation des débits réels

Les liens OVH chez moi

Les liens OVH chez moi

Un effort de transparence que je salue donc. Bref, je souscrit en ligne sur numéro inactif un jeudi dans la soirée (vers 21h). On m’annonce en fin de procédure un délais de création de ligne de 3 à 21 jours. Je laisse donc l’affaire de coté. Mon déménagement à lieu le samedi suivant, entre le chargement du camion, la route et le déchargement, je n’ai pas vraiment le temps d’y penser. Le dimanche soir, je me dit que je devrais connecter mon modem Netgear sur la prise, ainsi, je verrai immédiatement lorsque la ligne sera active. Je branche donc le tout 3 jours après la commande. Nous sommes dimanche, il est 18h, le modem démarre… puis se synchronise en quelques secondes. Je me connecte à l’interface du modem, incrédule. Le modem est bel est bien synchronisé, mais ne parvient pas à se connecter. Je vérifie les paramètres utilisés par OVH depuis ma connexion 3G, je switch l’encapsulation du modem de VC vers LLC, reboot le routeur et… magie, ça se connecte ! Une connexion ultérieure à mon manager OVH m’indiquera que la ligne a été crée le 25 janvier, le vendredi donc. C’est ce qu’on appel être réactif !

Le modem est synchronisé à 13 Mbps, soit pile poil le débit indiqué dans 50% des cas, ma ligne est donc « standard », pas de surprises de ce côté la. Je reçoit la notification d’envoi du modem OVH le lundi, colis reçu dans mon point relais le 29 janvier. Je vais le chercher rapidement, puis connecte le modem à la ligne et mon téléphone fixe à cette « box » (en fait un modem-routeur Technicolor TG788vn). Immédiatement, la ligne téléphonique est fonctionnelle. C’est du SIP, mais OVH ne fournit pas les identifiants. Une astuce existe pour les récupérer, pour l’avoir testée, elle fonctionne très bien, mais ça reste du bricolage (les CGV spécifient en fait qu’il est interdit d’utiliser les lignes SIP comprises dans le package d’une autre connexion que la connexion fournie par OVH). Bonne surprise avec ce modem par contre, il synchronise plus haut que mon Netgear, je suis à 16 Mbps, c’est toujours ça de pris !

OVH fournit en réalité 2 lignes SIP dans l’abonnement. Très pratique je trouve, personnellement, j’ai fait apparaître mon nom dans l’annuaire sur l’une des lignes, et celui de ma copine sur l’autre. Le tout arrive sur le même téléphone. Cela permet à un éventuel correspondant de nous trouver tous les 2 dans l’annuaire.

La connexion est très stable, aucunes désynchronisations de constatée à ce jour en 2 mois de fonctionnement. Par ailleurs, le manager OVH offre une transparence totale puisque l’on peut suivre heure par heure (avec des beaux graphiques), le débit montant et descendant de la ligne, la vitesse de synchronisation et le ping. Je regrette par contre l’interface du routeur fourni, plutôt brouillonne et assez peu clair. On arrive cependant à faire tout ce que l’on souhaite une fois la logique du bouzin comprise.

Pour résumer rapidement :

J’ai aimé :

  • La rapidité d’installation (1 jour ouvrable pour créer la ligne, 3-4 jours ouvrables pour recevoir le modem)
  • La transparence à la souscription vis à vis du débit promis ! Tous les autres FAI devraient en prendre de la graine, voir cela devrait devenir une obligation légale à défaut d’action volontaire des FAI !
  • L’IP fixe avec possibilité de configurer le reverse DNS
  • La compatibilité IPv4 et IPv6
  • Le débit de synchronisation élevé avec le modem fourni
  • La possibilité d’avoir un numéro de fax compris dans l’offre (offre ecofax d’OVH). Ça n’est plus très utile ni vital de nos jours, mais ça peut dépanner à quelques occasions.
  • Le VDSL Ready, j’espère pouvoir en profiter lorsque l’ARCEP l’autorisera !

J’ai moins aimé

  • Le fait qu’OVH ne communique pas les identifiants SIP, c’est dommage. Avec comme corollaire l’obligation de passer par leur modem si on ne veux pas violer les CGV.
  • L’interface d’administration du modem fourni, plutôt décevante. Très brouillonne (et pas sécure, par défaut aucun mot de passe pour accéder à l’admin… dommage quand on se destine au monde pro)
  • L’interface de gestion (manager OVH) est parfois un peu lente bien que très complète
  • J’ai trouvé un peu dommage l’engagement de 1 an alors que tous les concurrents sont passés sans engagements. Ceci dit, une fois la fin d’engagement atteint, on ne doit plus rien à OVH en cas de résiliation.
  • La nécessité d’activer manuellement les lignes VoIP, ça n’est pas rédhibitoire, mais pour quelqu’un qui ne touche pas nécessairement à la technique ça n’est pas forcément intuitif.
  • L’absence de bouquet TV. Nous ne sommes pas très consommateurs de télé, donc cela ne devrait pas nous manquer mais ça reste un point à considérer pour ceux qui profitent beaucoup de leur offre TV ADSL.

Bref, pour résumer, je suis pour le moment très content de ce choix !

Linkage Qt sous Visual Studio : libgles_cm.lib

11 décembre 2011

J’ai acquis récemment une nouvelle machine pour le développement. Je fais notamment du développement sous Visual Studio 2008 avec Qt, grâce à l’add-in Qt pour Visual Studio. J’ai donc importé mes projets après avoir réinstallé l’ensemble de mes outils. A la première compilation, l’erreur suivante survient lors de l’étape de l’édition des liens :

LINK : fatal error LNK1181: impossible d'ouvrir le fichier en entrée 'libgles_cm.lib'

Après enquête, la solution est la suivante : sous Visual Studio : menu Projet –> Propriétés du projet –> Propriété de configuration (barre latérale à droite) –> Editeur de liens –> Entrée –> supprimer la bibliothèque problématique (libgles_cm.lib) dans la zone « Dépendances supplémentaires ».

Cette bibliothèque n’était pas présente dans mon projet initial, j’ignore donc pourquoi cette dépendance à été ajoutée de façon automatique et à mon insu… Il s’agit a priori d’une bibliothèque OpenGL. La seule différence entre les deux configuration des machines étant le passage de Qt 4.6.3 à 4.6.4.

Générer un dégradé en arc-en-ciel

3 novembre 2011

Pour un projet personnel (dont je reparlerais certainement plus tard sur ce blog), j’ai eu besoin de générer des points de couleur en fonction de la position de la valeur du point au sein d’un ensemble. Je souhaitais avoir quelque chose de continu, c’est à dire que 2 points ayant une valeur proche aient une couleur proche, et couvrir la plus large gamme possible de couleur, l’idéal étant d’avoir quelque chose qui se rapproche d’un arc en ciel.

Pour résumer, voici mes contraintes :

  • une variation continue des couleurs (autrement dit, hors de question de faire un saut du jaune au rouge par exemple si 2 points ont des valeurs voisines, chose que l’on obtient en général avec des algorithmes plus simplistes)
  • couvrir la plus large gamme possible de couleurs (pour résumer, je veux du rouge, du orange, du jaune, du vert, du bleu, du violet…)

C’est un problème d’apparence simple, mais qui nécessite d’être correctement modélisé pour parvenir à ses fins. Une simple étude du système RGB permet d’en trouver une solution. Traçons le graph des composantes rouges (R), vertes (V) et bleues (B) des couleurs ordonnées de l’arc en ciel. On obtient quelque chose comme ceci (on a en x les « numéro » des couleurs et en y la valeur entre 0 et 255 de chaque composante RGB. Les pastilles aux bases et aux sommets permettent de représenter la couleur résultante) :

RGB componant graphic

Graphique des composantes RVB

On voit ici que l’idée de l’algorithme est de ne faire varier qu’une seule composante à la fois.

Avec ce graphique, il est aisé de donner les fonctions résultantes des composantes R, V et B, qui sont de simple fonctions du premier degré, à définir par parties (l’objectif étant de d’avoir les valeurs de R, V et B sur l’intervalle [0;255], en ne faisant varier qu’une seule composante à la fois) :

  • Pour la composante rouge :
  (r) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 255 & :r= & 255 \\  \textrm{si } 255 \le x < 510 & :r= & 510-x \\  \textrm{si } 510 \le x < 1020 & :r= & 0 \\  \textrm{si } 1020 \le x \le 1275 & :r= & x-1020 \\  \textrm{si } 1275 \le x \le 1530 & :r= & 255 \\  \end{array}  \right.
  • Pour la composante verte :
  (v) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 255 & :v= & x \\  \textrm{si } 255 \le x < 765 & :v= & 255 \\  \textrm{si } 765 \le x < 1020 & :v= & 1020-x \\  \textrm{si } 1020 \le x \le 1530 & :v= & 0 \\  \end{array}  \right.
  • Pour la composante bleue :
  (b) \left\{  \begin{array}{lrl}  \textrm{si } 0 \le x < 510 & :b= & 0 \\  \textrm{si } 510 \le x < 765 & :b= & x-510 \\  \textrm{si } 765 \le x < 1275 & :b= & 255 \\  \textrm{si } 1275 \le x \le 1530 & :b= & 1530-x \\  \end{array}  \right.

Dans toutes ces formules, x représentant le « numéro » (ou l’indice) de la couleur que l’on souhaite obtenir. Si on a une valeur y comprise entre dans l’intervalle [y_{min};y_{max}], on peut obtenir x par la formule x = \dfrac{1530}{y_{max}-y_{min}} \times y.

A noter qu’ici, j’ai opté pour un intervalle de [0;1530] car il représente 6 times 255 soit le plus grand nombre de couleurs que l’on puisse obtenir avec cet algorithme (au delà, une même couleur pourrait avoir 2 numéros, ce qui serait bien sur inutile). Il est bien sur possible d’adapter cet algorithme de façon à avoir un nombre de nuances plus réduits (100 par exemple).

Cette algorithme produit ces variations (je vous présente ici la gamme complète des couleurs que peut générer l’algo) :

Dégradé généré par l'algorithme présenté

Dégradé généré par l’algorithme présenté

Passons au code, voici le code qui permet de générer les codes RGB correspondants aux valeurs. La fonction prend en argument l’intervalle et la valeur à partir de laquelle il faut  déterminer la couleur. Comme c’est du C++, la fonction retourne simplement un objet QColor (objet Qt).

QColor calcColor(double interval, double value){
QColor color;
int x = (1530/interval)*value;
int r;
int g;
int b;
if(x>=0 && x<255){
r = 255;
g = x;
b = 0;
}
if(x>=255 && x<510){
r = 510-x;
g = 255;
b = 0;
}
if(x>=510 && x<765){
r = 0;
g = 255;
b = x-510;
}
if(x>=765 && x<1020){
r = 0;
g = 1020-x;
b = 255;
}
if(x>=1020 && x<1275){
r = x-1020;
g = 0;
b = 255;
}
if(x>=1275 && x<=1530){
r = 255;
g = 0;
b = 1530-x;
}
color.setRgb(r, g, b);
return color;
}

A noter que cet algorithme devrait également fonctionner dans d’autres espaces de couleur que RGB (en CMY, cyan/magenta/jaune, notamment).

Utilisation de GeographicLib sous Visual Studio C++

21 octobre 2011

Je vous livre ici la solution à un problème qui m’a donné pas mal de fil à retordre : l’utilisation de la librairie GeographicLib (une bibliothèque de calcul de coordonnés géographique, notamment du « direct geodesic problem« , qui consiste à calculer une positon sur la Terre en connaissant une positon d’origine, une distance et un azimut(cap). Cette bibliothèque est également capable de faire des conversions entre les différents systèmes géodesiques existants). Je précise que la version utilisées ici est la 1.14

Mes problèmes furent multiples :

  1. Faire fonctionner la bibliothèque sous Visual Studio (2008 pour mon cas, mais les soucis auraient probablement étés les mêmes sous VS2005 ou VS2010)
  2. Comprendre comment elle fonctionne
  3. Réussir à compiler, en l’occurrence, j’avais des erreurs sur l »édition des liens (linker).

1) Installer et faire fonctionner la librairie sous VC2008

Pas de grosses difficultés ici, il faut juste ne pas se faire piéger par la doc qui présente (à ce jour) une erreur. Donc :

  • dans les paramètres du projet (Projet -> Propriété de…),
  • se rendre dans Propriété de configuration ->C/C++->Général->Autres répertoire include et renseigner : C:Program FilesGeographicLib-1.14include.
  • Dans Éditeur de liens->Général-> Répertoires de bibliothèques supplémentaires, renseigner C:Program FilesGeographicLib-1.14lib et non C:Program FilesGeographicLib-1.14include comme indiqué dans la documentation
  • Dans Éditeur de liens->Entrée->Dépendances supplémentaires, ajouter Geographic.lib
Je vais tâcher de les contacter pour leur indiquer cette erreur.

2) Comprendre comment elle fonctionne

Ici, j’ai eu des difficultés, car c’est l’une des premières fois que j’utilise une bibliothèque tierce (hors Qt, superbe doc,  et SDK matériels, qui ont souvent eut aussi une doc assez explicite avec des exemples), et assez peu utilisée. J’ai donc eu un mal terrible à trouver des exemples sur Internet. Lors de mes premiers essais, j’ai ainsi codé ainsi :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
Geodesic::Direct(lat1, lon1, azi1, s12, &amp;lat2, &amp;lon2);

Ce qui générait à la compilation des erreurs du genre :

.main.cpp(295) : error C2665: 'GeographicLib::Geodesic::Direct' : aucune des 6 surcharges n'a pu convertir tous les types d'arguments
.GeographicLib/Geodesic.hpp(350): peut être 'GeographicLib::Math::real GeographicLib::Geodesic::Direct(GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real,GeographicLib::Geodesic::real &amp;,GeographicLib::Geodesic::real &amp;) throw() const'

Je vous livre donc la syntaxe correcte qui est :

double lat1 = 46.908848;
double lon1 = 6.327472;
double azi1 = 59.16;
double s12 = 6216.28;
double lat2;
double lon2;
const Geodesic&amp; g = Geodesic::WGS84;
g.Direct(lat1, lon1, azi1, s12, lat2, lon2);

3) Parvenir à compiler/linker

A la compilation, enfin, à l’édition des liens pour être précis, j’obtenais les erreurs suivantes :

1>Édition des liens en cours...
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(Geodesic.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_MSC_VER=1600' non valide rencontrée ; ignorée
1>Geographic.lib(GeodesicLine.obj) : warning LNK4229: directive '/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0' non valide rencontrée ; ignorée
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::erase(unsigned int,unsigned int)" (?erase@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@II@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: static unsigned int __cdecl std::char_traits<char>::length(char const *)" (?length@?$char_traits@D@std@@SAIPBD@Z) déjà défini(e) dans Geographic.lib(Geodesic.obj)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xlength_error(char const *)" (__imp_?_Xlength_error@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xlen(void)const " (?_Xlen@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)
1>Geographic.lib(Geodesic.obj) : error LNK2019: symbole externe non résolu "__declspec(dllimport) void __cdecl std::_Xout_of_range(char const *)" (__imp_?_Xout_of_range@std@@YAXPBD@Z) référencé dans la fonction "public: void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Xran(void)const " (?_Xran@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEXXZ)

Après pas mal de lecture sur le net et avoir bidouillé a peu près tous les paramètres de l’éditeur de liens de Visual Studio, je me suis résolu à recompiler moi même la librairie. Pour cela, il faut télécharger le zip du code source de GeographicLib (ici par exemple). Les développeurs ont même eu l’idée de fournir des fichiers projets pour VS2005 (GeographicLib-vc8.sln), 2008 (GeographicLib-vc9.sln) et 2010 (GeographicLib-vc10.sln) (répertoire windows de l’archive). J’ouvre donc le fichier qui correspond à ma version de Visual Studio et j’ai compilé la bibliothèque en mode Release. Il en ressort un beau fichier .lib d’environ 1800 ko (contre 1300 ko pour celui fourni). Après remplacement du fichier Geographic.lib fourni par ce nouveau fichier, la compilation et l’édition des liens se déroule à merveille, et la bibliothèque semble fonctionner.

Dans mon immense bonté, je vous fourni cette librairie compilée avec Visual Studio C++ 2008 (je ne sais pas si elle fonctionne avec VC2005 ou VC2010) : Geographic.lib.

DependencyWalker, explorer les dépendances d’une application

17 octobre 2011

Bien souvent, lorsque l’on développer une application, tout se passe bien jusqu’au moment ou l’on souhaite la faire fonctionner sur une autre machine. Bien souvent, lors de cette étape, on fait le douloureux constat que l’application ne démarre même bien, en général, on obtient juste un message indiquant qu’il y a un problème et que l’application ne peut démarrer, avec pour seule suggestion de remède une réinstallation, ce qui bien sur est inutile.

Dans la plupart des cas, on est face à un problème de dépendances avec des bibliothèques présentes sur la machine de développement (installées au bon endroit lors de l’installation des outils de développement), et absentes des systèmes « classiques ».

Il est parfois aisé de savoir quelles sont les librairies utilisées, en fonction des SDK et autres Framwork utilisés, mais parfois, ça n’est pas si simple.

Dans ces cas, il existe des logiciels capables d’analyser un fichier binaire pour en retirer les dépendances. Dependency Walker fait parti de ceux-ci.

Fenêtre principale de Dependency Walker

Fenêtre principale de Dependency Walker

La simple ouverture d’un exécutable dans ce logiciel vous permettra de voir instantanément de quelles DLL à besoin le logiciel pour fonctionner. Une simple recherche sur la machine de dev devrait vous permettre de mettre la main sur la DLL manquante afin de la joindre à votre programme pour que tout rentre dans l’ordre.

Un certain travail de tri et de sélection des informations restera cependant nécessaire car comme le montre la capture ci-dessus, l’intégralité des DLL et dépendances sont affichées, il faudra donc différencier les DLL systèmes (toujours présentes sous Windows et qu’il ne sera donc pas nécessaire d’importer) des DLL applicatives qu’il faudra fournir.

InnoSetup : ajouter les DLL Visual C++

14 octobre 2011

Si vous développez à l’aide de Microsoft Visual Studio, vos programmes nécessitent, pour fonctionner sur une machine quelconque, de diposer des bibliothèques suivantes (DLL de VC++ 2008) :

  • mfc90.dll
  • msvcr90.dll
  • msvcp90.dll
  • atl90.dll
  • vcomp.dll
L’absence des ces librairies est un cas fréquent de non fonctionnement des programmes développés par vos soins, le syptôme est alors l’apparition d’un message du type : « Cette application n’a pas pu démarrer car la configuration de l’application est incorrecte. Réinstaller l’application pourrait résoudre ce problème.« .

 

La solution est d’installer le package de DLL « Microsoft Visual C++ 2008 Redistribuable Package » (téléchargeable sur le site de Microsoft : vcredist_x86.exe ou vcredist_x64.exe pour la version 64 bits).
Mais voila, si vous distribuez vos applications avec un installeur comme Inno Setup, cela impose à vos utilisateurs de télécharger ce package de DLL en sus, avec le risque qu’ils passent à coté et qu’il ne parviennent donc pas à lancer votre application.
La solution la plus simple est donc d’intégrer vcredist dans l’installeur InnoSetup de façon à ce que son installation soit automatique et transparente pour vos utilisateurs. Voici comment procéder :
  1. Téléchargez vcredist_x86.exe sur le site de Microsoft (voir lien plus haut) et enregistrez le dans un sous dossier ./bin/ de votre projet
  2. Ouvrez votre projet Inno Setup (je suppose ici que celui-ci est d’hors et déjà créé et que l’emplacement des autres fichiers de votre projet sont déjà renseignés)
  3. Dans la section [files] de votre projet, ajoutez ceci :
    Source: "{src}binvcredist_x86.exe"; DestDir: "{app}bin"; Flags: deleteafterinstall
  4. Dans la section [Run], ajoutez :
    Filename: "{app}binvcredist_x86.exe"; Parameters: "/q:a /c:""VCREDI~3.EXE /q:a /c:""""msiexec /i vcredist.msi /qn"""" """; WorkingDir: "{app}bin"; StatusMsg: Installing VCREDIST...
Il faudra bien sur adapter ces commandes si vous intégrez la version 64 bits.
Vous devriez également pouvoir inclure les 2 versions (32 et 64 bits) en jouant avec les options et conditions disponibles dans InnoSetup.

 

Grâce à cette technique, l’installation se fera de façon totallement transparente, l’utilisateur n’ayant même pas besoin de valider les différentes étapes de l’installer du package Visual Studio VC++ Redistribuable (il voit juste une barre de progression qui se remplit sans poser de questions).

 

Note : ce billet traite plus particulièrement de la version 2008 de Visual Studio (celle que j’utilise), mais cette astuce est transposable telle qu’elle pour les autres versions de VS (je pense notamment aux versions 2005 et 2010), il suffit de télécharger les pack vcredist correspondants à ces versions sur le site de Microsoft.