belav / csharpier

CSharpier is an opinionated code formatter for c#.

Home Page:https://csharpier.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How can I make CSharpier work with Visual Studio?

Dennis-N8 opened this issue · comments

Environments

  • IDE Version: Microsoft Visual Studio Community 2022 (64-bit) - Current
    Version 17.9.6
  • Extension Version: 1.7.1
  • CSharpier Version: 0.28.2
  • Operating System: Windows 10 Pro
  • .csharpierrc Settings: Not present
  • .editorconfig Settings: Not present

Log Output
[Info - 4/30/2024 19:30:53] Formatting started for C:...\CarController.cs using CSharpier 0.28.2
[Warn - 4/30/2024 19:30:53] Failed posting to the csharpier server. System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: The requested address is not valid in its context 127.0.0.1:0
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at CSharpierProcessServer.formatFile(FormatFileParameter parameter)
[Info - 4/30/2024 19:30:53] Formatted in 1ms

Steps to reproduce
Right click inside any .cs file in Visual Studio and select 'Format With CSharpier'

Expected behavior
It should work as expected

Actual behavior
It doesn't format the .cs file.

The output of 'dotnet --list-sdks':
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.204 [C:\Program Files\dotnet\sdk]

global.json content
{ "sdk": { "version": "7.0.401" } }

With and without global.json the CSharpier extension doesn't work.

Also, how can I make the CSharpier work with latest dotnet sdk regardless which sdk version is in global.json?

Based on the fact it is trying to connect using port 0, I believe it is failing to start the csharpier server but not detecting that it failed to start. Can you enable debug logging? That will hopefully point me in the direction of the problem.

If you need to get things working in the short term using csharpier 0.27.x will use the older style of communication. I don't see an obvious way to downgrade the extension to 1.5.x which would also use the older style of communication with 0.28.x

image

The CSharpier output I posted at the beginning was with enabled debug logging.

image

image

Sometimes it starts.

image

What I did differently now is:

  1. ran the command: dotnet tool update csharpier
  2. deleted the 'global.json' file
  3. closed the Visual Studio a few times after that.

I'm not sure which of these commands helped. Maybe both.

The difference between these two is: in the first screenshot Visual Studio on start doesn't check for 'dotnet-tools.json'.

The solution which contains the .config directory (with dotnet-tools.json) has several C# projects.

image

But this solution is temporary. After I restart the computer - it doesn't work again.

I did find a path through the code that would cause the extension to try formatting with 0 as a port, but it should still produce a warning. If csharpier fails to start after 2 seconds it was giving up but not flagging it as unable to start. I believe 1.7.2 will prevent the extension from trying to call csharpier on port 0, and instead log "CSharpier process failed to start. Formatting cannot occur., which still doesn't tell us why it isn't starting for you.

The output of CSharpier should always start with this line, maybe your output is getting cleared somehow?
[Info - 5/3/2024 10:44:18 AM] Starting

You can try running the command the extension uses to start csharpier, it would be

C:\Users\[UserName]\AppData\Local\CSharpier\[Version]\dotnet-csharpier.exe --server

You should see info from kestrel starting up and which port it is on.

I'm not sure if the global.json file would affect how the extension makes that call, I don't set WorkingDirectory on ProcessStartInfo so I believe it uses the directory that contains dotnet-csharpier.

If all else fails you could also try debugging the extension

https://github.com/belav/csharpier/blob/main/Src/CSharpier.VisualStudio/CONTRIBUTING.md has some basic instructions

https://github.com/belav/csharpier/blob/main/Src/CSharpier.VisualStudio/CSharpier.VisualStudioShared/CSharpierProcessServer.cs#L38 is where the extension is trying to start csharpier.

This is the output when it starts. You are correct, it starts with Starting

image

So I closed the Visual Studio and re-opened it. Now the extension version is 1.7.2

I got this message:
image

Clicking on the link opened this page: https://csharpier.com/docs/EditorsTroubleshooting

And this was in Output:
image

Deleting the global.json, running the 'dotnet tool update csharpier' and reopening VS helps.

Maybe on timeout try to start the process on one/several default port(s)?

Can you run this to see what it does? It already tries to find a free port when starting

C:\Users\[UserName]\AppData\Local\CSharpier\[Version]\dotnet-csharpier.exe --server

So I closed and reopened the Visual Studio while the command was running in console.
And I could format the code.

Strange.

Today running the command dotnet csharpier --server before opening the project in Visual Studio helped.
Will try again tomorrow.

I am running into the same issue. This morning, I couldn't get csharpier to boot up properly in VS, even after a few restart.

Starting the server on another terminal prompted me for network permissions, which I allowed, and ran on the same port as in Dennis' last screenshot. Then started VS and it booted another server, as it connected to port 49153 instead of 49152 from the server running in the other terminal. Killed the server & VS, started VS again and csharpier seems fine, and connected to port 49152.

This is very erratic on my end, hopefully allowing the network access will have fixed things... but if not, perhaps adding logs from the server in VS's debug output could help pinpoint the issue?

So with or without global.json the CSharpier doesn't start when dotnet csharpier --server is running.

But it started to work after I closed Visual studio, ran dotnet tool update csharpier and re-opened the Visual Studio.

Today the dotnet tool update csharpier helped too, but I had to close and reopen Visual Studio twice.

When dotnet csharpier --server is run, it attempts to find an open port at 49152 or higher. If you run that from the terminal, the extension will start up a second instance of csharpier, which will find a different port and connect to that.

The extension has no way of knowing that an instance of csharpier was started already and is running which is why it may end up with a different port. Additionally the extension can be running multiple instances of csharpier, one per version. TLDR, the different/erratic port numbers is expected.

@yonguelink was the prompt you got like this?
image

CSharpier binds kestrel to 127.0.0.1 which should avoid that. I was getting the popup initially when I was binding to "any" ipaddress.

Adding logging to the csharpier end is a good idea, getting it back into the extension is harder. But as long as it logs to a known location that would work.

I think for know I'm going to see if I can get the VS extension to try to find a port, and also add an option to completely bypass csharpier server. With VS trying to find the port it will be much easier to log/debug.

Sorry for the picture of a screen - snipping tool didn't want to take the prompt in screenshot (probably due to elevated permissions?)

This is the prompt I got when starting csharpier via the terminal:

image

Note that the server doesn't seem to mind and just runs

image

Hitting cancel or allow has no effect on the actual behavior

I guess completely bypassing the server would be an effective workaround until the issue is found...

As a side note, I noticed that the issue happens pretty much all the time when I first boot my computer, but doesn't appear as often (if at all? I don't restart my IDEs that often outside of the daily reboot, but I haven't really noticed failure during those).

@yonguelink you probably have a version 0.27.x installed globally. That's the version that binds to 0.0.0.0, which causes the network popup. The extension will only run --server on 0.28.x

I have the changes I mentioned done and released as 1.7.3. I also realized that when csharpier --server was not responding with a port as expected that the extension wasn't reading from stderr, only stdout. Maybe that will help debug this issue.

The new option to skip csharpier server. I added the server option to make it easier to respond to the extension with information beyond just the contents of the formatted file. IE the server can respond with "this file is ignored, this file has compilation errors, etc". The older version that pipes the file back and forth still works and I don't foresee removing it.

I ran the dotnet tool update csharpier command and closed the Visual Studio 2 times.
Extension version 1.7.3

The output looks like this:

image

So the CSharpier server timed out, but when I selected to format the C# file - it did it.

@yonguelink you probably have a version 0.27.x installed globally.

Oh right, I just verified, I forgot to update that beforehand 😅

I have the changes I mentioned done and released as 1.7.3. I also realized that when csharpier --server was not responding with a port as expected that the extension wasn't reading from stderr, only stdout. Maybe that will help debug this issue.

The new option to skip csharpier server. I added the server option to make it easier to respond to the extension with information beyond just the contents of the formatted file. IE the server can respond with "this file is ignored, this file has compilation errors, etc". The older version that pipes the file back and forth still works and I don't foresee removing it.

Thank you, I just updated the extension. I'll update tomorrow on how things go!

EDIT: A few days later, and no issue remains! Thank you!

I ran into this issue today. It's an issue I've run into randomly at different times in the last 4-5 years with different tools (some written by me).

Windows prevent the use of a range of ports by users for "operating system stuff". Rather than just selecting an unused port, it likes to reserve huge chunks of ports for itself and prevent anything from using them. From memory, the range of ports that are reserved shifts every bootup. This is why it randomly appears and disappears.

Unless you want to keep rebooting until the stars align, below are some instructions to alleviate your headaches.


For users:

  1. Confirm this issue is affecting you.
    In an elevated powershell, run: netsh interface ipv4 show excludedportrange protocol=tcp
    Check the list of excluded ranges to see if port 49152 is blocked.
    The rest assumes this is your issue.

  2. If you want to be cautious: stop any VMs or docker containers before proceeding until winnat is restarted.

  3. Run net stop winnat to release the exclusions.

  4. Run netsh interface ipv4 show excludedportrange protocol=tcp again to ensure the ports are no longer excluded.

  5. Don't celebrate yet, winnat is important and we want to ensure this doesn't happen again.

  6. Run netsh int ipv4 set dynamic tcp start=49180 num=16356 to define that excluded ports should be between 49180-65536

  7. Run net start winnat to re-enable NAT.

With a bit of luck, you should be good to go.


For @belav: you can reduce the frequency of this issue by modifying how you find an open port.
Instead of incrementing by 1 for example, try poking in different port ranges. Try 19152, 24152, 29152, ...
Also, I came across more than 1 source that suggests people use 49152 - 65536 as their exclusion range.
I don't know if you're attached to 49152, but your tool might run into this issue more often because of this.

@mheguy-flo Thank you. Today csharpier did not work in VS and it drive me crazy. This fixed for me.

@mheguy-flo thanks for all the info, finally explains the random issues people are running into.

I did a basic test of this by finding a port windows had reserved, and modifying csharpier to use that port as the starting point. This did result in a failure.

I was toying with ideas for dealing with this and ran across a blog post that gave me a good idea - just let kestrel pick its own open port. It seems safe to assume that the aspnetcore team has solved the problem of finding a free port already.

I am thinking I'll modify the extensions to stop using csharpier server on 0.28.X to avoid anyone else running into this.

We are waiting for a release))

Result of dotnet csharpier --server command

image

@Dennis-N8: There hasn't been a release to fix this issue yet. I suggest you check my comment above if you want a workaround.

Oh, It helped, thank you)

@Dennis-N8: There hasn't been a release to fix this issue yet. I suggest you check my comment above if you want a workaround.

image

I just installed the new version of extension for Visual Studio.
Although it showed the Warning, it worked.