24

Is it possible to run auto-format code for all or for specific file in solution, like (Ctrl+K, Ctrl+D) formatting in Visual Studio but from it`s command line? Or use Resharper's cleanup also from command line for solution files?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 2
    Have you tried anything? Would you show us? – Hanlet Escaño Mar 22 '13 at 22:06
  • I don't think (am afk atm so unable to test) that Ctrl+K, Ctrl+D is exclusive to ReSharper, so maybe that tag in your question is unnescessary! – JMK Mar 22 '13 at 22:25
  • This answer says that Resharper API is not usefull: http://stackoverflow.com/questions/13729649/resharpening-from-the-command-line?rq=1 This suggestion http://www.narrange.net/doc/index.htm provides third party console tool. Interesting, is it something new in new versions of VS2012 that adds such new features to command line? – Александр Киричек Mar 22 '13 at 22:26
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Mar 22 '13 at 22:27
  • Thanks you Jhon. JMK, Ctrl+K, Ctrl+D is for IDE. For Resharper exclusive is clean-up. – Александр Киричек Mar 22 '13 at 22:33

5 Answers5

12

Create your own tool. You can use EnvDTE, EnvDTE80 to create Visual Studio project and load the files you want to format on the fly. Once you are done delete the Visual Studio project. You can specify to not to show Visual Studio window while formatting. If you are interested let me know I can give you some code to make this work.

UPDATE: I am copying the code I have. I used it to format *.js files. I removed some code which you don't need. Feel free to ask if it doesn't work.

    //You need to make a reference to two dlls:
    envdte
    envdte80



    void FormatFiles(List<FileInfo> files)
    {       
        //If it throws exeption you may want to retry couple more times
        EnvDTE.Solution soln = System.Activator.CreateInstance(Type.GetTypeFromProgID("VisualStudio.Solution.11.0")) as EnvDTE.Solution;
        //try this if you have Visual Studio 2010
        //EnvDTE.Solution soln = System.Activator.CreateInstance(Type.GetTypeFromProgID("VisualStudio.Solution.10.0")) as EnvDTE.Solution;
        soln.DTE.MainWindow.Visible = false;
        EnvDTE80.Solution2 soln2 = soln as EnvDTE80.Solution2;
        //Creating Visual Studio project
        string csTemplatePath = soln2.GetProjectTemplate("ConsoleApplication.zip", "CSharp");
        soln.AddFromTemplate(csTemplatePath, tempPath, "FormattingFiles", false);
        //If it throws exeption you may want to retry couple more times
        Project project = soln.Projects.Item(1);

        foreach (FileInfo file in files)
        {
            ProjectItem addedItem;
            bool existingFile = false;
            int _try = 0;
            while (true)
            {            
                try
                {
                    string fileName = file.Name;
                    _try++;
                    if (existingFile)
                    {
                        fileName = file.Name.Substring(0, (file.Name.Length - file.Extension.Length) - 1);
                        fileName = fileName + "_" + _try + file.Extension;
                    }
                    addedItem = project.ProjectItems.AddFromTemplate(file.FullName, fileName);
                    existingFile = false;
                    break;
                }
                catch(Exception ex)
                {
                    if (ex.Message.Contains(file.Name) && ex.Message.Contains("already a linked file"))
                    {
                        existingFile = true;
                    }
                }
            }
            while (true)
            {
                //sometimes formatting file might throw an exception. Thats why I am using loop.
                //usually first time will work
                try
                {
                    addedItem.Open(Constants.vsViewKindCode);
                    addedItem.Document.Activate();
                    addedItem.Document.DTE.ExecuteCommand("Edit.FormatDocument");
                    addedItem.SaveAs(file.FullName);
                    break;
                }
                catch
                {
                    //repeat
                }
            }
        }
        try
        {
            soln.Close();
            soln2.Close();
            soln = null;
            soln2 = null;
        }
        catch
        {
            //for some reason throws exception. Not all the times.
            //if this doesn't closes the solution CleanUp() will take care of this thing
        }
        finally
        {
            CleanUp();
        }
    }   

    void CleanUp()
    {
        List<System.Diagnostics.Process> visualStudioProcesses = System.Diagnostics.Process.GetProcesses().Where(p => p.ProcessName.Contains("devenv")).ToList();
        foreach (System.Diagnostics.Process process in visualStudioProcesses)
        {
            if (process.MainWindowTitle == "")
            {
                process.Kill();
                break;
            }
        }
        tempPath = System.IO.Path.GetTempPath();
        tempPath = tempPath + "\\FormattingFiles";
        new DirectoryInfo(tempPath).Delete(true);
    } 

I hope this helps.

Dilshod
  • 3,189
  • 3
  • 36
  • 67
  • COMExceptions can be easily solved by properly implementing message filtering as described [here](http://stackoverflow.com/a/31560298/3242721). – Michal Hosala Apr 06 '16 at 10:38
5

As a followup to Dilshod's post, if you're just looking to format a single file, here's a way of doing it that won't need a temporary path:

static void FormatFile(string file)
{
    EnvDTE.Solution soln = System.Activator.CreateInstance(
        Type.GetTypeFromProgID("VisualStudio.Solution.10.0")) as EnvDTE.Solution;

    soln.DTE.ItemOperations.OpenFile(file);

    TextSelection selection = soln.DTE.ActiveDocument.Selection as TextSelection;
    selection.SelectAll();
    selection.SmartFormat();

    soln.DTE.ActiveDocument.Save();
}

Note that "file" will need to have the full path on disk in all likelihood. Relative paths don't seem to work (though I didn't try all that hard).

Jay Lemmon
  • 1,158
  • 1
  • 8
  • 22
  • Also, for completeness you'd probably want to implement this COM listener to catch for some random busy errors you can get: http://msdn.microsoft.com/en-us/library/ms228772.aspx – Jay Lemmon Dec 08 '13 at 02:47
  • This solution doesn't work for me. It throws errors on trying to use `SmartFormat`. I also implemented the `MessageFilter ` – Patrick Magee Apr 17 '15 at 10:59
  • Which version of Visual Studio are you using? You'll need to make sure your "VisualStudio.Solution.10.0" matches your version. eg: for VS2013, it should be "VisualStudio.Solution.12.0". If that doesn't work, you can see what I'm currently doing at http://svn.darwinbots.com/Darwinbots3/Trunk/Modules/Reformatter/Program.cs and see if there's something there I'm doing I'm not mentioning. Works on my machine :) – Jay Lemmon Apr 17 '15 at 18:10
  • Hi Jay, thanks for responding. I ended up using the `Tools.CommandWindow` and using `document.Activate();` followed by `CommandWindow.SendInput("Edit.FormatDocument")` – Patrick Magee Apr 20 '15 at 09:26
  • @PatrickMagee would you mind posting you complete solutions I encountered the same problem and do not know how to solve. Thanks! – user1935724 Oct 30 '17 at 22:54
5

To format net core c# source, use https://github.com/dotnet/format

Install the tool as per the project readme.

I had a need to format some code files I was generating from Razor templates. I created a shell .CSProj file in the root of my output folder, using dotnet new console which gives you this basic file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <RootNamespace>dotnet_format</RootNamespace>
  </PropertyGroup>

</Project>

Then run dotnet format from a VS command prompt in that folder. It will recurse into sub-directories and format everything it finds. To format specific files you can provide a list of filenames with the --files switch.

Daz
  • 2,833
  • 2
  • 23
  • 30
2

Use CodeFormatter from the .NET Team

  1. Install MSBuild Tools 2015.
  2. Download CodeFormatter 1.0.0-alpha6.
  3. Add CodeFormatter.csproj to the root directory of your projects:

CodeFormatter.csproj

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Compile Include="**\*.cs" />
  </ItemGroup>
  <Target Name="Compile">
    <Csc Sources="@(Compile)"/>
  </Target>
</Project>

Then run this from the Command Line.

> codeformatter.exe CodeFormatter.csproj /nocopyright

The result: all your projects' C# files now adhere to the majority of the .NET Foundation coding guidelines.

Remarks

  • Installing MSBuild Tools 2015 means that we do not need Visual Studio.
  • Adding CodeFormatter.csproj to the root directory recursively includes all C# files, which means the above works with project.json and *.xproj based setups.

See also

http://bigfontblog.azurewebsites.net/autoformat/

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
1

Not possible with Visual Studio, but there are command line utilities for this: http://astyle.sourceforge.net/astyle.html

DasKrümelmonster
  • 5,816
  • 1
  • 24
  • 45