如何判断.NET代码是否由Visual Studiodevise器运行

当我在Visual Studio的devise器中打开Windows窗体表单时,出现了一些在我的代码中引发的错误。 我想分支我的代码,并执行一个不同的初始化,如果表单被打开的devise师,而不是如果它是真正的运行。

如何在运行时确定代码是否作为devise者打开表单的一部分而被执行?

要了解您是否处于“devise模式”:

  • Windows窗体组件(和控件)具有DesignMode属性。
  • Windows Presentation Foundation控件应使用IsInDesignMode附加属性。
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime) { // Design time logic } 

Control.DesignMode属性可能是你正在寻找的。 它会告诉您控件的父项是否在devise器中打开。

在大多数情况下,它的效果很好,但有些情况下它不能按预期工作。 首先,它在控件构造函数中不起作用。 其次,DesignMode对于“孙子”控制是错误的。 例如,UserControl中托pipe的控件上的DesignMode将在UserControl托pipe在父项中时返回false。

有一个相当简单的解决方法。 它是这样的:

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

我没有testing过这个代码,但它应该可以工作。

最可靠的方法是:

 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 } 

由于devise师现在有自己的过程,devenv方法停止在VS2012工作。 这里是我目前使用的解决scheme(“devenv”部分留在那里的遗留,但没有VS2010我不能够testing,虽然)

 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; } } 
 using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess()) { bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv"; return inDesigner; } 

我尝试了上面的代码(添加了使用语句),这在某些情况下会失败。 在一个用户控件的构造函数中进行testing,并在启动时加载devise器,直接放置在一个表单中。 但会在其他地方工作。

对我来说,在所有地方工作的是:

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

我在Visual Studio Express 2013中遇到了同样的问题。我尝试了很多这里提出的解决scheme,但是为我工作的解决scheme是一个不同线程的答案,在链接被破坏的情况下,

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

我不确定在debugging模式下运行是否真实,但是一个简单的方法是在代码中包含一个if语句来检查System.Diagnostics.Debugger.IsAttached

我们在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 

运行项目时,其名称会附加“.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; } } 

这个对我有用。

这是hack-ish,但是如果你使用的是VB.NET ,当你在Visual Studio中运行时My.Application.Deployment.CurrentDeployment将是Nothing,因为你还没有部署它。 我不知道如何检查在C#中的等效值。

如果创build了一个在devise时根本不需要的属性,则可以使用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*/ } } 

它停止了我的Visual Studio崩溃每次我用NotImplementedException()更改窗体,并试图保存。 相反,Visual Studio知道我不想序列化这个属性,所以它可以跳过它。 它只在窗体的属性框中显示一些奇怪的string,但似乎是安全的忽略。

请注意,此更改在重build之前不会生效。

如果您处于窗体或控件中,则可以使用DesignMode属性:

 if (DesignMode) { DesignMode Only stuff } 

我发现DesignMode属性是buggy,至less在以前的Visual Studio版本中。 因此,我用自己的逻辑做了自己的事情:

 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 } 

在testing了大部分答案之后,很遗憾没有为我工作(VS2015)。 所以我在JohnV的答案中增加了一点小小的改动 ,因为DesignMode是Control类中的一个受保护的属性。

首先我做了一个扩展方法,它通过reflection返回DesignMode的属性值:

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

然后我做了一个像JohnV的function:

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

这是为我工作的唯一方法,避免了所有的ProcessName混乱,而reflection不应该被轻率使用,在这种情况下,它做了所有的区别! ;)

编辑:

你也可以使第二个函数成为这样的扩展方法:

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

这是一个灵活的方式,适合你编译的地方,以及你是否关心你在哪个模式。

 string testString1 = "\\bin\\"; //string testString = "\\bin\\Debug\\"; //string testString = "\\bin\\Release\\"; if (AppDomain.CurrentDomain.BaseDirectory.Contains(testString)) { //Your code here }