it-swarm-es.com

Cómo saber si el diseñador de Visual Studio está ejecutando el código .NET

Estoy recibiendo algunos errores en mi código cuando abro un formulario de Windows Forms en el diseñador de Visual Studio. Me gustaría bifurcar mi código y realizar una inicialización diferente si el diseñador está abriendo el formulario que si se está ejecutando de verdad.

¿Cómo puedo determinar en tiempo de ejecución si el código se está ejecutando como parte del diseñador que abre el formulario?

55
Zvi

Para saber si estás en "modo de diseño":

  • Los componentes de Windows Forms (y los controles) tienen una propiedad DesignMode .
  • Los controles de Windows Presentation Foundation deberían usar la propiedad adjunta IsInDesignMode .
49
Roger Lipscombe
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
  // Design time logic
}
47
NET3

La propiedad Control.DesignMode es probablemente lo que estás buscando. Le dice si el padre del control está abierto en el diseñador.

En la mayoría de los casos funciona bien, pero hay casos en los que no funciona como se esperaba. Primero, no funciona en el constructor de controles. Segundo, DesignMode es falso para los controles de "nieto". Por ejemplo, DesignMode en los controles alojados en un UserControl devolverá false cuando el UserControl esté alojado en un padre.

Hay una solución bastante fácil. Es algo parecido a esto:

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

No he probado ese código, pero debería funciona.

19
JohnV

El enfoque más confiable es:

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

La forma más confiable de hacer esto es ignorar la propiedad DesignMode y usar su propia bandera que se establece en el inicio de la aplicación.

Clase:

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

Program.cs:

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

Entonces solo marca la bandera cuando la necesites.

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

El enfoque de devenv dejó de funcionar en VS2012 ya que el diseñador ahora tiene su propio proceso. Aquí está la solución que estoy usando actualmente (la parte 'devenv' se deja ahí para legado, pero sin VS2010 no puedo probar eso).

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

Tuve el mismo problema en Visual Studio Express 2013. Probé muchas de las soluciones sugeridas aquí, pero la que funcionó para mí fue na respuesta a un tema diferente , que repetiré aquí en caso de que el enlace está siempre roto

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;
}

Probé el código anterior (agregue una declaración de uso) y esto fallaría en algunas ocasiones para mí. Pruebas en el constructor de un control de usuario colocado directamente en un formulario con el diseñador cargando en el inicio. Pero funcionaría en otros lugares.

Lo que funcionó para mí, en todos los lugares es:

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;
}

Tal vez un poco excesivo, pero funciona, así que es lo suficientemente bueno para mí.

El éxito en el ejemplo mencionado anteriormente es el bModeCheck, por lo que probablemente el DesignMode es excedente.

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

Es hack-ish, pero si está utilizando VB.NET y cuando está ejecutando desde Visual Studio My.Application.Deployment.CurrentDeployment será Nothing, porque todavía no lo ha implementado. No estoy seguro de cómo verificar el valor equivalente en C #.

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

No estoy seguro de si la ejecución en modo de depuración cuenta como real, pero una manera fácil es incluir una declaración if en su código que verifique el System.Diagnostics.Debugger.IsAttached.

1
Adrian Anttila

Cuando se ejecuta un proyecto, su nombre se añade con ".vshost".

Entonces, yo uso esto:

    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;
        }
    }

Esto funciona para mi.

1
Andy

Si creó una propiedad que no necesita en absoluto en el momento del diseño, puede usar el atributo DesignerSerializationVisibility y establecerlo en Oculto. Por ejemplo:

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

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

Detuvo el bloqueo de Visual Studio cada vez que hice un cambio en el formulario con NotImplementedException() e intenté guardar. En cambio, Visual Studio sabe que no quiero serializar esta propiedad, por lo que puede omitirla. Solo muestra una cadena extraña en el cuadro de propiedades del formulario, pero parece ser seguro ignorarlo.

Tenga en cuenta que este cambio no surte efecto hasta que lo reconstruya.

1
Bolek

Usamos el siguiente código en UserControls y hace el trabajo. Usar solo DesignMode no funcionará en su aplicación que usa sus controles de usuario personalizados como lo indican otros miembros.

    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

Verifica la propiedad DesignMode de su control:

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

Tenga en cuenta que esto no funcionará en su constructor porque los componentes aún no se han inicializado.

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

Aqui hay otro más:

        //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 está en un formulario o control, puede usar la propiedad DesignMode:

if (DesignMode)
{
        DesignMode Only stuff
}
0
Akselsson

Encontré que la propiedad DesignMode tiene errores, al menos en versiones anteriores de Visual Studio. Por lo tanto, hice mi propio uso de la siguiente lógica:

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

Una especie de hack, lo sé, pero funciona bien.

0
Eyvind

Después de probar la mayoría de las respuestas aquí, desafortunadamente, nada me funcionó (VS2015). Así que agregué un pequeño giro a respuesta de JohnV , que no funcionó de la caja, ya que DesignMode es una propiedad protegida en la clase de Control.

Primero hice un método de extensión que devuelve el valor de propiedad de DesignMode a través de la reflexión:

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);
}

y luego hice una función como JohnV:

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

Este es el único método que funcionó para mí, evitando todo el lío de ProcessName, y aunque la reflexión no se debe usar a la ligera, ¡en este caso hizo toda la diferencia! ;)

EDITAR:

También puedes hacer que la segunda función sea un método de extensión como este:

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

Para resolver el problema, también puede codificar de la siguiente manera:

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

}
0