There are two related questions about resetting VisualStudio keyboard scheme and importing VisualStudio settings. However, this doesn't seem to play nice all together.
I have two settings files containing shortcuts:
<!-- IntelliJ.vssettings -->
<ShortcutsScheme>Visual C# 2005</ShortcutsScheme>
<UserShortcuts>
<Shortcut Command="ReSharper.ReSharper_GotoNextHighlight" Scope="Global">F12</Shortcut>
</UserShortcuts>
<!-- ReSharper.vssettings -->
<ShortcutsScheme>Visual C# 2005</ShortcutsScheme>
<UserShortcuts>
<!-- Implicitly has F12 assigned to Edit.GoToDefinition -->
</UserShortcuts>
As you see ReSharper.vssettings doesn't really have the F12 shortcut assigned, since it is the default for VisualStudio. Importing that file, will not reapply the ShortcutsScheme, which is Visual Studio C# 2005 in both cases. This in turn results in the fact, that F12 keeps executing the GotoNextHighlight command. Same problem when just using the import dialog.
Using DTE as follows to reset the keyboard scheme also doesn't work:
var property = dte.Properties["Environment", "Keyboard"];
property.Item("SchemeName").Value = "(Default)";
Exporting the default settings doesn't work for the same reason. As shown here no shortcuts are exported.
Question therefore: How can I reset the VisualStudio keyboard scheme programmatically using DTE?
What I actually need is the command to trigger the Reset button in Options | Environment | Keyboard dialog.
You can remove specific key bindings as per:
Visual Studio key bindings configuration file
Unfortunately I dont have both IntelliJ and ReSharper to test if it works. If it does it'd be nice to do this using DTE however this solution is beyond the scope of DTE and would be trivial using System.IO.File.
UPDATE:
Question: How can I reset the VisualStudio keyboard scheme programmatically using DTE? What I actually need is the command to trigger the Reset button in Options | Environment | Keyboard dialog.
Unfortunately you cannot do it (AFAIK) because resetting the Keyboard Shortcuts is beyond the scope of DTE.
If you setup a VS AddIn Project called "ResetKeyBoard" and put a break point on the Exec method you will see DTE doesnt catch any Visual Studio events firing when you're inside the Tools Options window, they simply aren't exposed through the DTE Object model:
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
This can also be demonstrated by Recording a Macro, the recorded commands only go so deep as to open the Option Dialog (no matter what settings you change inside):
Public Module RecordingModule
Sub TemporaryMacro()
DTE.ExecuteCommand("Tools.Options")
End Sub
End Module
I did learn how to open the Keyboard tab of the Options window directly but since its a Modal Dialog you cant even use SendKeys to press the Reset button:
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName == "ResetKeyBoard.Connect.ResetKeyBoard")
{
_applicationObject.ExecuteCommand("Tools.Options", "BAFF6A1A-0CF2-11D1-8C8D-0000F87570EE");
System.Windows.Forms.SendKeys.Send("%e");
System.Windows.Forms.SendKeys.Send("{ENTER}");
The last DTE option I tried (without luck) is using Commands.Raise, again you cant get deeper than opening Tools Options or at least if you can its undocumented.
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName == "ResetKeyBoard.Connect.ResetKeyBoard")
{
Commands cmds = _applicationObject.Commands;
Command cmdobj = cmds.Item("Tools.Options");
object customIn = null;
object customOut = null;
_applicationObject.Commands.Raise(cmdobj.Guid, cmdobj.ID, ref customIn, ref customOut);
Workarounds:
a) I dont encourage you to replace the Visual C# 2005.vsk file, but if you want to investigate its this file:
C:\Program Files (x86)\Microsoft Visual Studio 1X.0\Common7\IDE\Visual C# 2005.vsk
MSDN Warning
You cannot programmatically change the settings for the default keyboard mapping scheme. To change the settings, save a copy of the default keyboard mapping scheme in the Keyboard node in the Options dialog box. You can then change the settings in that mapping scheme.
I do not recommend or encourage this method, its bad programming and you could destroy someone's keyboard shortcuts!
b) Another way could be by creating your own VSK file and setting it in the currentSettings.vssettings:
</ScopeDefinitions>
<ShortcutsScheme>Visual C# JT</ShortcutsScheme>
</KeyboardShortcuts>
Make sure you backup the currentSettings.vssettings file before changing it.
c) This leads back to Chris Dunaway's suggestion where you create a vssettings file (purely containing keyboard shortcuts) and import that in to reset the keyboard shortcuts. I realise the default shortcuts are not saved, however here is some code you can use with DTE to export the commands out, to insert into a new vssettings file to then import in:
//note, this is untested code!
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName == "ResetKeyBoard.Connect.ResetKeyBoard")
{
System.Diagnostics.Debug.WriteLine("<UserShortcuts>");
foreach (Command c in _applicationObject.Commands)
{
if (!string.IsNullOrEmpty(c.Name))
{
System.Array bindings = default(System.Array);
bindings = (System.Array)c.Bindings;
for (int i = 0; i <= bindings.Length - 1; i++)
{
string scope = string.Empty;
string keyShortCut = string.Empty;
string[] binding = bindings.GetValue(i).ToString().Split(new string[] { "::" },StringSplitOptions.RemoveEmptyEntries );
scope = binding[0];
keyShortCut = binding[1];
System.Diagnostics.Debug.WriteLine("<RemoveShortcut Command=\"...\" Scope=\"" + scope + "\">" + keyShortCut + "</RemoveShortcut>");
System.Diagnostics.Debug.WriteLine("<Shortcut Command=\"" + c.Name + "\" Scope=\"" + scope + "\">" + keyShortCut + "</Shortcut>");
}
}
}
System.Diagnostics.Debug.WriteLine("</UserShortcuts>");
Once you've got them out its easy to import them in:
_applicationObject.ExecuteCommand("Tools.ImportandExportSettings", "/import:\"KeyboardOnly-Exported-2016-08-29.vssettings\"");
REFs:
Visual Studio 2005 IDE Tips and Tricks
How to reset visual studio settings to my saved settings with just a single shortcut?
How does one set Visual Studio 2010 keyboard shortcuts comfortably, especially when using ReSharper?
https://superuser.com/questions/914244/is-there-a-quick-way-to-delete-all-shortcuts-in-visual-studio-10
Remove a keyboard shortcut binding in Visual Studio using Macros
http://vswindowmanager.codeplex.com/
Get full list of available commands for DTE.ExecuteCommand
HOWTO: Execute a command by Guid and Id from a Visual Studio package
HOWTO: Execute a command by Guid and Id from a Visual Studio add-in
HOWTO: Pass parameters programmatically to a command from a Visual Studio add-in
And finally this one by Jared Par:
https://github.com/jaredpar/VsVim/blob/master/Src/VsVimShared/Extensions.cs
/// <summary>
/// Safely reset the keyboard bindings on this Command to the provided values
/// </summary>
public static void SafeSetBindings(this DteCommand command, IEnumerable<string> commandBindings)
{
try
{
var bindings = commandBindings.Cast<object>().ToArray();
command.Bindings = bindings;
// There are certain commands in Visual Studio which simply don't want to have their
// keyboard bindings removed. The only way to get them to relinquish control is to
// ask them to remove the bindings twice.
//
// One example of this is SolutionExplorer.OpenFilesFilter. It has bindings for both
// "Ctrl-[, O" and "Ctrl-[, Ctrl-O". Asking it to remove all bindings will remove one
// but not both (at least until you restart Visual Studio, then both will be gone). If
// we ask it to remove bindings twice though then it will behave as expected.
if (bindings.Length == 0 && command.GetBindings().Count() != 0)
{
command.Bindings = bindings;
}
}
catch (Exception)
{
// Several implementations, Transact SQL in particular, return E_FAIL for this
// operation. Simply ignore the failure and continue
}
You can call devenv.exe directly and pass the /ResetSettings switch. Here is a link to the command line options for Visual Studio: https://msdn.microsoft.com/en-us/library/xee0c8y7.aspx
You can execute devenv.exe using the Systems.Diagnostics.Process class to reset the settings:
Devenv.exe /ResetSettings
You can, optionally, pass a settings file which contains the settings you want to restore:
Devenv.exe /ResetSettings "C:\My Files\MySettings.vssettings"
In Visual Studio, you can export selected settings by going to Tools > Import and Export Settings... and selecting "Export Selected Environment Settings". Then, only choose the Keyboard checkbox under the All Settings > Options > Environment subtree.
Related
I am attempting to use automation in Visual Studio 2019 to help with repetitive tasks as part of a large code merge. I've researched quite a lot on this and am aware that using Roslyn can get me the information I need, but since I am performing other automation tasks in the IDE, I would rather persevere at extracting everything from the IDE as it is presented to me. I got quite a few bits working, but can't seem to be able to manipulate the Find All References tool windows. I can invoke the dialog using dte.ExecuteCommand("Edit.FindAllReferences"). I can also access the Window object from EnvDTE.Windows that corresponds to an existing "Find All References" window, but can't do much with it or the Window.Object property. I am also able to get the IVsWindowFrame object for an existing "Find All References" window, but again I am unable to do very much with it. The way to go appears to be to acquire IFindAllReferencesService but for me, GetService() always returns null. I've since tried the VCmd extension which lets you code macros against the IDE. I found that the macro code in this extension runs in the same process as the IDE - I don't know if it's for this reason or not, but the same GetService() code inside a macro returns a valid interface (Microsoft.VisualStudio.ErrorListPkg.FindAllReferencesService) which is what I need to progress being able to get references information out of a tool window.
I have the following code so far:
using EnvDTE80;
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
//using Microsoft.VisualStudio.Shell;
//using Microsoft.VisualStudio.Data.Framework;
namespace Util2
{
public static class StackOverflowQuestion1
{
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
[DllImport("ole32.dll")]
private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
public static object GetInstanceBySolutionFileName(string FileName)
{
GetRunningObjectTable(0, out var rot);
rot.EnumRunning(out var enumMoniker);
enumMoniker.Reset();
var fetched = IntPtr.Zero;
var moniker = new IMoniker[1];
CreateBindCtx(0, out var bindCtx);
object comObject;
string displayName;
EnvDTE.DTE dte;
while (enumMoniker.Next(1, moniker, fetched) == 0)
{
moniker[0].GetDisplayName(bindCtx, null, out displayName);
if (!displayName.StartsWith("!VisualStudio.DTE.16.0:"))
continue;
rot.GetObject(moniker[0], out comObject);
dte = (EnvDTE.DTE)comObject;
if (dte.Solution.FullName == FileName)
return comObject;
}
return null;
}
public static void Test()
{
Microsoft.VisualStudio.Shell.FindAllReferences.IFindAllReferencesService findAllReferencesService;
//IServiceProvider serviceProvider;
var dte = GetInstanceBySolutionFileName(#"C:\YOUR PROJECT PATH\YOUR_SOLUTION_FILE.sln");
var serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte);
//serviceProvider = new Microsoft.VisualStudio.Data.Framework.ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte);
findAllReferencesService = serviceProvider.GetService(
typeof(Microsoft.VisualStudio.Shell.FindAllReferences.SVsFindAllReferences)) as
Microsoft.VisualStudio.Shell.FindAllReferences.IFindAllReferencesService;
if (findAllReferencesService == null)
MessageBox.Show("NULL!");
else
MessageBox.Show("OK!");
//MessageBox.Show(findAllReferencesService.GetType().ToString());
}
}
}
I am "supposed" to be using packages instead of automation from another application, but the concept of packages and their purpose don't fit what I am trying to achieve. I am trying to create a bunch of code snippets to help me automate a large merge, after that I will not need it. Also, there is a possibility I will need to manipulate 2 VS instances, so even the fact that the code works inside a package, it should not work if that package attempts to hook into another VS instance (i.e. it will have the same problem as my application).
For what it's worth, here's the code that can get me the IVsWindowFrame for the Find All Reference window(s):
var shell = (IVsUIShell)serviceProvider.GetService(typeof(SVsUIShell));
var guid = new Guid("a80febb4-e7e0-4147-b476-21aaf2453969");
shell.FindToolWindowEx((uint)__VSFINDTOOLWIN.FTW_fFindFirst, ref guid, 0, out var windowFrame);
Note, the GUID comes from EnvDTE.Windows.Item().ObjectKind for a references window. Here is a little more about such a window, as an example:
Caption='txtTest_TextChanged' references
Kind=Tool
ObjectKind={A80FEBB4-E7E0-4147-B476-21AAF2453969}
Type=vsWindowTypeToolWindow
As a hack for now, I will call the extension's macro from my application (e.g. VCmd.Command01) which in turn will locate the Find All References window (or search for references for symbol at cursor) then write the results somewhere (e.g. file) and my application would read the results.
EDIT: My hack didn't work as planned and even though it had mileage in the end, I found a quicker way (sort of). After executing command Edit.FindAllReferences, ensure the Visual Studio window itself is focused, the 'Find references' tool/tab would be in a focused state, so I sent it a CTRL+A then CTRL+C using SendInput - all the details I need are in the clipboard which achieves my goal. Similar could be achieved by sending keys to navigate the box, but I haven't got the need for that yet. Obviously this is quite hacky and being able to use IFindAllReferences from another application would be preferrable. Using the macro extension VCMD, I was able to acquire IFindAllReferencesService ref, and was able to call StartSearch(). Looking in more detail, StartSearch merely initialises the window that it returns which is returned as IFindAllReferencesWindow. I haven't tried this, but I think it's possible to hold on to the IFindReferencesWindow interface returned by StartSearch (passing it the exact same label name as it would appear in the IDE e.g. "'button7' references"), then perform Edit.FindAllReferences command, then access the IFindAllReferencesWindow's properties to hopefully get the data. But there were other difficulties...so Clipboard method wins for now :)
This is a cosmetic issue but my application has a default icon on the control panel. Many other applications have custom icons.
My application does have custom icons for the menu and task bar.
How can the icon displayed on the Control Panel be changed using Visual Studio 2015 or later?
Update:
There has been a change in how Visual Studio creates installers. I'm not sure when it occurred, but 2015 definitely does not have a "deployment project". The majority of the hits on Google suggest going to the deployment project properties which does not exist under VS 2015 apps.
This was why I included the tag for visual-studio-2015. Sorry, not to have mentioned that in the original question. It would have been good information.
Using the registry is a possibility but the registry path mentioned, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, does not exist. It does sound kludgy to have the application check it's own icon in the registry all the time. It sounds like an installer function to me.
A post on the Microsoft Developer Network provided an answer. It also modifies the registry. I enhanced it by removing hard-coded values for the application name and the icon file.
// These references are needed:
// using System.Reflection;
// using System.Deployment.Application;
// using System.IO;
// using Microsoft.Win32;
private static void SetAddRemoveProgramsIcon(string iconName)
{
// only run if deployed
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed && ApplicationDeployment.CurrentDeployment.IsFirstRun)
{
try
{
string assemblyTitle="";
object[] titleAttributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), true);
if (titleAttributes.Length > 0 && titleAttributes[0] is AssemblyTitleAttribute)
{
assemblyTitle = (titleAttributes[0] as AssemblyTitleAttribute).Title;
}
string iconSourcePath = Path.Combine(System.Windows.Forms.Application.StartupPath, iconName);
if (!File.Exists(iconSourcePath))
{
return;
}
RegistryKey myUninstallKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Uninstall");
string[] mySubKeyNames = myUninstallKey.GetSubKeyNames();
for (int i = 0; i < mySubKeyNames.Length; i++)
{
RegistryKey myKey = myUninstallKey.OpenSubKey(mySubKeyNames[i], true);
object myValue = myKey.GetValue("DisplayName");
if (myValue != null && myValue.ToString() == assemblyTitle)
{
myKey.SetValue("DisplayIcon", iconSourcePath);
break;
}
}
}
catch (Exception) { }
}
return;
}
The original article by Robin Shahan is here: RobinDotNet
For WPF application we need to replace the following code
string iconSourcePath = Path.Combine(System.Windows.Forms.Application.StartupPath, iconName);
Replace with below code
string iconSourcePath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Startup), "TestIcon.ico");
I know you want 2015 but others may be looking for this in newer versions, like I was.
In Visual Studio 2019 Community we can go to the properties panel for the main setup project and the top property is AddRemoveProgramsIcon.
I have just come through this case today. I know it is old but will be useful for new seekers. To expose icon in Control Panel do the following:
Make a folder in [solution Folder][Project Folder]\bin\debug\images
Copy your icon in the new folder
In Set Up project always refer to the icon in the new created folder.
Solved my problem easily
I always do run StyleCop of menu or build the project when I have used StyleCop.
I want to run StyleCop when the program has been saved.
Is it possible?
Unfortunately macros have been dropped but to write an add-in is pretty easy. First of all create a new C# Add-In project (when finished you'll need to deploy your DLL into Visual Studio AddIns folder and restart VS).
Edit generated template to attach to DocumentSaved event:
private DocumentEvents _documentEvents;
public void OnConnection(object application,
ext_ConnectMode connectMode,
object addInInst,
ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
_documentEvents = _applicationObject.Events.DocumentEvents;
_documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;
}
public void OnDisconnection(ext_DisconnectMode disconnectMode,
ref Array custom)
{
_documentEvents.DocumentSaved -= DocumentEvents_DocumentSaved;
}
Your DocumentEvents_DocumentSaved method will just need to invoke right VS command (please note command name varies with Visual Studio version you're using).
private void DocumentEvents_DocumentSaved(Document Document)
{
document.DTE.ExecuteCommand("Build.RunCodeAnalysisonSelection", "");
}
In this case you'll run Code Analysis only on current project (assuming it's what you saved then it's also what you want to test). This assumption fails for Save All so you may need to use "Build.RunCodeAnalysisonSolution". Of course there is a lot of space for improvements (for example when multiple near sequential saves occur).
If you're targeting VS 2013 then you shouldn't use AddIns because they have been deprecated in favor of Packages. You have same thing to do but you have that notification through IVsRunningDocTableEvents. Override Initialize() in your Package (that will implement IVsRunningDocTableEvents interface). Call AdviseRunningDocTableEvents() from IVsRunningDocumentTable (obtain with GetService()) and you're done.
Finally note that same technique applies also for any other event (after successful build, before deployment, when closing solution, and so on).
I made VSAutoBuild in reference to answer of #Adriano Repetti.
It has been published in the following URL:
https://visualstudiogallery.msdn.microsoft.com/f0930864-0637-4fb3-a34a-155375aa85b3
and github URL:
https://github.com/ko2ic/VSAutoBuild
I am trying to include a custom language support for Visual Studio.
To start with, I need to have GoToDefinition support. And I am struggling to get the context menu to include this command.
I have defined a ContentTypeDefinition and have included the FileExtensionToContentTypeDefinition such as:
internal sealed class GaugeFileContentType
{
[Export]
[Name("Gauge")]
[BaseDefinition("code")]
internal static ContentTypeDefinition GaugeContentTypeDefinition = null;
[Export]
[FileExtension(".spec")]
[ContentType("Gauge")]
internal static FileExtensionToContentTypeDefinition GaugeFileExtensionDefinition = null;
}
Now, despite this, on debugging, I see that DTE.ActiveDocument.Type is text, despite me adding the [BaseDefinition('code')] attribute. What am I missing here?
Are the above definitions enough to tell Visual Studio to bring up Context menu for code?
I am using Visual Studio 2013 Ultimate.
After a few days of head banging, I managed to figure out a way.
I was using the Experimental Instance for debugging, and it did not clean and reinstall the extension, and thus Visual Studio continued to treat the ContentType as 'Plain Text', since that was what I had originally.
When I build a VSIX and installed, opened the same file in a new instance of Visual Studio, it brought up the right context menu.
However, it brought out more than what I wanted (i.e Run Unit Tests from Resharper). So I did some more digging up.
In order to ensure that Visual Studio can handle a command, it checks for it by calling IOleCommandTarget.QueryStatus method.
All I had to do was set the CommandFlag as (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED and return VSConstants.S_OK when the cmdId is VSConstants.VSStd97CmdID.GotoDefn.
The final method looks like this:
public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
if ((VSConstants.VSStd97CmdID)prgCmds[0].cmdID == VSConstants.VSStd97CmdID.GotoDefn)
{
prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_ENABLED | (uint)OLECMDF.OLECMDF_SUPPORTED;
return VSConstants.S_OK;
}
return Next.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
I assume this is a shared resource somewhere in Windows. Rather than making a copy for each app, is there a way to use this icon just like all Winforms apps use it?
How is this specified for Winforms apps by default? I don't see any reference of any icons in code or project settings. Just that it uses the "default icon".
It is stored as a resource in the System.Windows.Forms.dll assembly. You could get a copy with Reflector. Open the assembly, open the Resources node, all the way down to "wfc.ico". Right-click, Save As. Not sure why you'd want to use it, given that it is the default.
You set a custom icon for your application with Project + Properties, Application tab, Icon setting. Each form has its own Icon property.
If you have Visual Studio 2010 installed then there is a large collection of icons (potentially including the application icon/s), check out the following directory:
%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\1033
There may be a similar directory for previous VS versions, take a look if needs be.
EDIT:
On doing a search in the folder of the unzipped file for app there are two notable results:
Application.ico and ApplicationGeneric.ico + its *.png counterpart.
If you have VS 2010 and any of the icons in here are suitable, I believe you don't need to copy a single one - you should be able to include the file indirectly (as a shared/linked file) when adding using the Existing Item... dialog; you do this by selecting the arrow next to Add button and selecting the Add As Link option.
What I can't see working as desired is simply overwriting these files in an attempt to apply a global change.
It is stored as a resource in the System.Windows.Forms.dll assembly. You could get a copy with reflection as folow:
public static class FormUtils
{
private static Icon _defaultFormIcon;
public static Icon DefaultFormIcon
{
get
{
if (_defaultFormIcon == null)
_defaultFormIcon = (Icon)typeof(Form).
GetProperty("DefaultIcon", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).GetValue(null, null);
return _defaultFormIcon;
}
}
public static void SetDefaultIcon()
{
var icon = Icon.ExtractAssociatedIcon(EntryAssemblyInfo.ExecutablePath);
typeof(Form)
.GetField("defaultIcon", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
.SetValue(null, icon);
}
}
public static class FormExtensions
{
internal static void GetIconIfDefault(this Form dest, Form source)
{
if (dest.Icon == FormUtils.DefaultFormIcon)
dest.Icon = source.Icon;
}
}
So as you can see in the code you have in this way the same Icon.Handle. The same reference.
Form.DefaultIcon is an internal lazy loaded static property in class Form.
You can also override the default Winforms icon for your application. In Program.cs i use:
FormUtils.SetDefaultIcon();
This function will then override the default icon with the icon specified in your Application properties, the icon of your executable.
You can just use the Save method:
C#:
string IcoFilename = "C:\\Junk\\Default.ico";
using (System.IO.FileStream fs = new System.IO.FileStream(IcoFilename, System.IO.FileMode.Create))
{
this.Icon.Save(fs);
}
Visual Basic:
Dim strFilename As String = "C:\Junk\Default.ico"
Using fs As New System.IO.FileStream(strFilename, IO.FileMode.Create)
Me.Icon.Save(fs)
End Using
I had a problem which was similar, but different. Rather than needing to get the default icon, I needed to check to see whether the icon on a form was set or if it was left as the default. While I could have used reflection to get it, I ended up using a simpler solution:
private static Icon defaultIcon = new Form().Icon;
// ...
if(this.Icon == defaultIcon)
{
// ...
}