programing

.NET 코드가 Visual Studio 디자이너에서 실행 중인지 확인하는 방법

nasanasas 2021. 1. 5. 08:10
반응형

.NET 코드가 Visual Studio 디자이너에서 실행 중인지 확인하는 방법


Visual Studio 디자이너에서 Windows Forms 양식을 열 때 코드에 오류가 발생합니다. 내 코드에서 분기하고 디자이너가 양식을 여는 경우 실제 실행되는 경우보다 다른 초기화를 수행하고 싶습니다.

코드가 양식을 여는 디자이너의 일부로 실행 중인지 런타임에 어떻게 확인할 수 있습니까?


"디자인 모드"에 있는지 확인하려면 :

  • Windows Forms 구성 요소 (및 컨트롤)에는 DesignMode 속성이 있습니다.
  • Windows Presentation Foundation 컨트롤은 IsInDesignMode 연결된 속성을 사용해야합니다 .

if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
  // Design time logic
}

Control.DesignMode 속성은 아마도 당신이 찾고있는 것입니다. 디자이너에서 컨트롤의 부모가 열려 있는지 여부를 알려줍니다.

대부분의 경우 잘 작동하지만 예상대로 작동하지 않는 경우가 있습니다. 첫째, 컨트롤 생성자에서 작동하지 않습니다. 둘째, "손자"컨트롤에 대해 DesignMode가 false입니다. 예를 들어 UserControl에서 호스팅되는 컨트롤의 DesignMode는 UserControl이 부모에서 호스팅 될 때 false를 반환합니다.

매우 쉬운 해결 방법이 있습니다. 다음과 같이 진행됩니다.

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

그 코드를 테스트하지 않은,하지만 해야 작동합니다.


가장 신뢰할 수있는 접근 방식은 다음과 같습니다.

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

이 작업을 수행하는 가장 안정적인 방법은 DesignMode 속성을 무시하고 응용 프로그램 시작시 설정되는 고유 한 플래그를 사용하는 것입니다.

수업:

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

Program.cs :

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

그런 다음 필요할 때마다 플래그를 확인하십시오.

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

디자이너가 이제 자체 프로세스를 가지므로 devenv 접근 방식은 VS2012에서 작동하지 않습니다. 현재 사용중인 솔루션은 다음과 같습니다 ( 'devenv'부분은 레거시를 위해 남아 있지만 VS2010 없이는 테스트 할 수 없습니다) .

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

Visual Studio Express 2013에서 동일한 문제가 발생했습니다. 여기에서 제안 된 많은 솔루션을 시도했지만 저에게 도움이 된 것은 다른 스레드대한 답변 이었습니다 . 링크가 끊어진 경우 여기에서 반복하겠습니다.

protected static bool IsInDesigner
{
    get { return (Assembly.GetEntryAssembly() == null); }
}

using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
    bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv";
    return inDesigner;
}

나는 위의 코드를 시도했고 (using 문을 추가했습니다) 이것은 나를 위해 어떤 경우에 실패 할 것입니다. 시작시 디자이너가로드하는 양식에 직접 배치 된 usercontrol의 생성자에서 테스트합니다. 그러나 다른 곳에서 작동합니다.

모든 위치에서 나를 위해 일한 것은 다음과 같습니다.

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

약간 과잉 일 수도 있지만 작동하므로 나에게 충분합니다.

위에서 언급 한 예제의 성공은 bModeCheck이므로 DesignMode가 잉여 일 수 있습니다.


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

해킹이지만 VB.NET을 사용 하고 Visual Studio 내에서 실행할 때 My.Application.Deployment.CurrentDeployment 는 아직 배포하지 않았기 때문에 Nothing이됩니다. C #에서 동등한 값을 확인하는 방법을 잘 모르겠습니다.


UserControls에서 다음 코드를 사용하고 작업을 수행합니다. 다른 구성원이 지적한대로 사용자 지정 사용자 컨트롤을 사용하는 앱에서는 DesignMode 만 사용하면 작동하지 않습니다.

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

DesignMode컨트롤 속성을 확인합니다 .

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

구성 요소가 아직 초기화되지 않았기 때문에 생성자에서 작동하지 않습니다.


System.ComponentModel.Component.DesignMode == true

System.Diagnostics.Debugger.IsAttached

프로젝트를 실행할 때 이름에 ".vshost"가 추가됩니다.

그래서 이것을 사용합니다.

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

그것은 나를 위해 작동합니다.


디버그 모드에서 실행하는 것이 실제로 간주되는지 확실하지 않지만 쉬운 방법은 if 그 checkes에 대한 코드에서 문을 System.Diagnostics.Debugger.IsAttached.


디자인 타임에 전혀 필요하지 않은 속성을 만든 경우 DesignerSerializationVisibility를 사용할 수 있습니다. 특성을 사용하고이를 Hidden으로 설정할 수 있습니다. 예를 들면 :

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

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

양식을 변경 NotImplementedException()하고 저장하려고 할 때마다 Visual Studio 충돌이 중지되었습니다 . 대신 Visual Studio는이 속성을 직렬화하지 않으려는 것을 알고 있으므로 건너 뛸 수 있습니다. 양식의 속성 상자에 이상한 문자열 만 표시되지만 무시해도되는 것 같습니다.

이 변경 사항은 다시 빌드 할 때까지 적용되지 않습니다.


폼이나 컨트롤에있는 경우 DesignMode 속성을 사용할 수 있습니다.

if (DesignMode)
{
        DesignMode Only stuff
}

최소한 이전 버전의 Visual Studio에서는 DesignMode 속성이 버그가있는 것으로 나타났습니다. 따라서 다음 논리를 사용하여 직접 만들었습니다.

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

일종의 해킹이라고 알고 있지만 잘 작동합니다.


문제를 해결하기 위해 다음과 같이 코딩 할 수도 있습니다.

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

}

다음은 또 하나입니다.

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

After testing most of the answers here, unfortunately nothing worked for me (VS2015). So I added a little twist to JohnV's answer, which didn't work out of the box, since DesignMode is a protected Property in the Control class.

First I made an extension method which returns the DesignMode's Property value 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);
}

and then I made a function like JohnV:

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

This is the only method that worked for me, avoiding all the ProcessName mess, and while reflection should not be used lightly, in this case it did all the difference! ;)

EDIT:

You can also make the second function an extension method like this:

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

    /// <summary>
    ///  Whether or not we are being run from the Visual Studio IDE
    /// </summary>
    public bool InIDE
    {
        get
        {
            return Process.GetCurrentProcess().ProcessName.ToLower().Trim().EndsWith("vshost");
        }
    }

Here's a flexible way that is adaptable to where you compile from as well as whether or not you care which mode you're in.

string testString1 = "\\bin\\";
//string testString = "\\bin\\Debug\\";
//string testString = "\\bin\\Release\\";

if (AppDomain.CurrentDomain.BaseDirectory.Contains(testString))
{
    //Your code here
}

ReferenceURL : https://stackoverflow.com/questions/73515/how-to-tell-if-net-code-is-being-run-by-visual-studio-designer

반응형