Tech: Visual Studio 2010, Visual Studio Visualization & Modeling SDK
We have a commercial Visual Studio 2010 DSL, when we release a new version we want to increment the version number. I open the DslDefinition.dsl and update the version number as required and then do a Transform all templates so that the changes get reflected. The DslPackage 'source.extension.vsixmanifest' gets updated fine and shows the new version number.
The issue is however is that when someone opens a model created from version 1.0.0.0 with the updated version 1.0.0.1 then they can't open the model, the reason seems to be that the 'dslVersion' in the *.diagram file is set to 1.0.0.0 which has been outdated, I can fix by manually updating the dslVersion but there seems to be no way to set a supported version range.
Is there any fix for this?
I have solved this issue by overriding the 'CheckVersion' method which sits in the '*SerializationHelper' class. My implementation is below.
partial class ProductSerializationHelper
{
protected override void CheckVersion(Microsoft.VisualStudio.Modeling.SerializationContext serializationContext, System.Xml.XmlReader reader)
{
#region Check Parameters
global::System.Diagnostics.Debug.Assert(serializationContext != null);
if (serializationContext == null)
throw new global::System.ArgumentNullException("serializationContext");
global::System.Diagnostics.Debug.Assert(reader != null);
if (reader == null)
throw new global::System.ArgumentNullException("reader");
#endregion
global::System.Version expectedVersion = new global::System.Version("2.5.0.0");
string dslVersionStr = reader.GetAttribute("dslVersion");
if (dslVersionStr != null)
{
try
{
global::System.Version actualVersion = new global::System.Version(dslVersionStr);
// #### THIS IS WHERE I CHANGED FROM '!=' to '>'
if (actualVersion > expectedVersion)
{
ProductSerializationBehaviorSerializationMessages.VersionMismatch(serializationContext, reader, expectedVersion, actualVersion);
}
}
catch (global::System.ArgumentException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
catch (global::System.FormatException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
catch (global::System.OverflowException)
{
ProductSerializationBehaviorSerializationMessages.InvalidPropertyValue(serializationContext, reader, "dslVersion", typeof(global::System.Version), dslVersionStr);
}
}
}
}
Related
I have recently installed VS 2019 and opened up my project I created in VS 2017. The software works fine but there is a bug in VS with lambda captured variables. MS apparently is aware of said issue, but I was wondering if anyone else had come across this recently and if you have, have you managed to solve it?
Example bit of code from my project, the intellisense has flagged up every line where "[this]" appears. The error / bug reads
lambda captured variable of type "MainPage^*" cannot be copied to closure class field of type "MainPage^"
if (_serialPort1 != nullptr)
{
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
Ok, I managed to stumble upon a somewhat ugly hack to fix this.
Rather than pass [this] into the lambda, I added the line auto _this = this; prior to creating any tasks. This did however mean that any variables which were accessed using this->SomeVariable became _this->SomeVariable.
So my example above now looks like this.
if (_serialPort1 != nullptr)
{
auto _this = this;
concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
Hope this is of use.
If so then why copying outside the task? You could do
if (_serialPort1 != nullptr)
{ concurrency::create_task(WriteToSerialDeviceAsync(cancellationTokenSource_serialPort1->get_token(),
Arduino_Device.Outgoing_Bytes, PORT_1)).then([_this = this](concurrency::task<void> previousTask) {
try
{
previousTask.get();
}
catch (Platform::COMException^ ex)
{
_this->DataStreamWindow->Text += "\r\n!EXCEPTION CAUGHT! " + ex->Message;
}
});
}
But based on your problem this is not the proper solution. You better find what's wrong with your project migration to VS 2019.
In Visual Studio 2015 RC, there was that Feedback smiley in the upper right of the main window.
Unfortunately, it is still there in the final release of Visual Studio 2015:
I've searched all through the options and settings and found no way to hide this smiley.
My question:
Any option or other (Registry etc.) hack to remove the smiley?
Update 2015-12-01:
Yesterday Update 1 for Visual Studio was released.
While I still find no option to hide the smiley, they at least provided a less distracting icon for it:
Edit:
Visual Studio 2015 Update 1 changes the feedback icon to an understated black and white one so no more smiley! It's not mentioned in the release notes.
Original answer:
As in OPs answer, this icon is specified in this registry key:
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0_Config\MainWindowFrameControls{F66FBC48-9AE4-41DC-B1AF-0D64F0F54A07}
if you delete the key, Visual Studio recreates it, but if you invalidate the "Package" value of the registry key and restart Visual Studio then the smiley icon is gone:
However, when you install a Visual Studio update (eg SSDT, Resharper) the installer restores the package value, and the smiley is back. So I have created a registry file like this to run when the smiley reappears:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0_Config\MainWindowFrameControls\{F66FBC48-9AE4-41DC-B1AF-0D64F0F54A07}]
#="Feedback Button"
"Package"="{00000000-AA51-43B1-97EE-509A33B681F3}"
"DisplayName"="#1001"
"ViewFactory"="{060EAB95-139E-407D-BEDC-CC2B7A9B39D4}"
"ViewId"=dword:00000064
"Alignment"="TitleBarRight"
"Sort"=dword:00000064
"FullScreenAlignment"="MenuBarRight"
"FullScreenSort"=dword:00000064
This doesn't seem to affect startup time or stability, but there are no guarantees, registry changes are bad mmm, etc.
Thanks to Jehof's hint for Visual Studio 2013, I was able to resolve this:
Deleting the following Registry key actually helped.
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0_Config\MainWindowFrameControls\{F66FBC48-9AE4-41DC-B1AF-0D64F0F54A07}
(Please note the 14.0 instead of the 12.0 in the linked blog post)
After restarting Visual Studio, the Feedback button is now gone.
Update one day later
Suddenly the Feedback icon is here again. And the registry key is here again, too.
How on earth can this happen?
Seems the smiley resurrected from its grave. I'm really frightened now…
Following the advice in this thread, I modified also the registry key and it worked at first, but VS2015 keeps recreating the key to its original value after a while.
To remedy that, I added a VS2015 shortcut in Taskbar, and then Shift+Right Click to access 'Properties'. Replace the Target path of the shortcut pointing to devenv.exe with a own local c:\tools\vs.bat file.
Additionally, I changed Run to 'Minimized' in the shortcut properties. The vs.bat looks as follows:
#echo off
reg ADD HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0_Config\MainWindowFrameControls\{F66FBC48-9AE4-41DC-B1AF-0D64F0F54A07} /v Package /t REG_SZ /d {00000000-AA51-43B1-97EE-509A33B681F3} /f 2> nul
start /B devenv.exe
This ensures the key is overwritten every time I start VS2015 via Taskbar shourtcut. I found this to be reliably working for me.
If you ever start VS without this (e.g., on a VS restart), you may need to run the above twice.
I have removed value of Alignment key (just left it empty). The icon has gone until now but I didn't install no updates yet. Will keep posting.
UPDATE Restoring VS2015 not only restored this button but also changed the way it is configured: now my method doesn't work. Moreover, removing the registry key no longer helps. Wrote to MS through this helpful tool.
The Visual Commander extension allows creation of extensions which can hook into events. One provided example is hiding the feedback icon.
// References: System.Xaml
public class E : VisualCommanderExt.IExtension
{
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = System.TimeSpan.FromMilliseconds(1000);
timer.Tick += OnTimer;
timer.Start();
}
public void Close()
{
timer.Stop();
}
private void OnTimer(System.Object o, System.EventArgs a)
{
try
{
if (HideSignIn() && HideFeedback())
;
}
catch (System.Exception e)
{
}
}
private bool HideSignIn()
{
System.Windows.FrameworkElement e =
FindElement(System.Windows.Application.Current.MainWindow,
"PART_MenuBarFrameControlContainer");
if (e != null)
{
e.Visibility = System.Windows.Visibility.Collapsed;
return true;
}
return false;
}
private bool HideFeedback()
{
System.Windows.FrameworkElement e =
FindElement(System.Windows.Application.Current.MainWindow,
"PART_TitleBarFrameControlContainer");
if (e != null)
{
System.Windows.DependencyObject o1 =
System.Windows.Media.VisualTreeHelper.GetChild(e, 0);
System.Windows.DependencyObject o2 =
System.Windows.Media.VisualTreeHelper.GetChild(o1, 0);
System.Windows.DependencyObject o3 =
System.Windows.Media.VisualTreeHelper.GetChild(o2, 0);
if (System.Windows.Media.VisualTreeHelper.GetChildrenCount(o3) == 3)
{
System.Windows.DependencyObject o4 =
System.Windows.Media.VisualTreeHelper.GetChild(o3, 1);
(o4 as System.Windows.FrameworkElement).Visibility =
System.Windows.Visibility.Collapsed;
return true;
}
}
return false;
}
private System.Windows.FrameworkElement FindElement(System.Windows.Media.Visual v, string name)
{
if (v == null)
return null;
for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(v); ++i)
{
System.Windows.Media.Visual child =
System.Windows.Media.VisualTreeHelper.GetChild(v, i) as
System.Windows.Media.Visual;
if (child != null)
{
System.Windows.FrameworkElement e =
child as System.Windows.FrameworkElement;
if (e != null && e.Name == name)
return e;
}
System.Windows.FrameworkElement result = FindElement(child, name);
if (result != null)
return result;
}
return null;
}
private System.Windows.Threading.DispatcherTimer timer;
}
Although, comparing this example with the hide publish button example it seems the OnTimer function should stop the timer once the icons have been hidden.
private void OnTimer(System.Object o, System.EventArgs a)
{
try
{
if (HideSignIn() && HideFeedback())
timer.Stop();
}
catch (System.Exception e)
{
}
}
This line of PowerShell removes the icon until an update is installed:
Set-ItemProperty -Path "HKCU:\Software\Microsoft\VisualStudio\14.0_Config\MainWindowFrameControls\{F66FBC48-9AE4-41DC-B1AF-0D64F0F54A07}" Package "{00000000-AA51-43B1-97EE-509A33B681F3}"
I am wondering if anyone knows an extension that pops up a warning if you drag a file to another folder through VS 2010 solution explorer. Many times I will be on a file and my computer may lag for a second and all of a sudden the file is now in some other folder and I may not even notice it.
There is a Visual Studio extension available called VSCommands 2010 which has a feature Prevent accidental Drag & Drop in Solution Explorer.
Edit
The feature is part of the Pro package which is not free.
I don't know of a free Visual Studio extension that would do it, but here is a C# sample of an Addin that demonstrate how to hook into Visual Studio global remove & rename file management. It's based on the IVsTrackProjectDocumentsEvents2 interface.
You would have to extend the two OnQueryxxx methods to suit your needs.
using System;
using System.Diagnostics;
using EnvDTE;
using EnvDTE80;
using Extensibility;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
namespace MyAddin1
{
public class Connect : IDTExtensibility2, IVsTrackProjectDocumentsEvents2
{
private uint _trackerCookie;
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
// the Addin project needs assembly references to Microsoft.VisualStudio.Shell, Microsoft.VisualStudio.Shell.Interop && Microsoft.VisualStudio.OLE.Interop
// any version should do
ServiceProvider sp = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_applicationObject);
IVsTrackProjectDocuments2 tracker = (IVsTrackProjectDocuments2)sp.GetService(typeof(SVsTrackProjectDocuments));
// ask VS to notify us of files & directories changes
tracker.AdviseTrackProjectDocumentsEvents(this, out _trackerCookie);
}
public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
{
if (_trackerCookie != 0)
{
// we quit, tell VS not to notify us anymore
ServiceProvider sp = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_applicationObject);
IVsTrackProjectDocuments2 tracker = (IVsTrackProjectDocuments2)sp.GetService(typeof(SVsTrackProjectDocuments));
tracker.UnadviseTrackProjectDocumentsEvents(_trackerCookie);
_trackerCookie = 0;
}
}
public int OnQueryRenameFiles(IVsProject pProject, int cFiles, string[] rgszMkOldNames, string[] rgszMkNewNames, VSQUERYRENAMEFILEFLAGS[] rgFlags, VSQUERYRENAMEFILERESULTS[] pSummaryResult, VSQUERYRENAMEFILERESULTS[] rgResults)
{
Trace.WriteLine("OnQueryRenameFiles pProject:" + pProject + " old[0]:" + rgszMkOldNames[0] + " new[0]:" + rgszMkNewNames[0]);
// TODO: implement this (I have assumed cFiles is 1 here)
if (!NotRenameOk(old[0], new[0])
{
rgResults[0] = VSQUERYRENAMEFILERESULTS.VSQUERYRENAMEFILERESULTS_RenameNotOK; // nope, it's not ok
}
return 0;
}
public int OnQueryRemoveFiles(IVsProject pProject, int cFiles, string[] rgpszMkDocuments, VSQUERYREMOVEFILEFLAGS[] rgFlags, VSQUERYREMOVEFILERESULTS[] pSummaryResult, VSQUERYREMOVEFILERESULTS[] rgResults)
{
Trace.WriteLine("OnQueryRemoveFiles pProject:" + pProject + " file[0]:" + rgpszMkDocuments[0]);
// TODO: needs to be implemented, use rgResults to tell VS if it's ok or not
return 0;
}
// other IVsTrackProjectDocumentsEvents2 methods implementation omitted for brevity...
I created a small extension for the EF designer that adds a new property to the property window. I did this using a vsix project (new project -> c# -> extensibility -> vsix project). When I hit F5 the experimental VS instance starts up. I create a new project, add an entity data model and add an entity. However, my break points never get hit and I don't see the property. Any ideas as to what I might be doing wrong?
public class AggregateRootValue
{
internal static XName AggregateRootElementName = XName.Get("AggregateRoot", "http://efex");
private readonly XElement _property;
private readonly PropertyExtensionContext _context;
public AggregateRootValue(XElement parent, PropertyExtensionContext context)
{
_property = parent;
_context = context;
}
[DisplayName("Aggregate Root")]
[Description("Determines if an entity is an Aggregate Root")]
[Category("Extensions")]
[DefaultValue(true)]
public string AggregateRoot
{
get
{
XElement child = _property.Element(AggregateRootElementName);
return (child == null) ? bool.TrueString : child.Value;
}
set
{
using (EntityDesignerChangeScope scope = _context.CreateChangeScope("Set AggregateRoot"))
{
var element = _property.Element(AggregateRootElementName);
if (element == null)
_property.Add(new XElement(AggregateRootElementName, value));
else
element.SetValue(value);
scope.Complete();
}
}
}
}
[Export(typeof(IEntityDesignerExtendedProperty))]
[EntityDesignerExtendedProperty(EntityDesignerSelection.ConceptualModelEntityType)]
public class AggregateRootFactory : IEntityDesignerExtendedProperty
{
public object CreateProperty(XElement element, PropertyExtensionContext context)
{
var edmXName = XName.Get("Key", "http://schemas.microsoft.com/ado/2008/09/edm");
var keys = element.Parent.Element(edmXName).Elements().Select(e => e.Attribute("Name").Value);
if (keys.Contains(element.Attribute("Name").Value))
return new AggregateRootValue(element, context);
return null;
}
}
EDIT: I put the code on Github: https://github.com/devlife/Sandbox
EDIT: After Adding the MEF component to the manifest as suggested, the extension still never loads. Here is a picture of the manifest:
So the answer, as it turns out, is in how I setup my project. I put both classes inside the project which produces the VSIX file. By simply moving those classes into another project and setting that project as the MEF Component in the manifest (and thus copying the assembly) it worked like a charm!
For VS2012, it is only needed to add Solution as MEF component also. Just add whole solution as MEF component also.
Then it works surprisingly fine.
It seems the dll built by your project isn't automatically included in the generated VSIX package, and VS2013 doesn't give you options through the IDE to change this (that I can work out, anyway).
You have to manually open the project file and alter the XML. The property to change is IncludeAssemblyInVSIXContainer.
Seen here: How to include VSIX output in it's package?
We are getting the following warning from Code Analysis in Visual Studio 2010 and I'm wondering if this is a false positive that we can safely ignore or the code should be refactored to correctly dispose the object.
The relevant code:
public void MyFunction()
{
OracleConnection oraConnection = null;
OracleCommand oraCommand = null;
try
{
// Connect to the database
oraConnection = new OracleConnection(connectionString);
oraConnection.Open();
// Prepare and run the query
oraCommand = new OracleCommand(sqlQuery, oraConnection);
oraCommand.ExecuteNonQuery();
}
catch { throw; }
finally
{
// Perform a safe cleanup
if (oraCommand != null) { oraCommand.Dispose(); }
if (oraConnection != null)
{
oraConnection.Close();
oraConnection.Dispose();
}
}
}
The relevant error message:
Warning 18 CA2202 : Microsoft.Usage : Object 'oraConnection' can be disposed
more than once in method 'ClassName.MyFunction()'. To avoid generating a
System.ObjectDisposedException you should not call Dispose more than one
time on an object.
If you remove the line:
oraConnection.Close();
it should get rid of the warning, since closing and disposing a connection are essentially the same thing.
You might also want to replace your try/finally by a using statement.
Note that Microsoft's own guidelines say that IDisposable.Dispose should be implemented in such a way that it can safely be called multiple times. Which means that the CA2202 warning can safely be ignored, as noted in the comment by JoeM27 on the MSDN page for CA2202.