Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: obsolete/Microsoft.VisualStudio.Project/ProjectConfig.cs

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /// Copyright (c) Microsoft Corporation. All rights reserved.
2
3 using System;
4 using System.Collections.Generic;
5 using System.Diagnostics;
6 using System.Diagnostics.CodeAnalysis;
7 using System.Globalization;
8 using System.IO;
9 using System.Runtime.InteropServices;
10 using Microsoft.VisualStudio;
11 using Microsoft.VisualStudio.OLE.Interop;
12 using Microsoft.VisualStudio.Shell;
13 //#define ConfigTrace
14 using Microsoft.VisualStudio.Shell.Interop;
15 using MSBuild = Microsoft.Build.BuildEngine;
16
17 namespace Microsoft.VisualStudio.Project
18 {
19 [CLSCompliant(false), ComVisible(true)]
20 public class ProjectConfig :
21 IVsCfg,
22 IVsProjectCfg,
23 IVsProjectCfg2,
24 IVsProjectFlavorCfg,
25 IVsDebuggableProjectCfg,
26 ISpecifyPropertyPages,
27 IVsSpecifyProjectDesignerPages,
28 IVsCfgBrowseObject
29 {
30 #region constants
31 internal const string Debug = "Debug";
32 internal const string Release = "Release";
33 internal const string AnyCPU = "AnyCPU";
34 #endregion
35
36 #region fields
37 private ProjectNode project;
38 private string configName;
39 private MSBuild.BuildPropertyGroup currentConfig;
40 private List<OutputGroup> outputGroups;
41 private IProjectConfigProperties configurationProperties;
42 private IVsProjectFlavorCfg flavoredCfg;
43 private BuildableProjectConfig buildableCfg;
44 #endregion
45
46 #region properties
47 public ProjectNode ProjectMgr
48 {
49 get
50 {
51 return this.project;
52 }
53 }
54
55 public string ConfigName
56 {
57 get
58 {
59 return this.configName;
60 }
61 set
62 {
63 this.configName = value;
64 }
65 }
66
67 public virtual object ConfigurationProperties
68 {
69 get
70 {
71 if (this.configurationProperties == null)
72 {
73 this.configurationProperties = new Proje ctConfigProperties(this);
74 }
75 return this.configurationProperties;
76 }
77 }
78
79 protected IList<OutputGroup> OutputGroups
80 {
81 get
82 {
83 if (null == this.outputGroups)
84 {
85 // Initialize output groups
86 this.outputGroups = new List<OutputGroup >();
87
88 // Get the list of group names from the project.
89 // The main reason we get it from the pr oject is to make it easier for someone to modify
90 // it by simply overriding that method a nd providing the correct MSBuild target(s).
91 IList<KeyValuePair<string, string>> grou pNames = project.GetOutputGroupNames();
92
93 if (groupNames != null)
94 {
95 // Populate the output array
96 foreach (KeyValuePair<string, st ring> group in groupNames)
97 {
98 OutputGroup outputGroup = CreateOutputGroup(project, group);
99 this.outputGroups.Add(ou tputGroup);
100 }
101 }
102
103 }
104 return this.outputGroups;
105 }
106 }
107 #endregion
108
109 #region ctors
110 public ProjectConfig(ProjectNode project, string configuration)
111 {
112 this.project = project;
113 this.configName = configuration;
114
115
116 // Because the project can be aggregated by a flavor, we need to make sure
117 // we get the outer most implementation of that interfac e (hence: project --> IUnknown --> Interface)
118 IntPtr projectUnknown = Marshal.GetIUnknownForObject(thi s.ProjectMgr);
119 try
120 {
121 IVsProjectFlavorCfgProvider flavorCfgProvider = (IVsProjectFlavorCfgProvider)Marshal.GetTypedObjectForIUnknown(projectUnknown, t ypeof(IVsProjectFlavorCfgProvider));
122 ErrorHandler.ThrowOnFailure(flavorCfgProvider.Cr eateProjectFlavorCfg(this, out flavoredCfg));
123 if (flavoredCfg == null)
124 throw new COMException();
125 }
126 finally
127 {
128 if (projectUnknown != IntPtr.Zero)
129 Marshal.Release(projectUnknown);
130 }
131 // if the flavored object support XML fragment, initiali ze it
132 IPersistXMLFragment persistXML = flavoredCfg as IPersist XMLFragment;
133 if (null != persistXML)
134 {
135 this.project.LoadXmlFragment(persistXML, this.Di splayName);
136 }
137 }
138 #endregion
139
140 #region methods
141 protected virtual OutputGroup CreateOutputGroup(ProjectNode proj ect, KeyValuePair<string, string> group)
142 {
143 OutputGroup outputGroup = new OutputGroup(group.Key, gro up.Value, project, this);
144 return outputGroup;
145 }
146
147 public void PrepareBuild(bool clean)
148 {
149 project.PrepareBuild(this.configName, clean);
150 }
151
152 public virtual string GetConfigurationProperty(string propertyNa me, bool resetCache)
153 {
154 MSBuild.BuildProperty property = GetMsBuildProperty(prop ertyName, resetCache);
155 if (property == null)
156 return null;
157
158 return property.FinalValue;
159 }
160
161 public virtual void SetConfigurationProperty(string propertyName , string propertyValue)
162 {
163 if (!this.project.QueryEditProjectFile(false))
164 {
165 throw Marshal.GetExceptionForHR(VSConstants.OLE_ E_PROMPTSAVECANCELLED);
166 }
167
168 string condition = String.Format(CultureInfo.InvariantCu lture, ConfigProvider.configString, this.ConfigName);
169 this.project.BuildProject.SetProperty(propertyName, prop ertyValue, condition);
170
171 // property cache will need to be updated
172 this.currentConfig = null;
173 // Signal the output groups that something is changed
174 foreach (OutputGroup group in this.OutputGroups)
175 {
176 group.InvalidateGroup();
177 }
178 this.project.SetProjectFileDirty(true);
179
180 return;
181 }
182
183 /// <summary>
184 /// If flavored, and if the flavor config can be dirty, ask it i f it is dirty
185 /// </summary>
186 /// <param name="storageType">Project file or user file</param>
187 /// <returns>0 = not dirty</returns>
188 internal int IsFlavorDirty(_PersistStorageType storageType)
189 {
190 int isDirty = 0;
191 if (this.flavoredCfg != null && this.flavoredCfg is IPer sistXMLFragment)
192 {
193 ErrorHandler.ThrowOnFailure(((IPersistXMLFragmen t)this.flavoredCfg).IsFragmentDirty((uint)storageType, out isDirty));
194 }
195 return isDirty;
196 }
197
198 /// <summary>
199 /// If flavored, ask the flavor if it wants to provide an XML fr agment
200 /// </summary>
201 /// <param name="flavor">Guid of the flavor</param>
202 /// <param name="storageType">Project file or user file</param>
203 /// <param name="fragment">Fragment that the flavor wants to sav e</param>
204 /// <returns>HRESULT</returns>
205 internal int GetXmlFragment(Guid flavor, _PersistStorageType sto rageType, out string fragment)
206 {
207 fragment = null;
208 int hr = VSConstants.S_OK;
209 if (this.flavoredCfg != null && this.flavoredCfg is IPer sistXMLFragment)
210 {
211 Guid flavorGuid = flavor;
212 hr = ((IPersistXMLFragment)this.flavoredCfg).Sav e(ref flavorGuid, (uint)storageType, out fragment, 1);
213 }
214 return hr;
215 }
216 #endregion
217
218 #region IVsSpecifyPropertyPages
219 public void GetPages(CAUUID[] pages)
220 {
221 this.GetCfgPropertyPages(pages);
222 }
223 #endregion
224
225 #region IVsSpecifyProjectDesignerPages
226 /// <summary>
227 /// Implementation of the IVsSpecifyProjectDesignerPages. It wil l retun the pages that are configuration dependent.
228 /// </summary>
229 /// <param name="pages">The pages to return.</param>
230 /// <returns>VSConstants.S_OK</returns>
231 public virtual int GetProjectDesignerPages(CAUUID[] pages)
232 {
233 this.GetCfgPropertyPages(pages);
234 return VSConstants.S_OK;
235 }
236 #endregion
237
238 #region IVsCfg methods
239 /// <summary>
240 /// The display name is a two part item
241 /// first part is the config name, 2nd part is the platform name
242 /// </summary>
243 public virtual int get_DisplayName(out string name)
244 {
245 name = DisplayName;
246 return VSConstants.S_OK;
247 }
248
249 private string DisplayName
250 {
251 get
252 {
253 string name;
254 string[] platform = new string[1];
255 uint[] actual = new uint[1];
256 name = this.configName;
257 // currently, we only support one platform, so j ust add it..
258 IVsCfgProvider provider;
259 ErrorHandler.ThrowOnFailure(project.GetCfgProvid er(out provider));
260 ErrorHandler.ThrowOnFailure(((IVsCfgProvider2)pr ovider).GetPlatformNames(1, platform, actual));
261 if (!string.IsNullOrEmpty(platform[0]))
262 {
263 name += "|" + platform[0];
264 }
265 return name;
266 }
267 }
268 public virtual int get_IsDebugOnly(out int fDebug)
269 {
270 fDebug = 0;
271 if (this.configName == "Debug")
272 {
273 fDebug = 1;
274 }
275 return VSConstants.S_OK;
276 }
277 public virtual int get_IsReleaseOnly(out int fRelease)
278 {
279 CCITracing.TraceCall();
280 fRelease = 0;
281 if (this.configName == "Release")
282 {
283 fRelease = 1;
284 }
285 return VSConstants.S_OK;
286 }
287 #endregion
288
289 #region IVsProjectCfg methods
290 public virtual int EnumOutputs(out IVsEnumOutputs eo)
291 {
292 CCITracing.TraceCall();
293 eo = null;
294 return VSConstants.E_NOTIMPL;
295 }
296
297 public virtual int get_BuildableProjectCfg(out IVsBuildableProje ctCfg pb)
298 {
299 CCITracing.TraceCall();
300 if (buildableCfg == null)
301 buildableCfg = new BuildableProjectConfig(this);
302 pb = buildableCfg;
303 return VSConstants.S_OK;
304 }
305
306 public virtual int get_CanonicalName(out string name)
307 {
308 return ((IVsCfg)this).get_DisplayName(out name);
309 }
310
311 public virtual int get_IsPackaged(out int pkgd)
312 {
313 CCITracing.TraceCall();
314 pkgd = 0;
315 return VSConstants.S_OK;
316 }
317
318 public virtual int get_IsSpecifyingOutputSupported(out int f)
319 {
320 CCITracing.TraceCall();
321 f = 1;
322 return VSConstants.S_OK;
323 }
324
325 public virtual int get_Platform(out Guid platform)
326 {
327 CCITracing.TraceCall();
328 platform = Guid.Empty;
329 return VSConstants.E_NOTIMPL;
330 }
331
332 public virtual int get_ProjectCfgProvider(out IVsProjectCfgProvi der p)
333 {
334 CCITracing.TraceCall();
335 p = null;
336 IVsCfgProvider cfgProvider = null;
337 this.project.GetCfgProvider(out cfgProvider);
338 if (cfgProvider != null)
339 {
340 p = cfgProvider as IVsProjectCfgProvider;
341 }
342
343 return (null == p) ? VSConstants.E_NOTIMPL : VSConstants .S_OK;
344 }
345
346 public virtual int get_RootURL(out string root)
347 {
348 CCITracing.TraceCall();
349 root = null;
350 return VSConstants.S_OK;
351 }
352
353 public virtual int get_TargetCodePage(out uint target)
354 {
355 CCITracing.TraceCall();
356 target = (uint)System.Text.Encoding.Default.CodePage;
357 return VSConstants.S_OK;
358 }
359
360 public virtual int get_UpdateSequenceNumber(ULARGE_INTEGER[] li)
361 {
362 CCITracing.TraceCall();
363 li[0] = new ULARGE_INTEGER();
364 li[0].QuadPart = 0;
365 return VSConstants.S_OK;
366 }
367
368 public virtual int OpenOutput(string name, out IVsOutput output)
369 {
370 CCITracing.TraceCall();
371 output = null;
372 return VSConstants.E_NOTIMPL;
373 }
374 #endregion
375
376 #region IVsDebuggableProjectCfg methods
377 /// <summary>
378 /// Called by the vs shell to start debugging (managed or unmana ged).
379 /// Override this method to support other debug engines.
380 /// </summary>
381 /// <param name="grfLaunch">A flag that determines the condition s under which to start the debugger. For valid grfLaunch values, see __VSDBGLAUN CHFLAGS</param>
382 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code</returns>
383 public virtual int DebugLaunch(uint grfLaunch)
384 {
385 CCITracing.TraceCall();
386
387 try
388 {
389 VsDebugTargetInfo info = new VsDebugTargetInfo() ;
390 info.cbSize = (uint)Marshal.SizeOf(info);
391 info.dlo = Microsoft.VisualStudio.Shell.Interop. DEBUG_LAUNCH_OPERATION.DLO_CreateProcess;
392
393 // On first call, reset the cache, following cal ls will use the cached values
394 string property = GetConfigurationProperty("Star tProgram", true);
395 if (string.IsNullOrEmpty(property))
396 {
397 info.bstrExe = this.project.GetOutputAss embly(this.ConfigName);
398 }
399 else
400 {
401 info.bstrExe = property;
402 }
403
404 property = GetConfigurationProperty("WorkingDire ctory", false);
405 if (string.IsNullOrEmpty(property))
406 {
407 info.bstrCurDir = Path.GetDirectoryName( info.bstrExe);
408 }
409 else
410 {
411 info.bstrCurDir = property;
412 }
413
414 property = GetConfigurationProperty("CmdArgs", f alse);
415 if (!string.IsNullOrEmpty(property))
416 {
417 info.bstrArg = property;
418 }
419
420 property = GetConfigurationProperty("RemoteDebug Machine", false);
421 if (property != null && property.Length > 0)
422 {
423 info.bstrRemoteMachine = property;
424 }
425
426 info.fSendStdoutToOutputWindow = 0;
427
428 property = GetConfigurationProperty("EnableUnman agedDebugging", false);
429 if (property != null && string.Compare(property, "true", StringComparison.OrdinalIgnoreCase) == 0)
430 {
431 //Set the unmanged debugger
432 //TODO change to vsconstant when it is a vailable in VsConstants (guidNativeOnlyEng was the old name, maybe it has got a new name)
433 info.clsidCustom = new Guid("{3B476D35-A 401-11D2-AAD4-00C04F990171}");
434 }
435 else
436 {
437 //Set the managed debugger
438 info.clsidCustom = VSConstants.CLSID_Com PlusOnlyDebugEngine;
439 }
440 info.grfLaunch = grfLaunch;
441 VsShellUtilities.LaunchDebugger(this.project.Sit e, info);
442 }
443 catch (Exception e)
444 {
445 Trace.WriteLine("Exception : " + e.Message);
446
447 return Marshal.GetHRForException(e);
448 }
449
450 return VSConstants.S_OK;
451 }
452
453 /// <summary>
454 /// Determines whether the debugger can be launched, given the s tate of the launch flags.
455 /// </summary>
456 /// <param name="flags">Flags that determine the conditions unde r which to launch the debugger.
457 /// For valid grfLaunch values, see __VSDBGLAUNCHFLAGS or __VSDB GLAUNCHFLAGS2.</param>
458 /// <param name="fCanLaunch">true if the debugger can be launche d, otherwise false</param>
459 /// <returns>S_OK if the method succeeds, otherwise an error cod e</returns>
460 public virtual int QueryDebugLaunch(uint flags, out int fCanLaun ch)
461 {
462 CCITracing.TraceCall();
463 string assembly = this.project.GetAssemblyName(this.Conf igName);
464 fCanLaunch = (assembly != null && assembly.ToUpperInvari ant().EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) ? 1 : 0;
465 if (fCanLaunch == 0)
466 {
467 string property = GetConfigurationProperty("Star tProgram", true);
468 fCanLaunch = (property != null && property.Lengt h > 0) ? 1 : 0;
469 }
470 return VSConstants.S_OK;
471 }
472 #endregion
473
474 #region IVsProjectCfg2 Members
475
476 public virtual int OpenOutputGroup(string szCanonicalName, out I VsOutputGroup ppIVsOutputGroup)
477 {
478 ppIVsOutputGroup = null;
479 // Search through our list of groups to find the one the y are looking forgroupName
480 foreach (OutputGroup group in OutputGroups)
481 {
482 string groupName;
483 group.get_CanonicalName(out groupName);
484 if (String.Compare(groupName, szCanonicalName, S tringComparison.OrdinalIgnoreCase) == 0)
485 {
486 ppIVsOutputGroup = group;
487 break;
488 }
489 }
490 return (ppIVsOutputGroup != null) ? VSConstants.S_OK : V SConstants.E_FAIL;
491 }
492
493 public virtual int OutputsRequireAppRoot(out int pfRequiresAppRo ot)
494 {
495 pfRequiresAppRoot = 0;
496 return VSConstants.E_NOTIMPL;
497 }
498
499 public virtual int get_CfgType(ref Guid iidCfg, out IntPtr ppCfg )
500 {
501 // Delegate to the flavored configuration (to enable a f lavor to take control)
502 // Since we can be asked for Configuration we don't supp ort, avoid throwing and return the HRESULT directly
503 int hr = flavoredCfg.get_CfgType(ref iidCfg, out ppCfg);
504
505 return hr;
506 }
507
508 public virtual int get_IsPrivate(out int pfPrivate)
509 {
510 pfPrivate = 0;
511 return VSConstants.S_OK;
512 }
513
514 public virtual int get_OutputGroups(uint celt, IVsOutputGroup[] rgpcfg, uint[] pcActual)
515 {
516 // Are they only asking for the number of groups?
517 if (celt == 0)
518 {
519 if ((null == pcActual) || (0 == pcActual.Length) )
520 {
521 throw new ArgumentNullException("pcActua l");
522 }
523 pcActual[0] = (uint)OutputGroups.Count;
524 return VSConstants.S_OK;
525 }
526
527 // Check that the array of output groups is not null
528 if ((null == rgpcfg) || (rgpcfg.Length == 0))
529 {
530 throw new ArgumentNullException("rgpcfg");
531 }
532
533 // Fill the array with our output groups
534 uint count = 0;
535 foreach (OutputGroup group in OutputGroups)
536 {
537 if (rgpcfg.Length > count && celt > count && gro up != null)
538 {
539 rgpcfg[count] = group;
540 ++count;
541 }
542 }
543
544 if (pcActual != null && pcActual.Length > 0)
545 pcActual[0] = count;
546
547 // If the number asked for does not match the number ret urned, return S_FALSE
548 return (count == celt) ? VSConstants.S_OK : VSConstants. S_FALSE;
549 }
550
551 public virtual int get_VirtualRoot(out string pbstrVRoot)
552 {
553 pbstrVRoot = null;
554 return VSConstants.E_NOTIMPL;
555 }
556
557 #endregion
558
559 #region IVsCfgBrowseObject
560 /// <summary>
561 /// Maps back to the configuration corresponding to the browse o bject.
562 /// </summary>
563 /// <param name="cfg">The IVsCfg object represented by the brows e object</param>
564 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code. </returns>
565 public virtual int GetCfg(out IVsCfg cfg)
566 {
567 cfg = this;
568 return VSConstants.S_OK;
569 }
570
571 /// <summary>
572 /// Maps back to the hierarchy or project item object correspond ing to the browse object.
573 /// </summary>
574 /// <param name="hier">Reference to the hierarchy object.</param >
575 /// <param name="itemid">Reference to the project item.</param>
576 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code. </returns>
577 public virtual int GetProjectItem(out IVsHierarchy hier, out uin t itemid)
578 {
579 if (this.project == null || this.project.NodeProperties == null)
580 {
581 throw new InvalidOperationException();
582 }
583 return this.project.NodeProperties.GetProjectItem(out hi er, out itemid);
584 }
585 #endregion
586
587 #region helper methods
588 /// <summary>
589 /// Splits the canonical configuration name into platform and co nfiguration name.
590 /// </summary>
591 /// <param name="canonicalName">The canonicalName name.</param>
592 /// <param name="configName">The name of the configuration.</par am>
593 /// <param name="platformName">The name of the platform.</param>
594 /// <returns>true if successfull.</returns>
595 internal static bool TrySplitConfigurationCanonicalName(string c anonicalName, out string configName, out string platformName)
596 {
597 configName = String.Empty;
598 platformName = String.Empty;
599
600 if (String.IsNullOrEmpty(canonicalName))
601 {
602 return false;
603 }
604
605 string[] splittedCanonicalName = canonicalName.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
606
607 if (splittedCanonicalName == null || (splittedCanonicalN ame.Length != 1 && splittedCanonicalName.Length != 2))
608 {
609 return false;
610 }
611
612 configName = splittedCanonicalName[0];
613 if (splittedCanonicalName.Length == 2)
614 {
615 platformName = splittedCanonicalName[1];
616 }
617
618 return true;
619 }
620
621 private MSBuild.BuildProperty GetMsBuildProperty(string property Name, bool resetCache)
622 {
623 if (resetCache || this.currentConfig == null)
624 {
625 // Get properties for current configuration from project file and cache it
626 this.project.SetConfiguration(this.ConfigName);
627 this.currentConfig = this.project.BuildProject.E valuatedProperties;
628
629 project.SetCurrentConfiguration();
630 }
631
632 if (this.currentConfig == null)
633 throw new Exception("Failed to retrieve properti es");
634
635 // return property asked for
636 return this.currentConfig[propertyName];
637 }
638
639 /// <summary>
640 /// Retrieves the configuration dependent property pages.
641 /// </summary>
642 /// <param name="pages">The pages to return.</param>
643 private void GetCfgPropertyPages(CAUUID[] pages)
644 {
645 // We do not check whether the supportsProjectDesigner i s set to true on the ProjectNode.
646 // We rely that the caller knows what to call on us.
647 if (pages == null)
648 {
649 throw new ArgumentNullException("pages");
650 }
651
652 if (pages.Length == 0)
653 {
654 throw new ArgumentException(SR.GetString(SR.Inva lidParameter, CultureInfo.CurrentUICulture), "pages");
655 }
656
657 // Retrive the list of guids from hierarchy properties.
658 // Because a flavor could modify that list we must make sure we are calling the outer most implementation of IVsHierarchy
659 string guidsList = String.Empty;
660 IVsHierarchy hierarchy = HierarchyNode.GetOuterHierarchy (this.project);
661 object variant = null;
662 ErrorHandler.ThrowOnFailure(hierarchy.GetProperty(VSCons tants.VSITEMID_ROOT, (int)__VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList, out variant), new int[] { VSConstants.DISP_E_MEMBERNOTFOUND, VSConstants.E_NOTIMPL } );
663 guidsList = (string)variant;
664
665 Guid[] guids = Utilities.GuidsArrayFromSemicolonDelimite dStringOfGuids(guidsList);
666 if (guids == null || guids.Length == 0)
667 {
668 pages[0] = new CAUUID();
669 pages[0].cElems = 0;
670 }
671 else
672 {
673 pages[0] = PackageUtilities.CreateCAUUIDFromGuid Array(guids);
674 }
675 }
676 #endregion
677
678 #region IVsProjectFlavorCfg Members
679 /// <summary>
680 /// This is called to let the flavored config let go
681 /// of any reference it may still be holding to the base config
682 /// </summary>
683 /// <returns></returns>
684 int IVsProjectFlavorCfg.Close()
685 {
686 // This is used to release the reference the flavored co nfig is holding
687 // on the base config, but in our scenario these 2 are t he same object
688 // so we have nothing to do here.
689 return VSConstants.S_OK;
690 }
691
692 /// <summary>
693 /// Actual implementation of get_CfgType.
694 /// When not flavored or when the flavor delegate to use
695 /// we end up creating the requested config if we support it.
696 /// </summary>
697 /// <param name="iidCfg">IID representing the type of config obj ect we should create</param>
698 /// <param name="ppCfg">Config object that the method created</p aram>
699 /// <returns>HRESULT</returns>
700 int IVsProjectFlavorCfg.get_CfgType(ref Guid iidCfg, out IntPtr ppCfg)
701 {
702 ppCfg = IntPtr.Zero;
703
704 // See if this is an interface we support
705 if (iidCfg == typeof(IVsDebuggableProjectCfg).GUID)
706 ppCfg = Marshal.GetComInterfaceForObject(this, t ypeof(IVsDebuggableProjectCfg));
707 else if (iidCfg == typeof(IVsBuildableProjectCfg).GUID)
708 {
709 IVsBuildableProjectCfg buildableConfig;
710 this.get_BuildableProjectCfg(out buildableConfig );
711 ppCfg = Marshal.GetComInterfaceForObject(buildab leConfig, typeof(IVsBuildableProjectCfg));
712 }
713
714 // If not supported
715 if (ppCfg == IntPtr.Zero)
716 return VSConstants.E_NOINTERFACE;
717
718 return VSConstants.S_OK;
719 }
720
721 #endregion
722 }
723
724 //====================================================================== =======
725 // NOTE: advises on out of proc build execution to maximize
726 // future cross-platform targeting capabilities of the VS tools.
727
728 [CLSCompliant(false)]
729 [ComVisible(true)]
730 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledC orrectly", MessageId = "Buildable")]
731 public class BuildableProjectConfig : IVsBuildableProjectCfg
732 {
733 #region fields
734 ProjectConfig config = null;
735 EventSinkCollection callbacks = new EventSinkCollection();
736 #endregion
737
738 #region ctors
739 public BuildableProjectConfig(ProjectConfig config)
740 {
741 this.config = config;
742 }
743 #endregion
744
745 #region IVsBuildableProjectCfg methods
746
747 public virtual int AdviseBuildStatusCallback(IVsBuildStatusCallb ack callback, out uint cookie)
748 {
749 CCITracing.TraceCall();
750
751 cookie = callbacks.Add(callback);
752 return VSConstants.S_OK;
753 }
754
755 public virtual int get_ProjectCfg(out IVsProjectCfg p)
756 {
757 CCITracing.TraceCall();
758
759 p = config;
760 return VSConstants.S_OK;
761 }
762
763 public virtual int QueryStartBuild(uint options, int[] supported , int[] ready)
764 {
765 CCITracing.TraceCall();
766 if (supported != null && supported.Length > 0)
767 supported[0] = 1;
768 if (ready != null && ready.Length > 0)
769 ready[0] = (this.config.ProjectMgr.BuildInProgre ss) ? 0 : 1;
770 return VSConstants.S_OK;
771 }
772
773 public virtual int QueryStartClean(uint options, int[] supported , int[] ready)
774 {
775 CCITracing.TraceCall();
776 config.PrepareBuild(false);
777 if (supported != null && supported.Length > 0)
778 supported[0] = 1;
779 if (ready != null && ready.Length > 0)
780 ready[0] = (this.config.ProjectMgr.BuildInProgre ss) ? 0 : 1;
781 return VSConstants.S_OK;
782 }
783
784 public virtual int QueryStartUpToDateCheck(uint options, int[] s upported, int[] ready)
785 {
786 CCITracing.TraceCall();
787 config.PrepareBuild(false);
788 if (supported != null && supported.Length > 0)
789 supported[0] = 0; // TODO:
790 if (ready != null && ready.Length > 0)
791 ready[0] = (this.config.ProjectMgr.BuildInProgre ss) ? 0 : 1;
792 return VSConstants.S_OK;
793 }
794
795 public virtual int QueryStatus(out int done)
796 {
797 CCITracing.TraceCall();
798
799 done = (this.config.ProjectMgr.BuildInProgress) ? 0 : 1;
800 return VSConstants.S_OK;
801 }
802
803 public virtual int StartBuild(IVsOutputWindowPane pane, uint opt ions)
804 {
805 CCITracing.TraceCall();
806 config.PrepareBuild(false);
807
808 // Current version of MSBuild wish to be called in an ST A
809 uint flags = VSConstants.VS_BUILDABLEPROJECTCFGOPTS_REBU ILD;
810
811 // If we are not asked for a rebuild, then we build the default target (by passing null)
812 this.Build(options, pane, ((options & flags) != 0) ? MsB uildTarget.Rebuild : null);
813
814 return VSConstants.S_OK;
815 }
816
817 public virtual int StartClean(IVsOutputWindowPane pane, uint opt ions)
818 {
819 CCITracing.TraceCall();
820 config.PrepareBuild(true);
821 // Current version of MSBuild wish to be called in an ST A
822 this.Build(options, pane, MsBuildTarget.Clean);
823 return VSConstants.S_OK;
824 }
825
826 public virtual int StartUpToDateCheck(IVsOutputWindowPane pane, uint options)
827 {
828 CCITracing.TraceCall();
829
830 return VSConstants.E_NOTIMPL;
831 }
832
833 public virtual int Stop(int fsync)
834 {
835 CCITracing.TraceCall();
836
837 return VSConstants.S_OK;
838 }
839
840 public virtual int UnadviseBuildStatusCallback(uint cookie)
841 {
842 CCITracing.TraceCall();
843
844
845 callbacks.RemoveAt(cookie);
846 return VSConstants.S_OK;
847 }
848
849 public virtual int Wait(uint ms, int fTickWhenMessageQNotEmpty)
850 {
851 CCITracing.TraceCall();
852
853 return VSConstants.E_NOTIMPL;
854 }
855 #endregion
856
857 #region helpers
858 private void Build(uint options, IVsOutputWindowPane output, str ing target)
859 {
860 if (!this.config.ProjectMgr.HasPassedSecurityChecks)
861 {
862 // From a security perspective, if there was som ething truly malicious about the project,
863 // the user is about to toast himself by request ing a build. Any further attempts at
864 // preventing damage by avoiding MSBuild targets /tasks are futile. So, from this point
865 // forward, we might as well pretend that this p roject has passed all security checks,
866 // and we're free to run any targets we like.
867 this.config.ProjectMgr.HasPassedSecurityChecks = true;
868 }
869
870 // We want to refresh the references if we are building with the Build or Rebuild target or if the project was opened for browsing only.
871 bool shouldRepaintReferences = (target == null || target == MsBuildTarget.Build || target == MsBuildTarget.Rebuild
872 || !this.config.ProjectMgr.HasPassedSecurityChec ks);
873
874 int shouldContinue = 1;
875 foreach (IVsBuildStatusCallback cb in callbacks)
876 {
877 try
878 {
879 ErrorHandler.ThrowOnFailure(cb.BuildBegi n(ref shouldContinue));
880 if (shouldContinue == 0)
881 return;
882 }
883 catch (Exception e)
884 {
885 // If those who ask for status have bugs in their code it should not prevent the build/notification from happening
886 Debug.Fail(String.Format(CultureInfo.Cur rentCulture, SR.GetString(SR.BuildEventError, CultureInfo.CurrentUICulture), e.M essage));
887 }
888 }
889
890 MSBuildResult result = MSBuildResult.Failed;
891 try
892 {
893 result = config.ProjectMgr.Build(options, this.c onfig.ConfigName, output, target);
894 }
895 catch (Exception e)
896 {
897 Trace.WriteLine("Exception : " + e.Message);
898 ErrorHandler.ThrowOnFailure(output.OutputStringT hreadSafe("Unhandled Exception:" + e.Message + "\n"));
899 throw;
900 }
901 finally
902 {
903
904 int success = ((result == MSBuildResult.Successf ul) ? 1 : 0);
905
906 foreach (IVsBuildStatusCallback cb in callbacks)
907 {
908 try
909 {
910 ErrorHandler.ThrowOnFailure(cb.B uildEnd(success));
911 }
912 catch (Exception e)
913 {
914 // If those who ask for status h ave bugs in their code it should not prevent the build/notification from happeni ng
915 Debug.Fail(String.Format(Culture Info.CurrentCulture, SR.GetString(SR.BuildEventError, CultureInfo.CurrentUICultu re), e.Message));
916 }
917 }
918
919 ErrorHandler.ThrowOnFailure(output.FlushToTaskLi st());
920
921 // Now repaint references if that is needed.
922 // We hardly rely here on the fact the ResolveAs semblyReferences target has been run as part of the build.
923 // One scenario to think at is when an assembly reference is renamed on disk thus becomming unresolvable,
924 // but msbuild can actually resolve it.
925 // Another one if the project was opened only fo r browsing and now the user chooses to build or rebuild.
926 if (shouldRepaintReferences && (result == MSBuil dResult.Successful))
927 {
928 this.RefreshReferences();
929 }
930 }
931 }
932
933 /// <summary>
934 /// Refreshes references and redraws them correctly.
935 /// </summary>
936 private void RefreshReferences()
937 {
938 // Refresh the reference container node for assemblies t hat could be resolved.
939 IReferenceContainer referenceContainer = this.config.Pro jectMgr.GetReferenceContainer();
940 if (referenceContainer != null)
941 {
942 foreach (ReferenceNode referenceNode in referenc eContainer.EnumReferences())
943 {
944 referenceNode.RefreshReference();
945 }
946 }
947 }
948 #endregion
949 }
950 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698