"Tabify" all files in Visual Studio solution? - visual-studio

There's a "tabify" command in
Edit > Advanced > Tabify Selected Lines
(and the Power Tools 2010 also provide this functionality on a per-file basis) but is there a way to do this for all code files in a solution?
ReSharper has a Clean Up command but the only half-suitable option I found there is to run formatting on all files which does more than I want (I don't want to run a complete formatting, just tabifying).

If you have added the Microsoft Productivity Power tools extension (which if you haven't I would recommned) it adds an option to tabify files. This does not apply across all files in a solution, but it's prompted for when editing each file, on a per file basis. Not quite what you're after but a help.
Also you might try setting your IDE editor settings to use tabs, then do menu-edit-advanced-format document (CTRL+E,D). This will replace groups of tab length spaces with a tab, and that should be scriptable for all files in the solution via a macro.

The request contains links to IDE macros that can do the job:
http://blogs.msdn.com/b/kevinpilchbisson/archive/2004/05/17/133371.aspx
http://web.archive.org/web/20090217094033/http://chriseargle.com/post/Format-Solution.aspx
Here is sample code for a Visual Studio macro that automatically formats all *.cs, *.h, *.cpp, and *.hpp files in an open solution, which includes converting spaces to tabs (depending on your Tab settings in Tools > Options > Text Editor > specific language or "All Languages" > Tabs):
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Public Module ConvertTabsToSpaces
Public Sub FormatSolution()
Dim sol As Solution = DTE.Solution
For i As Integer = 1 To sol.Projects.Count
FormatProject(sol.Projects.Item(i))
Next
End Sub
Private Sub FormatProject(ByVal proj As Project)
If Not proj.ProjectItems Is Nothing Then
For i As Integer = 1 To proj.ProjectItems.Count
FormatProjectItem(proj.ProjectItems.Item(i))
Next
End If
End Sub
Private Sub FormatProjectItem(ByVal projectItem As ProjectItem)
If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then
If projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
projectItem.Document.DTE.ExecuteCommand("Edit.FormatDocument")
window.Close(vsSaveChanges.vsSaveChangesYes)
ElseIf ((projectItem.Name.LastIndexOf(".cpp") = projectItem.Name.Length - 4) OrElse (projectItem.Name.LastIndexOf(".hpp") = projectItem.Name.Length - 4) OrElse (projectItem.Name.LastIndexOf(".h") = projectItem.Name.Length - 2)) Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
projectItem.Document.DTE.ExecuteCommand("Edit.SelectAll")
projectItem.Document.DTE.ExecuteCommand("Edit.FormatSelection")
window.Close(vsSaveChanges.vsSaveChangesYes)
End If
End If
'Be sure to format all of the ProjectItems.
If Not projectItem.ProjectItems Is Nothing Then
For i As Integer = 1 To projectItem.ProjectItems.Count
FormatProjectItem(projectItem.ProjectItems.Item(i))
Next
End If
'Format the SubProject if it exists.
If Not projectItem.SubProject Is Nothing Then
FormatProject(projectItem.SubProject)
End If
End Sub
End Module
Instructions (Visual Studio 2005, but similar for newer versions):
Launch Visual Studio
Tools > Macros > Macros IDE...
Right-click MyMacros > Add > Add New Item...
Select Module
Enter "ConvertSpacesToTabs" without quotes in the Name field
Click Add
Replace the contents of the new module with the code above
Click Save
Close the Macros IDE
Tools > Macros > Macro Explorer
Expand MyMacros > ConvertSpacesToTabs
Double-click on FormatSolution
Wait for the macro to finish
Edit
I updated the code to also support *.h, *.cpp, and *.hpp files using code from Siegmund Frenzel here:
https://stackoverflow.com/a/14766393/90287

as far as I know what "Tabify" does is this - it only replaces " " (4 spaces) with a tab, it does not change the formatting or anything else.
Although I would suggest using document formatting, the "tabification" could easily be done via a custom application which would mimic the same action on all the files that you want.
Hope this helps!

For vs2010, you can use the following find and replace (this example is for tabs to 4 spaces).
In the find box, enter: ^{ *} (^{ space *} tab)
In the replace box, enter \1 (\1 space space space space)
Check the condition box and set to regular expressions.
Newer versions of vs use different regular expression syntax, but the same should be doable.
Update
This worked by executing once for vb files, but required multiple passes for a resx file, so you may have to execute multiple times depending on the file type...

There's a new way using the dotnet CLI:
Install dotnet format by running the following command:
dotnet tool install -g dotnet-format
Run it, replacing SolutionFile.sln with the path to your solution file, with the following command line:
dotnet format SolutionFile.sln
The indent_style of .editorconfig will be used to determine if the code will use tabs or spaces.

Macros have been removed from Visual Studio 2013 onwards (and the new version of Macros uses JavaScript rather than VBScript), so to get Rami A.'s answer to work in Visual Studio 2019:
Download and install the Visual Commander extension
Extensions > VCmd > Edit macro
Name it
Paste the following code. I have had to make some changes to it to make the code work with Visual Commander. I have also changed the file extensions that it tabifies to .cs, .aspx and .ascx so change these if you need C++/other file extensions.
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports Microsoft.VisualStudio.Shell
Imports VisualCommanderExt
Public Class ConvertTabsToSpaces
Implements ICommand
Sub Run(DTE As DTE2, package As Package) Implements ICommand.Run
Dim sol As Solution = dte.Solution
For i As Integer = 1 To sol.Projects.Count
FormatProject(sol.Projects.Item(i))
Next
End Sub
Private Sub FormatProject(ByVal proj As Project)
If Not proj.ProjectItems Is Nothing Then
For i As Integer = 1 To proj.ProjectItems.Count
FormatProjectItem(proj.ProjectItems.Item(i))
Next
End If
End Sub
Private Sub FormatProjectItem(ByVal projectItem As ProjectItem)
If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then
If (projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 OrElse (projectItem.Name.LastIndexOf(".aspx") = projectItem.Name.Length - 5 OrElse (projectItem.Name.LastIndexOf(".ascx") = projectItem.Name.Length - 5))) Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
Try
projectItem.Document.DTE.ExecuteCommand("Edit.RemoveAndSort")
Catch
' Do nothing
End Try
Try
projectItem.Document.DTE.ExecuteCommand("Edit.SelectAll")
projectItem.Document.DTE.ExecuteCommand("Edit.FormatSelection")
Catch
' Do nothing
End Try
window.Close(vsSaveChanges.vsSaveChangesYes)
End If
End If
'Be sure to format all of the ProjectItems
If Not projectItem.ProjectItems Is Nothing Then
For i As Integer = 1 To projectItem.ProjectItems.Count
FormatProjectItem(projectItem.ProjectItems.Item(i))
Next
End If
'Format the SubProject if it exists
If Not projectItem.SubProject Is Nothing Then
FormatProject(projectItem.SubProject)
End If
End Sub
End Class
Save
Run
To save for future use: Extensions > VCmd > Save macro as command > Name it > Save

Related

programmatically alter project settings

I have an old MFC solution with 120 projects in it.
Now Im trying to compile it with VisualC 2017 but every project emits the error:
cannot open file mfc140d.lib
Opening project properties, change the platform toolset to VS2017 141 and the the language version to C++17 fixes it.
But it will take a looooong time to do this for 120 projects and then the same for release build. Which are the settings in the project files that I can change programatically to set these two options? I sure cant find them
Wrote a python script that adds stdcpp17 and v141 to the vcxproj file if non existing. Maybe somebody finds a use for it:
def get_all_files(basedir):
for root, subfolders, files in os.walk(basedir):
for file in os.listdir(root):
yield root, file
def all_lines_from_file(file):
with open(file, 'r') as fd:
for line in fd.readlines():
yield line
def update_VCXPROJ():
standard = '<LanguageStandard>stdcpp17</LanguageStandard>'
toolset = '<PlatformToolset>v141</PlatformToolset>'
add1 = '<CharacterSet>MultiByte</CharacterSet>'
add2 = '<DebugInformationFormat>'
for root, file in get_all_files('c:/projects/6thcycle/sources/'):
if not file.lower().endswith('.vcxproj'):
continue
thisfile = ''
for line in all_lines_from_file('{0}/{1}'.format(root, file)):
if toolset in line or standard in line:
continue
if add1 in line:
line += ' {0}\n'.format(toolset)
elif add2 in line:
line += ' {0}\n'.format(standard)
thisfile += line
with open('{0}/{1}'.format(root, file), 'w') as fd:
fd.write(thisfile)
update_VCXPROJ()

Shorten Find Results Filepath Name

Because of all the sub-directories my code typically lives in, whenever I do a Find In File for something, the code gets run off the screen because the results window has wasted so much valuable real estate by repeating the long file path for every object in my solution. More often than not, they are in the same parent directory, or I don't really care where there from.
Is there an option to shorten the path name to perhaps just the file?
Also, the Display File Names Only option in the Find in Files dialog does not do this, it only omits the code from the result.
You can change the VS search result formatting by changing the registry.
According to the article Customize how Find in Files results are displayed in the Find Results Window:
Open up RegEdit
Go to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\Find
Add a new string called Find result format with a value of $f$e($l,$c):$t\r\n
DANGER: This involves hacking the Registry so use this tip at your own risk!
Further, here's the syntax to use if you'd like to customize the string further:
Files
$p - path
$f - filename
$v - drive/unc share
$d - dir
$n - name
$e - .ext
Location
$l - line
$c - col
$x - end col if on first line, else end of first line
$L - span end line
$C - span end col
Text
$0 - matched text
$t - text of first line
$s - summary of hit
$T - text of spanned lines
Char
\n - newline
\s - space
\t - tab
\\ - slash
\$ - $
Things are different on Visual Studio 2017. You won't find the registry keys for Visual Studio 2017 anymore as Visual Studio 2017 now stores registry keys in a private binary file under %VsAppDataFolder%\privateregistry.bin.
However, according to this link, there is still a way to find and modify registry keys for Visual Studio 2017.
Close Visual Studio 2017
Open regedit
Select HKEY_LOCAL_MACHINE from the left bar
Select File > Load Hive...
Load the privateregistry.bin file from %localappdata%\Microsoft\VisualStudio\15.0_[instanceid]{RootSuffix}\privateregistry.bin. The RootSuffix for a normal VS installation will be blank. This is mostly used for the experimental instance
Name the key whatever you want (e.g. "VS2017") when prompted
From there, you should be able to view the entries just like any normal registry.
Customise it according to accepted answer's suggestions.
Important! Once you're finished, you need to make sure that you "Unload" the private registry, by selecting the "root" key ("VS2017" in this example) and selecting File > Unload Hive . If you don't do this, VS won't be able to read the privateregistry.bin file when it runs, causing major problems.
Update:
It also works on Visual Studio 2019 (version 16.0) too.
There is an option you can select "Find results table".
Then you can do a Ctrl+ALL and copy the tab delimited results to a spreadsheet such as Excel. Then you can see only the code instead of file names.

Find files in project/solution that no longer exist

Visual Studio 2010 has a bug (or annoying behavior) that it always starts a new build for a project if it includes a reference to a (source) file that no longer exists (and subsequently all depending projects). Now I have a rather large project and the only way I know of to find such files is to manually open every file.
Is there an easier way to identify such invalid references in project files?
I wrote a python script that identifies missing files and prints them to the console.
import os
import re
import sys
def show_help():
print()
print("Syntax:", sys.argv[0], "[filename]")
print()
def check_missing_project_includes(filename):
f = open(filename, 'r')
p = re.compile('(ClCompile|ClInclude) Include="(.*?)" />', re.IGNORECASE)
missing_files = []
for line in f:
m = re.search(p, line)
if m:
filename = m.group(2)
if not os.path.exists(filename):
missing_files.append(filename)
return missing_files
if len(sys.argv) != 2:
show_help()
exit()
filename = sys.argv[1]
missing_files = check_missing_project_includes(filename)
if len(missing_files) > 0:
print("Missing files:")
for mf in missing_files:
print("\t", mf)
A technique that I've used to diagnose missing files is to install a SCC provider Addin (eg AnkhSVN if you're using Subversion), then in the Solution Explorer missing files will have a different icon. This isn't as useful for larger projects, but for smaller ones it's quite quick to see at a glance.
Have you tried opening the proj file in an editor like Notepad++ and locate and remove the references from there? (If I'm understanding the question correctly that is)

Visual Studio 2010 plugin to show current file EOL style

It seems the EOL style in our current project isn't consistent. I'm looking for a Visual Studio plugin/extension to show the EOL style in the currently opened file as either LF, CRLF or Mixed.
try to used the below codes
Dim TextLine As String
FileOpen(1, "TESTFILE", OpenMode.Input) ' Open file.
Do While Not EOF(1) ' Loop until end of file.
TextLine = LineInput(1) ' Read line into variable.
Debug.WriteLine(TextLine) ' Print to the Command window.
Loop
FileClose(1)
Not exactly what you looking for, but there is a build-in feature:
Tools -> Options
Environment -> Documents -> Check for consistent line endings on load

How to automatically add a huge set of .vcproj files to the solution?

I have a huge set of .vcproj files (~200) stored in different locations. I have a list of these files with full paths.
How can i automatically add them to the solution file(.sln) ?
UPD: I'm looking for existing tool/method.
Here's how I'd do it:
Create and save a blank solution to insert the vcproj files into (File->New Project->Other Project Types->Visual Studio Solutions->Blank Solution)
Create a VS macro which adds a project to a solution, saves the solution, and exits. Try the following:
Public Sub AddProjectAndExit(Optional ByVal vcprojPath As String = "")
If Not String.IsNullOrEmpty(vcProjPath) Then
DTE.ExecuteCommand("File.AddExistingProject", vcprojPath)
DTE.ExecuteCommand("File.SaveAll")
DTE.ExecuteCommand("File.Exit")
End If
End Sub
Create a batch script which executes this macro from the Visual Studio command prompt, iterating over each of your .vcproj files. The command for a single execution would be:
devenv.exe BlankSolution.sln /Command "Macros.MyMacros.Module1.AddProjectAndExit MyProject1.vcproj"
Hope that helps!
The .vcproj & .sln files are ascii format, so you could write a macro/script/program to run through your list of projects and insert the proper info into the .sln file. The only additional info you'll need to get about the projects is the project GUID, which can be found in the .vcproj file (assuming your build configurations are the same for each project).
Modify and existing vcwizard.
function CreateCustomProject(strProjectName, strProjectPath)
{
try
{
//This will add the default project to the new solution
prj = oTarget.AddFromTemplate(strProjTemplate, strProjectPath, strProjectNameWithExt);
//Create a loop here to loop through the project names
//you want to add to the new solution.
var prjItem = oTarget.AddFromFile("C:\\YourProjectPath\\YourProject.vcproj", false);
}
return prj;
}
catch(e)
{
throw e;
}
}

Resources