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
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.
So I closed the Visual Studio and re-opened it. Now the extension version is 1.7.2
Clicking on the link opened this page: https://csharpier.com/docs/EditorsTroubleshooting
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?
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:
Note that the server doesn't seem to mind and just runs
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.
@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:
-
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. -
If you want to be cautious: stop any VMs or docker containers before proceeding until winnat is restarted.
-
Run
net stop winnat
to release the exclusions. -
Run
netsh interface ipv4 show excludedportrange protocol=tcp
again to ensure the ports are no longer excluded. -
Don't celebrate yet, winnat is important and we want to ensure this doesn't happen again.
-
Run
netsh int ipv4 set dynamic tcp start=49180 num=16356
to define that excluded ports should be between 49180-65536 -
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))
@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.