it-swarm-pt.tech

Como saber se o código .NET está sendo executado pelo designer do Visual Studio

Estou recebendo alguns erros lançados no meu código quando abro um formulário do Windows Forms no designer do Visual Studio. Gostaria de ramificar meu código e executar uma inicialização diferente se o formulário estiver sendo aberto pelo designer e se estiver sendo executado de verdade.

Como determinar em tempo de execução se o código está sendo executado como parte do designer que abre o formulário?

55
Zvi

Para descobrir se você está no "modo de design":

  • Os componentes (e controles) do Windows Forms têm uma propriedade DesignMode .
  • Os controles do Windows Presentation Foundation devem usar a propriedade anexada IsInDesignMode .
49
Roger Lipscombe
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
  // Design time logic
}
47
NET3

A propriedade Control.DesignMode é provavelmente o que você está procurando. Informa se o pai do controle está aberto no designer.

Na maioria dos casos, funciona muito bem, mas há casos em que não funciona conforme o esperado. Primeiro, ele não funciona no construtor de controles. Segundo, o DesignMode é falso para os controles "netos". Por exemplo, DesignMode nos controles hospedados em um UserControl retornará false quando o UserControl estiver hospedado em um pai.

Existe uma solução bastante fácil. É algo como isto:

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

Eu não testei esse código, mas deveria funciona.

19
JohnV

A abordagem mais confiável é:

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

A maneira mais confiável de fazer isso é ignorar a propriedade DesignMode e usar seu próprio sinalizador definido na inicialização do aplicativo.

Classe:

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

Program.cs:

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

Em seguida, basta verificar a bandeira que você precisar.

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

A abordagem devenv parou de funcionar no VS2012, pois o designer agora tem seu próprio processo. Aqui está a solução que estou usando atualmente (a parte 'devenv' é deixada lá para o legado, mas sem o VS2010 eu não sou capaz de testar isso).

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

Eu tive o mesmo problema no Visual Studio Express 2013. Tentei muitas das soluções sugeridas aqui, mas a que funcionou para mim foi ma resposta para um thread diferente , que repetirei aqui caso o link está sempre quebrado:

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

Eu tentei o código acima (adicionou uma instrução using) e isso falharia em algumas ocasiões para mim. Teste no construtor de um controle de usuário colocado diretamente em um formulário com o designer carregando na inicialização. Mas funcionaria em outros lugares.

O que funcionou para mim em todos os locais é:

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

Talvez um pouco exagerado, mas funciona, então é bom o suficiente para mim.

O sucesso no exemplo mencionado acima é o bModeCheck, portanto, provavelmente o DesignMode é 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

É hack-ish, mas se você estiver usando VB.NET e quando estiver executando no Visual Studio My.Application.Deployment.CurrentDeployment será Nothing, porque você ainda não o implantou. Não sei como verificar o valor equivalente em c #.

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

Não tenho certeza se a execução no modo de depuração conta como real, mas uma maneira fácil é incluir uma instrução if no seu código que verifique System.Diagnostics.Debugger.IsAttached.

1
Adrian Anttila

Ao executar um projeto, seu nome é anexado com ".vshost".

Então, eu uso isso:

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

Funciona para mim.

1
Andy

Se você criou uma propriedade que você não precisa em tempo de design, você pode usar o atributo DesignerSerializationVisibility e configurá-lo como Oculto. Por exemplo:

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

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

Ele interrompeu o travamento do Visual Studio toda vez que eu fazia uma alteração no formulário com NotImplementedException() e tentava salvar. Em vez disso, o Visual Studio sabe que não quero serializar essa propriedade para que possa ignorá-la. Ele exibe apenas algumas strings estranhas na caixa de propriedades do formulário, mas parece seguro ignorar.

Observe que essa alteração não entra em vigor até você reconstruir.

1
Bolek

Usamos o seguinte código no UserControls e ele faz o trabalho. Usar apenas o DesignMode não funcionará no seu aplicativo que usa seus controles de usuário personalizados, conforme indicado por outros membros.

    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

Você verifica a propriedade DesignMode do seu controle:

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

Observe que isso não funcionará no seu construtor porque os componentes ainda não foram inicializados.

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

Aqui está mais um:

        //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

Se você estiver em um formulário ou controle, poderá usar a propriedade DesignMode:

if (DesignMode)
{
        DesignMode Only stuff
}
0
Akselsson

Eu achei a propriedade DesignMode com erros, pelo menos nas versões anteriores do Visual Studio. Por isso, criei meu próprio usando a seguinte lógica:

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

É uma espécie de truque, eu sei, mas funciona bem.

0
Eyvind

Depois de testar a maioria das respostas aqui, infelizmente nada funcionou para mim (VS2015). Então, adicionei uma pequena reviravolta a resposta de JohnV , que não funcionou imediatamente, pois DesignMode é uma propriedade protegida na classe Control.

Primeiro, criei um método de extensão que retorna o valor da propriedade 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);
}

e então eu criei uma função como JohnV:

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

Este é o único método que funcionou para mim, evitando toda a confusão de ProcessName e, embora a reflexão não deva ser usada levemente, nesse caso, fez toda a diferença! ;)

EDIT:

Você também pode tornar a segunda função um método de extensão 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 o problema, você também pode codificar como abaixo:

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

}
0
Ali Reza Kalantar