Lost in the matrix

C/C++/C#/Java, Multithreading


La FAXCOMLib est un bon moyen pour envoyer des fax à partir d'une application en C#/.Net. Toutefois, il faut savoir qu'elle utilise le lecteur PDF par défaut de l'utilisateur de son contexte. Ainsi, le comportement de la FAXCOMLib peut varier en fonction de ce lecteur. En effet, depuis la version 10 de Acrobat Reader, les fax envoyés à partir de la FAXCOMLib ne  partent plus.

Lors de l'envoie d'un fax, une exception "System.Runtime.InteropServices.COMException (0x80070102):Operation failed" est lancée au bout d'un certain temps. Grâce à mon précédent article "Interpréter une exceptionCOM sous Windows", nous savons qu'il s'agit d'un "timeout". Ce "timeout" est dû au fait qu'Acrobat Reader a changé son fonctionnement et essaie de lancer son IHM (GUI). La FAXCOMLib n'étant pas capable de gérer ce changement de protocole, elle "timeout" au bout de cinq minutes, le comportement à adopter dans cette situation.

solutions:


Parfois, il nous arrive d'utiliser des composants "Bas Niveau" dans nos applications (utilisation du fax par exemple). Cependant, du fait que le code est souvent non-managé, il est difficile d'interpréter les erreurs remontées par ces composants. Par conséquent, voici une petite astuce à connaître :


Pour notre exemple, nous allons considérer que nous avons une application en .Net et que nous utilisons le composant FAXCOMLib pour envoyer un fax. Enfin, nous allons considérer que l'exception suivante est survenue lors de l'exécution du programme :


System.Runtime.InteropServices.COMException (0x80070102): Operation failed


1) De cette exception nous allons extraire le code de l'erreur : 0x80070102


2) Puis extraire les 4 chiffres suivant le chiffre 7 : 0x80070102


3) Convertir le nombre de la base 16 (hexadecimal) à la base 10 : 258


Astuce : utiliser un site pour éffectuer la conversion, tel que :
http://www.statman.info/conversions/hexadecimal.html


4) Ouvrir un invité de commandes (cmd.exe) et taper : "net helpmsg 258"


Cette commande affiche "The wait operation timed out."

Astuce : la liste des codes d'erreur de Windows est disponible à cette adresse :
http://msdn.microsoft.com/en-us/library/ms681382(v=vs.85).aspx



Les erreurs COM sont maintenant lisibles :)

Voici, un petit hors-serie sur Steam qui, je l'espère devrait résourdre les problèmes de lenteur chez certain.


1) Fermer Steam (vérifier le cas échéant dans le gestionnaire de tâches).


2) Supprimer le fichier "ClientRegistry.blob" qui se trouve à la racine du répertoire d'installation de Steam. Exemple:
C:\Program Files (x86)\Steam\ClientRegistry.blob
Ce fichier contient entre-autres diverses informations sur votre connexion (ex: Client Bandwidth Stats)


3) Redémarrer Steam (Steam devrait vous re-demander vos identifiants, sinon recommencer à l'étape 1).


4) Relancer vos téléchargements.


1) Lancer Crystal Reports XI

2) Créer un nouveau rapport vide

3) Cliquer sur l'icône "Insérer une image"

4) Sélectionner une image arbitraire

5) Placer l'image

6) Ajouter un nouveau paramètre correspondant au chemin du fichier image

7) Ajouter un paramètre de type de "Chaîne", ici nommé "Image"

8) Clique droit sur l'image, puis cliquer sur "Mettre en forme le graphique"

9) Cliquer sur le bouton "formule" (X+2)


10) Mettre la formule "{?Image}" ou "Image" est le nom du paramètre

---
Il ne reste plus qu'a tester le modèle.

Ceci est une version très basique de la fonction Ping.
Elle ne gère pas tous les cas, mais je vais poster une version améliorée bientôt.

#include <winsock2.h>
#include <Ipexport.h>
#include <icmpapi.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

int IsPingable(const char *host, int timeout)
{
 IP_OPTION_INFORMATION ioi;
 ICMP_ECHO_REPLY       ier;
 LPHOSTENT             Host;
 WSADATA               wsaData;
 IN_ADDR               iaAddr;
 HANDLE                hIcmp;

 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
 {
  WSACleanup();
  return (0);
 }
 iaAddr.s_addr = inet_addr(host);
 if (iaAddr.s_addr == INADDR_NONE)
  Host = gethostbyname(host);
 else
  Host = gethostbyaddr((char *)&iaAddr, sizeof(IN_ADDR), AF_INET);
 if (Host == NULL)
 {
  WSACleanup();
  return (0);
 }
 hIcmp = IcmpCreateFile();
 ioi.Ttl = 255;
 ioi.Tos = 0;
 ioi.Flags = 0;
 ioi.OptionsSize = 0;
 ioi.OptionsData = NULL;
 IcmpSendEcho(hIcmp, *(DWORD *)(*Host->h_addr_list), NULL, 0, &ioi, &ier, sizeof(ICMP_ECHO_REPLY), timeout);
 IcmpCloseHandle(hIcmp);
 WSACleanup();
 return (ier.Status == 0);
}
Exemple:
int main(int argc, char **argv)
{
 printf("IsPingable : %d\n", IsPingable("clustrmaps.com", 5000));
 getchar();
 return (EXIT_SUCCESS);
}

Aujourd'hui, je suis tombé sur un problème avec le contrôle PropertyGrid, car je voulais éditer les propriétés d'un objet ainsi que ses sous-objets. Toutefois, j'ai eu quelques soucis, car la PropertyGrid ne permet pas (de base) d'éditer les sous-objets et ceux-ci apparaissent grisés.

Voici mon code:

using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication
{
    public partial class PropertyGridTest : Form
    {
        public PropertyGridTest()
        {
            InitializeComponent();
            this.propertyGrid1.SelectedObject = new Car();
        }
    }

    public class Driver
    {
        public string Name { get; set; }
        public bool HasDriverLicence { get; set; }
    }

    public class Car
    {
        public Car()
        {
            this.Driver = new Driver()
            {
                Name = "Johannes Fetz",
                HasDriverLicence = false
            };
            this.Color = Color.Red;
            this.Kind = "Sedan";
        }

        public string Kind { get; set; }
        public Color Color { get; set; }
        public Driver Driver { get; set; }
    }
}
qui donne le résultat suivant:
Après quelques recherches, j'ai trouvé comment résoudre ce problème. En effet, il suffit d'indiquer à la PropertyGrid que "Driver" est un objet "Expandable". Pour cela, il faut ajouter un using :
using System.ComponentModel;
et un attribut au dessus de la classe "Driver" :
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
public class Driver
{
Ce qui donne le résultat suivant:

Voici une petite démonstration d'une implémentation des delegates que j'ai fait en langage C :)
Dans ce code, une fonction est déclarée en locale avec un nom unique, composé du mot
"__delegate__" et du numéro de la ligne courrante (__LINE__). Puis, l'adresse est stockée
dans la variable de l'utilisateur sous forme d'un pointeur sur fonction de type "Delegate".

#include <stdio.h>

#define CONCAT2(s1, s2) s1##s2
#define CONCAT(s1, s2) CONCAT2(s1, s2)
#define NewDelegate(Ptr, Expr) void \
        CONCAT(__delegate__, __LINE__)() Expr \
        Ptr = (Delegate)&CONCAT(__delegate__, __LINE__)

typedef void (*Delegate)(void);

void    PseudoDelegateTest()
{       
        int  i;
        Delegate my_delegate;

        NewDelegate(my_delegate,
        {
           printf("i = %d\n", i);
        });

        for (i = 0; i < 5; ++i)
            my_delegate();
}

int main(int argc, char **argv)
{
  PseudoDelegateTest();
  getchar();
  return (0);
}