web-dev-qa-db-fra.com

Comment savoir si le code .NET est exécuté par le concepteur Visual Studio

Je reçois des erreurs dans mon code lorsque j'ouvre un formulaire Windows Forms dans le concepteur de Visual Studio. Je voudrais créer une branche dans mon code et effectuer une initialisation différente si le formulaire est ouvert par le concepteur que s'il est exécuté pour de vrai.

Comment puis-je déterminer au moment de l'exécution si le code est exécuté dans le cadre de l'ouverture du concepteur par le formulaire?

55
Zvi

Pour savoir si vous êtes en "mode conception":

  • Les composants (et contrôles) Windows Forms ont une propriété DesignMode .
  • Les contrôles Windows Presentation Foundation doivent utiliser la propriété jointe IsInDesignMode .
49
Roger Lipscombe
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
  // Design time logic
}
47
NET3

La propriété Control.DesignMode est probablement ce que vous recherchez. Il vous indique si le parent du contrôle est ouvert dans le concepteur.

Dans la plupart des cas, cela fonctionne très bien, mais il y a des cas où cela ne fonctionne pas comme prévu. Tout d'abord, cela ne fonctionne pas dans le constructeur de contrôles. Deuxièmement, DesignMode est faux pour les contrôles "petit-enfant". Par exemple, DesignMode sur les contrôles hébergés dans un UserControl renvoie false lorsque le UserControl est hébergé dans un parent.

Il existe une solution de contournement assez simple. Ca fait plutot comme ca:

public bool HostedDesignMode
{
  get 
  {
     Control parent = Parent;
     while (parent!=null)
     {
        if(parent.DesignMode) return true;
        parent = parent.Parent;
     }
     return DesignMode;
  }
}

Je n'ai pas testé ce code, mais cela devrait fonctionner.

19
JohnV

L'approche la plus fiable est:

public bool isInDesignMode
{
    get
    {
        System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
        bool res = process.ProcessName == "devenv";
        process.Dispose();
        return res;
    }
}
15
GWLlosa

La façon la plus fiable de le faire est d'ignorer la propriété DesignMode et d'utiliser votre propre indicateur défini au démarrage de l'application.

Classe:

public static class Foo
{
    public static bool IsApplicationRunning { get; set; }
}

Program.cs:

[STAThread]
static void Main()
{
     Foo.IsApplicationRunning = true;
     // ... code goes here ...
}

Vérifiez ensuite le drapeau lorsque vous en avez besoin.

if(Foo.IsApplicationRunning)
{
    // Do runtime stuff
}
else
{
    // Do design time stuff
}
13
Marty Dill

L'approche devenv a cessé de fonctionner dans VS2012 car le concepteur a maintenant son propre processus. Voici la solution que j'utilise actuellement (la partie 'devenv' est laissée là pour l'héritage, mais sans VS2010 je ne suis pas en mesure de tester cela cependant).

private static readonly string[] _designerProcessNames = new[] { "xdesproc", "devenv" };

private static bool? _runningFromVisualStudioDesigner = null;
public static bool RunningFromVisualStudioDesigner
{
  get
  {
    if (!_runningFromVisualStudioDesigner.HasValue)
    {
      using (System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess())
      {
        _runningFromVisualStudioDesigner = _designerProcessNames.Contains(currentProcess.ProcessName.ToLower().Trim());
      }
    }

    return _runningFromVisualStudioDesigner.Value;
  }
}
5
Johny Skovdal

J'ai eu le même problème dans Visual Studio Express 2013. J'ai essayé de nombreuses solutions suggérées ici, mais celle qui a fonctionné pour moi était ne réponse à un fil différent , que je répéterai ici au cas où le lien est jamais cassé:

protected static bool IsInDesigner
{
    get { return (Assembly.GetEntryAssembly() == null); }
}
4
GeeC
using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
    bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv";
    return inDesigner;
}

J'ai essayé le code ci-dessus (ajouté une instruction using) et cela échouait à certaines occasions pour moi. Test dans le constructeur d'un contrôle utilisateur placé directement dans un formulaire avec le chargement du concepteur au démarrage. Mais fonctionnerait dans d'autres endroits.

Ce qui a fonctionné pour moi, dans tous les pays, c'est:

private bool isDesignMode()
{
    bool bProcCheck = false;
    using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
    {
        bProcCheck = process.ProcessName.ToLower().Trim() == "devenv";
    }

    bool bModeCheck = (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime);

    return bProcCheck || DesignMode || bModeCheck;
}

Peut-être un peu exagéré, mais cela fonctionne, donc c'est assez bon pour moi.

Le succès dans l'exemple noté ci-dessus est le bModeCheck, donc probablement le DesignMode est excédentaire.

3
Martin
/// <summary>
/// Are we in design mode?
/// </summary>
/// <returns>True if in design mode</returns>
private bool IsDesignMode() {
    // Ugly hack, but it works in every version
    return 0 == String.CompareOrdinal(
        "devenv.exe", 0,
        Application.ExecutablePath, Application.ExecutablePath.Length - 10, 10);
}
3
pintergabor

C'est hack-ish, mais si vous utilisez VB.NET et lorsque vous exécutez à partir de Visual Studio My.Application.Deployment.CurrentDeployment sera Nothing, car vous ne l'avez pas encore déployé. Je ne sais pas comment vérifier la valeur équivalente en C #.

2
Joel Coehoorn
System.Diagnostics.Debugger.IsAttached
1
Bob King

Je ne sais pas si l'exécution en mode débogage compte comme réelle, mais un moyen simple consiste à inclure une instruction if dans votre code qui vérifie System.Diagnostics.Debugger.IsAttached.

1
Adrian Anttila

Lors de l'exécution d'un projet, son nom est ajouté avec ".vshost".

Donc, j'utilise ceci:

    public bool IsInDesignMode
    {
        get
        {
            Process p = Process.GetCurrentProcess();
            bool result = false;

            if (p.ProcessName.ToLower().Trim().IndexOf("vshost") != -1)
                result = true;
            p.Dispose();

            return result;
        }
    }

Ça marche pour moi.

1
Andy

Si vous avez créé une propriété dont vous n'avez pas du tout besoin au moment de la conception, vous pouvez utiliser l'attribut DesignerSerializationVisibility et la définir sur Masqué. Par exemple:

protected virtual DataGridView GetGrid()
{
    throw new NotImplementedException("frmBase.GetGrid()");
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int ColumnCount { get { return GetGrid().Columns.Count; } set { /*Some code*/ } }

Il a cessé de planter Visual Studio à chaque fois que je modifiais le formulaire avec NotImplementedException() et essayais d'enregistrer. Au lieu de cela, Visual Studio sait que je ne veux pas sérialiser cette propriété, il peut donc l'ignorer. Il n'affiche qu'une chaîne étrange dans la zone des propriétés du formulaire, mais il semble sûr de l'ignorer.

Veuillez noter que cette modification ne prend effet qu'après la reconstruction.

1
Bolek

Nous utilisons le code suivant dans UserControls et il fait le travail. L'utilisation de DesignMode uniquement ne fonctionnera pas dans votre application qui utilise vos contrôles utilisateur personnalisés comme indiqué par les autres membres.

    public bool IsDesignerHosted
    {
        get { return IsControlDesignerHosted(this); }
    }

    public bool IsControlDesignerHosted(System.Windows.Forms.Control ctrl)
    {
        if (ctrl != null)
        {
            if (ctrl.Site != null)
            {
                if (ctrl.Site.DesignMode == true)
                    return true;
                else
                {
                    if (IsControlDesignerHosted(ctrl.Parent))
                        return true;
                    else
                        return false;
                }
            }
            else
            {
                if (IsControlDesignerHosted(ctrl.Parent))
                    return true;
                else
                    return false;
            }
        }
        else
            return false;
    }
1
Kalle

Vous vérifiez la propriété DesignMode de votre contrôle:

if (!DesignMode)
{
//Do production runtime stuff
}

Notez que cela ne fonctionnera pas dans votre constructeur car les composants n'ont pas encore été initialisés.

1
Ryan Steckler
System.ComponentModel.Component.DesignMode == true
1
ShuggyCoUk

En voici un autre:

        //Caters only to thing done while only in design mode
        if (App.Current.MainWindow == null){ // in design mode  }

        //Avoids design mode problems
        if (App.Current.MainWindow != null) { //applicaiton is running }
0
John Peters

Si vous êtes dans un formulaire ou un contrôle, vous pouvez utiliser la propriété DesignMode:

if (DesignMode)
{
        DesignMode Only stuff
}
0
Akselsson

J'ai trouvé que la propriété DesignMode était boguée, au moins dans les versions précédentes de Visual Studio. Par conséquent, j'ai créé la mienne en utilisant la logique suivante:

Process.GetCurrentProcess().ProcessName.ToLower().Trim() == "devenv";

Une sorte de hack, je sais, mais ça marche bien.

0
Eyvind

Après avoir testé la plupart des réponses ici, malheureusement rien n'a fonctionné pour moi (VS2015). J'ai donc ajouté une petite touche à réponse de JohnV , ce qui n'a pas fonctionné, car DesignMode est une propriété protégée dans la classe Control.

J'ai d'abord créé une méthode d'extension qui renvoie la valeur de la propriété DesignMode via Reflection:

public static Boolean GetDesignMode(this Control control)
{
    BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static;
    PropertyInfo prop = control.GetType().GetProperty("DesignMode", bindFlags);
    return (Boolean)prop.GetValue(control, null);
}

puis j'ai fait une fonction comme JohnV:

public bool HostedDesignMode
{
    get
    {
        Control parent = Parent;
        while (parent != null)
        {
            if (parent.GetDesignMode()) return true;
            parent = parent.Parent;
        }
        return DesignMode;
    }
}

C'est la seule méthode qui a fonctionné pour moi, évitant tous les dégâts de ProcessName, et bien que la réflexion ne doive pas être utilisée à la légère, dans ce cas, elle a fait toute la différence! ;)

MODIFIER:

Vous pouvez également faire de la deuxième fonction une méthode d'extension comme celle-ci:

public static Boolean IsInDesignMode(this Control control)
{
    Control parent = control.Parent;
    while (parent != null)
    {
        if (parent.GetDesignMode())
        {
            return true;
        }
        parent = parent.Parent;
    }
    return control.GetDesignMode();
}
0
Gpower2

Pour résoudre le problème, vous pouvez également coder comme ci-dessous:

private bool IsUnderDevelopment
{
    get
    {
        System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
        if (process.ProcessName.EndsWith(".vshost")) return true;
        else return false;
    }

}
0