как определить, выполняется ли код .net дизайнером visual studio

<p>я получаю некоторые ошибки в моем коде при открытии формы windows forms в конструкторе visual studio. я хотел бы выполнить переход в моем коде и выполнить другую инициализацию, если форма открывается дизайнером, чем если бы она выполнялась по-настоящему.</p><p>как я могу определить во время выполнения, выполняется ли код как часть дизайнера, открывающего форму?</p>

<p>чтобы узнать, находитесь ли вы в "режиме разработки":</p><ul> <li>компоненты windows forms (и элементы управления) имеют свойство <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.component.designmode.aspx">designmode</a> .</li> <li>элементы управления windows presentation foundation должны использовать вложенное свойство <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.designerproperties.isindesignmode.aspx">isindesignmode</a> .</li> </ul>

<pre class="lang-cs prettyprint-override"><code>if (system.componentmodel.licensemanager.usagemode == system.componentmodel.licenseusagemode.designtime) { // design time logic } </code></pre>

<p>свойство control.designmode, вероятно, то, что вы ищете. он сообщает вам, если родительский элемент управления открыт в конструкторе.</p><p>в большинстве случаев это работает отлично, но есть случаи, когда это не работает, как ожидалось. во-первых, это не работает в конструкторе элементов управления. во-вторых, designmode ложно для "внучатых" элементов управления. например, designmode для элементов управления, размещенных в usercontrol, вернет false, когда usercontrol размещен в родительском элементе.</p><p>есть довольно легкий обходной путь. это выглядит примерно так:</p><pre><code>public bool hosteddesignmode { get { control parent = parent; while (parent!=null) { if(parent.designmode) return true; parent = parent.parent; } return designmode; } } </code></pre><p>я не тестировал этот код, но он <em>должен</em> работает.</p>

<p>самый надежный подход:</p><pre><code>public bool isindesignmode { get { system.diagnostics.process process = system.diagnostics.process.getcurrentprocess(); bool res = process.processname == "devenv"; process.dispose(); return res; } } </code></pre>

<p>самый надежный способ сделать это - игнорировать свойство designmode и использовать свой собственный флаг, который устанавливается при запуске приложения.</p><p>учебный класс:</p><pre><code>public static class foo { public static bool isapplicationrunning { get; set; } } </code></pre><p>program.cs:</p><pre><code>[stathread] static void main() { foo.isapplicationrunning = true; // ... code goes here ... } </code></pre><p>тогда просто проверьте флаг там, где он вам нужен.</p><pre><code>if(foo.isapplicationrunning) { // do runtime stuff } else { // do design time stuff } </code></pre>

<p>подход devenv перестал работать в vs2012, так как у дизайнера появился собственный процесс. вот решение, которое я в настоящее время использую <em>(часть 'devenv' оставлена там для наследства, но без vs2010 я не могу это проверить)</em>.</p><pre><code>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; } } </code></pre>

<p>у меня была та же проблема в visual studio express 2013. я перепробовал многие из предложенных здесь решений, но одно из них мне помогло <a href="https://stackoverflow.com/a/21054933/1287392">ответ в другой теме</a> , что я повторю здесь в случае ссылки когда-либо сломан:</p><pre><code>protected static bool isindesigner { get { return (assembly.getentryassembly() == null); } } </code></pre>

<pre><code>using (system.diagnostics.process process = system.diagnostics.process.getcurrentprocess()) { bool indesigner = process.processname.tolower().trim() == "devenv"; return indesigner; } </code></pre><p>я попробовал приведенный выше код (добавил оператор using), и в некоторых случаях это не получалось. тестирование в конструкторе пользовательского элемента управления, размещенного непосредственно в форме с загрузкой конструктора при запуске. но будет работать в других местах.</p><p>что сработало для меня во всех местах:</p><pre><code>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; } </code></pre><p>может быть, немного излишним, но это работает, так что это достаточно хорошо для меня.</p><p>успехом в приведенном выше примере является bmodecheck, поэтому, вероятно, designmode является излишним.</p>

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

<p>это хакерство, но если вы используете <a href="http://en.wikipedia.org/wiki/visual\_basic\_.net">vb.net</a> и когда вы работаете из visual studio <em> my.application.deployment.currentdeployment </em> будет nothing, потому что вы его еще не развернули. я не уверен, как проверить эквивалентное значение в c #.</p>

<pre><code>system.diagnostics.debugger.isattached </code></pre>

<p>я не уверен, считается ли работа в режиме отладки реальной, но простой способ - включить в код оператор <code>if</code>, который проверяет код <code>system.diagnostics.debugger.isattached</code>.</p>

<p>при запуске проекта к его имени добавляется ".vshost".</p><p>итак, я использую это:</p><pre><code> 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; } } </code></pre><p>меня устраивает.</p>

<p>если вы создали свойство, которое вам вообще не нужно во время разработки, вы можете использовать атрибут <strong>designerserializationvisibility</strong> и установить для него значение hidden. например:</p><pre><code>protected virtual datagridview getgrid() { throw new notimplementedexception("frmbase.getgrid()"); } [designerserializationvisibility(designerserializationvisibility.hidden)] public int columncount { get { return getgrid().columns.count; } set { /*some code*/ } } </code></pre><p>он останавливал мой сбой visual studio каждый раз, когда я вносил изменения в форму с помощью <code>notimplementedexception()</code> и пытался сохранить. вместо этого visual studio знает, что я не хочу сериализовать это свойство, поэтому он может его пропустить. он отображает только некоторые странные строки в окне свойств формы, но, кажется, их можно игнорировать.</p><p>обратите внимание, что это изменение не вступит в силу, пока вы не восстановите.</p>

<p>мы используем следующий код в usercontrols, и он делает свою работу. использование только designmode не будет работать в вашем приложении, которое использует ваши пользовательские элементы управления, как указано другими участниками.</p><pre><code> 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; } </code></pre>

<p>вы проверяете свойство <code>designmode</code> вашего элемента управления:</p><pre><code>if (!designmode) { //do production runtime stuff } </code></pre><p>обратите внимание, что это не будет работать в вашем конструкторе, потому что компоненты еще не были инициализированы.</p>

<pre><code>system.componentmodel.component.designmode == true </code></pre>

<p>вот еще один:</p><pre><code> //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 } </code></pre>

<p>если вы находитесь в форме или элементе управления, вы можете использовать свойство designmode:</p><pre><code>if (designmode) { designmode only stuff } </code></pre>

<p>я обнаружил, что свойство designmode содержит ошибки, по крайней мере в предыдущих версиях visual studio. следовательно, я сделал свой собственный, используя следующую логику:</p><pre><code>process.getcurrentprocess().processname.tolower().trim() == "devenv"; </code></pre><p>вроде хак, я знаю, но это хорошо работает.</p>

<p>после тестирования большинства ответов здесь, к сожалению, у меня ничего не получилось (vs2015). поэтому я добавил небольшой поворот в <a href="https://stackoverflow.com/a/73659/3235669">ответ johnv</a> , который не работал "из коробки", так как designmode является защищенным свойством в классе control.</p><p>сначала я создал метод расширения, который возвращает значение свойства designmode через reflection:</p><pre><code>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); } </code></pre><p>и тогда я сделал такую функцию, как johnv:</p><pre><code>public bool hosteddesignmode { get { control parent = parent; while (parent != null) { if (parent.getdesignmode()) return true; parent = parent.parent; } return designmode; } } </code></pre><p>это единственный метод, который работал для меня, избегая всего беспорядка processname, и хотя отражение не должно использоваться легкомысленно, в этом случае он сделал все различие! ;)</p><p><strong> edit: </strong></p><p>вы также можете сделать вторую функцию методом расширения следующим образом:</p><pre><code>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(); } </code></pre>

<p>чтобы решить проблему, вы также можете написать код, как показано ниже:</p><pre><code>private bool isunderdevelopment { get { system.diagnostics.process process = system.diagnostics.process.getcurrentprocess(); if (process.processname.endswith(".vshost")) return true; else return false; } } </code></pre>