Category: .NET

Azure : Faire cohabiter du PHP et du .NET sur un même site, c’est possible !

azure_logo Dans Azure, le cloud de Microsoft, il est possible de faire héberger un site web qui contient des pages .NET et PHP.
Avec le recul, ça peut paraître évident. Mais j’ai été surpris au premier abord.

Dans l’onglet “Configuration” du site, il suffit de vérifier si les 2 frameworks sont activés :

azure_1

(Désolé, c’est une capture de l’ancien portail Azure, mais je ne peux pas encadrer le nouveau portail avec son UX horrible)

Du côté de Visual Studio, ça se présente ainsi, pas besoin d’installer une extension du genre PHP Tools, il suffit d’ajouter ses fichiers PHP à la solution :

azure_2

Je me suis aperçu de tout cela en implémentant un back-end web-services en C# sur ma vieille appli PHP des années 90. Et ça marche nickel !

NB : Je ne serai pas étonné qu’on puisse également ajouter du JAVA et du Python, afin d’obtenir une application web œcuménique où les langages cohabiteraient en paix.

Call a Powershell script from c# code

PowerShell logo This solution given here :
executing-powershell-scripts-from-c is fine, but only works with .NET 4.0 or above…

In my case, I needed to call a powershell script from a c# code source running under .NET 3.5.

So, this is a function that uses a Process objet to run Powershell :


public static int RunPowershellScript(string ps)
{
int errorLevel;
ProcessStartInfo processInfo;
Process process;

processInfo = new ProcessStartInfo("powershell.exe", "-File " + ps);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;

process = Process.Start(processInfo);
process.WaitForExit();

errorLevel = process.ExitCode;
process.Close();

return errorLevel;
}

This code is synchronous, and has a lack of prerequisites checks, but it can be reusable in a more elegant code 😉

Combien ça rapporte de développer un jeu pour mobiles ?

Et bien pas grand chose !

Attention, on parle d’un jeu de base sans prétention développé par un clampin sur ses heures de sommeil.

Prenons Colorseeds pour Windows Phone : il est gratuit, et rapporte quelques millièmes de centime d’euro à chaque fois qu’une publicité s’affiche (bannière en haut de l’écran de jeu).

Prenons le mois d’avril :

– Colorseeds est présent dans plus de 180 pays, et il a été mis en avant (= plus de visibilité sur le Store) environ 60 fois (dont des pays à fort potentiel comme les Etats-Unis et le Canada),

– Il a été téléchargé 8290 fois, dont 1000 en France (c’est très peu !),

– Plus d’un million de publicités ont été affichées (c’est beaucoup ! Les gens qui ont téléchargé ont beaucoup joué),

– Le CPM (“coût par mille”), c’est à dire le nombre d’euros que me rapporte 1000 publicités affichées est de : 0.05€ (pas terrible),

– Ce qui donne : 1 543 138 pub * 0.05 CPM / 1000 = 51€ environ…

Bref, il me faudrait plus d’une vingtaine de jeux pour gagner un SMIC… Ou alors investir dans de la promo massive !

pubcenter_colorseeds_avril2014

 

Pour les heureux possesseurs d’un Windows Phone, Colorseeds se télécharge ici :

Download Colorseeds for Windows Phone !

Utilisation du type de variables “Decimal”

“Decimal” a été créé pour avoir une précision plus grande, mais dans une plage de valeurs plus restreinte.

Il est préconisé dans les applications monétaires, tandis que les autres types à virgules flottantes (double, single) sont destinés aux calcules scientifiques (et ils ont une vitesse de traitement plus rapide).

Fait amusant :

Decimal numerateur = 1m;
Decimal denominateur = 3m;
Console.WriteLine(numerateur / denominateur * denominateur);

Le résultat sera 0.999999… Ceci parce que Decimal est justement trop précis !

L’utilisation de Round permettra de profiter de la précision de Decimal, tout en faisant les arrondis nécessaires. Comme cité dans cette ressource : “Le type Decimal n’élimine pas la nécessité d’arrondir. Il réduit plutôt des erreurs en raison de l’arrondi”.

Console.WriteLine(Math.Round(numerateur / denominateur * denominateur, 2));

Ceci retournera 1.00.

L’utilisation des autres flottants n’est pas conseillé. Car les erreurs d’arrondis vont plus faciement s’accumuler à fur et à mesure des calculs.

Cet exemple ci-dessous ne doit pas fausser l’opinion des développeurs :

Double numerateur = 1f;
Double denominateur = 3f;
Console.WriteLine(numerateur / denominateur * denominateur);

Le résultat sera de 1 ! Mais cela reflète simplement un manque de précision de la division avec ce type de flottants : numerateur / denominateur = 0.3333343

 

SharePoint 2010 : Workflow d’envoi de mails déclenché par un utilisateur anonyme.

Les utilisateurs anonymes ne sont pas autorisés à déclencher certains flux de travail (workflow), notamment ceux qui envoient des mails.

Prenons l’exemple d’une liste qui déclenche un workflow d’envoi de mail sur l’ajout d’un élément :

Workflow_1

Ici l’envoi de mail sera un échec, car la tâche d’envoi de mail nécessite plus de droit que ne peut avoir un utilisateur anonyme.

Pour remédier à cela, une solution serait de faire déclencher le workflow par un événement tiers :

Workflow_2

Il suffit d’insérer un event-handler qui va prendre en charge l’événement “ajout d’un élément” à la place du workflow, et qui va forcer le démarrage du workflow “à la main”.

Le code de l’event-handler pourrait ressembler à cela :

public class List_EventReceiver : SPItemEventReceiver
{
 /// <summary>
 /// Un élément a été ajouté, on lance le workflow avec privilèges.
 /// </summary>
 public override void ItemAdded(SPItemEventProperties properties)
 {
    base.ItemAdded(properties);
    
        // Exécution en élévation de privilège
    SPSecurity.RunWithElevatedPrivileges(delegate()
   {
      using (SPSite site = new SPSite("http://mon_site"))
      {
        using (SPWeb siteWeb = site.OpenWeb())
        {
          SPList list = siteWeb.Lists["Ma_Liste"];

          SPWorkflowAssociation wf = list.WorkflowAssociations.GetAssociationByName("Nom_du_Workflow", System.Globalization.CultureInfo.CurrentCulture);

          // Lancement du workflow
          site.WorkflowManager.StartWorkflow(list.GetItemById(properties.ListItemId), wf, wf.AssociationData);
        }
      }
   });
 }
}