Visual Studio Resources: Default Location for Add Existing File - visual-studio

In the Visual Studio Resources area, is there a way to set the default location in the file select dialog, when selecting "Add Existing File..."?
The default location, when clicking on that menu is:
C:\Program Files (x86)\Microsoft\Visual Studio\2017\Enterprise\Common7\IDE
True, it is a small thing, as selecting my Downloads folder or something else is easy, but I keep having to go somewhere else, usually my Downloads folder, and it would definitely save time to have the default location go somewhere else.
I know that the Open File common dialog, which Visual Studio uses, has the option in the initial structure to specify the initial (default) directory, so the only question is, if it is possible for the default directory to point somewhere else.
I am using Visual Studio 2017.

You can use my Visual Commander extension to monitor for the Resources.AddExistingFile command and set your preferred directory before its execution. See the following C# extension example:
public class E : VisualCommanderExt.IExtension
{
public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
events = DTE.Events;
commandEvents = events.get_CommandEvents(null, 0);
commands = DTE.Commands as EnvDTE80.Commands2;
commandEvents.BeforeExecute += OnBeforeExecute;
}
public void Close()
{
commandEvents.BeforeExecute -= OnBeforeExecute;
}
private void OnBeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
{
string name = GetCommandName(Guid, ID);
if (name == "Resources.AddExistingFile")
System.IO.Directory.SetCurrentDirectory(#"c:\downloads");
}
private string GetCommandName(string Guid, int ID)
{
if (Guid == null)
return "null";
try
{
return commands.Item(Guid, ID).Name;
}
catch (System.Exception)
{
}
return "";
}
private EnvDTE.Events events;
private EnvDTE.CommandEvents commandEvents;
private EnvDTE80.Commands2 commands;
}

Related

How to tell if the active document is a text document?

I'm developing a Visual Studio extension in which one of the implemented commands needs to be available only when the active document is a text document (like e.g. the Visual Studio's "Toggle Bookmark" does). The problem is that I can't figure out how to tell when that's the case.
Right now I have a half working solution. In the package's Initialize method I subscribe to DTE's WindowActivated event, and then whenever a window is activated I check if the window DocumentData property is of type TextDocument:
protected override void Initialize()
{
base.Initialize();
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
dte.Events.WindowEvents.WindowActivated += WindowEventsOnWindowActivated;
//More initialization here...
}
//This is checked from command's BeforeQueryStatus
public bool ActiveDocumentIsText { get; private set; } = false;
private void WindowEventsOnWindowActivated(Window gotFocus, Window lostFocus)
{
if (gotFocus.Kind != "Document")
return; //It's not a document (e.g. it's a tool window)
TextDocument textDoc = gotFocus.DocumentData as TextDocument;
ActiveDocumentIsText = textDoc != null;
}
The problem with this approach is that 1) Window.DocumentData is documented as ".NET Framework internal use only", and 2) this gives a false positive when a document that has both a code view and a design view (e.g. a .visxmanifest file) is open in design mode.
I have tried to use IVsTextManager.GetActiveView as well, but this is returning the last active text view opened - so if I open a .txt file and then a .png file, it returns data for the .txt file even if it's not the active document anymore.
So, how do I check if the active document is a text document, or the code view of a document that can have a designer... and if possible, not using "undocumented" classes/members?
UPDATE: I found a slightly better solution. Inside the window activated handler:
ActiveDocumentIsText = gotFocus.Document.Object("TextDocument") != null;
At least this one is properly documented, but I still have the problem of false positives with designers.
I finally got it. It's somewhat tricky, but it works and is 100% "legal". Here's the recipe:
1- Make the package class implement IVsRunningDocTableEvents. Make all the methods just return VSConstants.S_OK;
2- Add the following field and the following auxiliary method to the package class:
private IVsRunningDocumentTable runningDocumentTable;
private bool DocIsOpenInLogicalView(string path, Guid logicalView, out IVsWindowFrame windowFrame)
{
return VsShellUtilities.IsDocumentOpen(
this,
path,
VSConstants.LOGVIEWID_TextView,
out var dummyHierarchy2, out var dummyItemId2,
out windowFrame);
}
3- Add the following to the Initialize method of the package class:
runningDocumentTable = GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
runningDocumentTable.AdviseRunningDocTableEvents(this, out var dummyCookie);
4- Don't blink, here comes the magic! Implement the IVsRunningDocTableEvents.OnBeforeDocumentWindowShow method as follows:
public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
runningDocumentTable.GetDocumentInfo(docCookie,
out var dummyFlags, out var dummyReadLocks, out var dummyEditLocks,
out string path,
out var dummyHierarchy, out var dummyItemId, out var dummyData);
IVsWindowFrame windowFrameForTextView;
var docIsOpenInTextView =
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_Code, out windowFrameForTextView) ||
DocIsOpenInLogicalView(path, VSConstants.LOGVIEWID_TextView, out windowFrameForTextView);
//Is the document open in the code/text view,
//AND the window for that view is the one that has been just activated?
ActiveDocumentIsText = docIsOpenInTextView && pFrame == logicalViewWindowFrame;
return VSConstants.S_OK;
}

Can I hide the smiley in Visual Studio 2015 final?

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

visual studio installer does not delete all file in uninstall

I am using visual studio installer.
but when uninstalling - from add remove program it does not delete all files but leaves the folder with some files, how can I cause the uninstall delete all files?
The installer only removes the files it installed. The files created the post installation are not removed. You must create a custom action to perform the cleanup.
To clean up after your software (delete some custom or user generated files), you should create a Custom Action and add it to the Uninstall section of your installer.
A custom action can be a Class Library that inherits from the System.Configuration.Install.Installer class.
Here's a sample implementation of the Uninstaller Custom Action:
[RunInstaller(true)]
public partial class CustomUninstaller : System.Configuration.Install.Installer
{
public CustomUninstaller()
{
InitializeComponent();
}
public override void Uninstall(IDictionary savedState)
{
if (savedState != null)
{
base.Uninstall(savedState);
}
string targetDir = #"C:\Your\Installation\Path";
string tempDir = Path.Combine(targetDir, "temp");
try
{
// delete temp files (you can as well delete all files: "*.*")
foreach (FileInfo f in new DirectoryInfo(targetDir).GetFiles("*.tmp"))
{
f.Delete();
}
// delete entire temp folder
if (Directory.Exists(tempDir))
{
Directory.Delete(tempDir, true);
}
}
catch (Exception ex)
{
// TODO: Handle exceptions here
}
}
}

Adding a custom editor to visual studio editor list

I am in the process of writing a custom editor for visual studio. I have implemented some basic functionality for the new language e.g. syntax highlighting and I succesfully installed tha package by using the generated .vsix file. All works just nice, however my custom editor needs to be able to be associated with different file extensions.
I thought, mistakenly, that since I installed the editor it would appear under
Tools->Options..->Text Editor->File Extension->Editors list:
However it does not appear there. So the question is: how do you add a custom editor to this list?
Thanks for any help!
Well at least I got the tumbleweed badge for this question.
After a lot of reverse engineering I found the solution... which is not documented.. Anywhere..
Step number 1:
First you need to create an editor factory with all the bells and whistles it comes with - MSVS has an extension for it.
Step number 2:
Then you have to create such a class
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class ProvideFileExtensionMapping : RegistrationAttribute
{
private readonly string _name, _id, _editorGuid, _package;
private readonly int _sortPriority;
public ProvideFileExtensionMapping(string id, string name, object editorGuid, string package, int sortPriority)
{
_id = id;
_name = name;
if (editorGuid is Type)
{
_editorGuid = ((Type)editorGuid).GUID.ToString("B");
}
else
{
_editorGuid = editorGuid.ToString();
}
_package = package;
_sortPriority = sortPriority;
}
public override void Register(RegistrationContext context)
{
using (Key mappingKey = context.CreateKey("FileExtensionMapping\\" + _id))
{
mappingKey.SetValue("", _name);
mappingKey.SetValue("DisplayName", _name);
mappingKey.SetValue("EditorGuid", _editorGuid);
mappingKey.SetValue("Package", _package);
mappingKey.SetValue("SortPriority", _sortPriority);
}
}
public override void Unregister(RegistrationAttribute.RegistrationContext context)
{
}
}
Step 3:
Then you need to add this class as an attribute to your editor factory (which you created in step 1):
[ProvideFileExtensionMapping("{E23E32ED-3467-4401-A364-1352666A3502}", "RText Editor", typeof(EditorFactory), GuidList.guidRTextEditorPluginEditorFactoryString, 100)]
public sealed class EditorFactory : IVsEditorFactory, IDisposable{...}
That's it. You should now be able to see your editor in the list of editors in visual studio.
Your editor shall be invoked when the file mapping is right.
Hopefully this post saves a lot of time for someone else..

Drag File Warning Extension VS 2010?

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...

Resources