Saturday, July 02, 2016

Trying out .NET Core and VS Code - Console Hello World

This is part of the .NET Core and VS Code series, which contains:
Since the release of .NET Core 1.1, a lot has changed, so I am trying to keep this up to date as much as possible, but there still might be some leftover obsolete info from earlier versions.


Debug console output So .NET Core was released and I started wondering if I could go full in, ignoring the usual way to work with .NET (you know, framework, Visual Studio, ReSharper, all that wonderful jazz). Well, five minutes in and I am worried. It looks like someone is trying to sell me developing in online editors packaged in a skinny app, just so that I run away scared back to the full Visual Studio paid stack. Yet, I'm only five minutes in, so I am going to persevere.

Installation


Getting started (on Windows) involves three easy steps:
  1. Download and install the .NET Core SDK for Windows (if you want the complete Core, that works with Visual Studio, go here for more details. This is the freeware version of getting started :) )
  2. Download and install Visual Studio Code which ironically needs .NET 4.5 to run.
  3. After running Code, press Ctrl-P and in the textbox that appears write 'ext install csharp', wait for a dropdown to appear and click on the C# for Visual Studio Code (powered by Omnisharp) entry to install support for C#

Now you understand why I am a little worried. By default, VS Code comes with built-in support for JavaScript, TypeScript and Node.js. That's it!

Visual Studio Code overview


Next stop, read up on how Code works. It's a different approach than Visual Studio. It doesn't open up projects, it opens up folders. The project, configuration, package files, even the settings files for Code itself, are json, not XML. The shortcut you used earlier is called Quick Open and is used to install stuff, find files, open things up, etc. Another useful shortcut is F1, which doesn't pop up some useless help file, but the Command Palette, which is like a dropdown for menu commands.

And, of course, as for any newly installed software, go immediately to settings and start customizing things. Open the File menu, go to Preferences and open User Settings and you will be amazed to see that instead of a nice interface for options you get two side-by-side json files. One is with the default settings and the other one is for custom settings that would override defaults. Interestingly, I see settings for Sass and Less. I didn't see anything that needed changing right from the start, so let's go further.

Another thing that you notice is the left side icon bar. It contains four icons:
  • Explorer - which opens up files and probably will show solutions
  • Search - which helps you search within files
  • Debug - I can only assume that it debugs stuff
  • Git - So Git is directly integrated in the code editor, not "source control", just Git. It is an interesting statement to see Git as a first class option in the editor, while support for C# needs to be installed.

Hello world! - by ear


A little disappointing, when you Open a Folder from Explorer, it goes directly to My Documents. I don't see a setting for the initial projects folder to open. Then again, maybe I don't need it. Navigate to where you need to, create a new folder, open it up. I named mine "Code Hello World", because I am a creative person at heart. Explorer remains open in the left, showing a list of Working Files (open files) and the folder with some useful options such as New File, New Folder, Refresh and Collapse All. Since we have opened a folder, we have access to the File → Preferences → Workspace Settings json files, which are just like the general Code settings, only applying to this one folder. Just opening the files creates a .vscode/settings.json empty file.

Let's try to write some code. I have no idea what I should write, so let's read up on it. Another surprise: not many articles on how to start a new project. Well, there is something called ASP.Net Core, which is another install, but I care not about the web right now. All I want is write a short Hello World thing. There are some pages about writing console applications with Code on Macs, but you know, when I said I am a creative person I wasn't going that far! I go to Quick Open, I go to the Command Palette, nothing resembling "new project" or "console app" or "dotnet something". The documentation is as full of information as a baby's bottom is full of hair. You know what that means, right? It's cutting edge, man! You got to figure it out yourself!

So let's go from memory, see where it gets us. I need a Program.cs file with a namespace, a Program class and a static Main method that accepts an array of strings as a first argument. I open a new file (which also gets created under the .vscode folder) and I write this:
namespace CodeHelloWorld
{
    public class Program {
        static void Main(string[] args) {
            Console.WriteLine("Hello World!");
        }
    }
}
I then go to the Debug icon and click it.
It asks me to select the environment in which I will debug stuff: NodeJS, the Code extension environment and .Net Core. I choose .Net Core and another configuration file is presented to me, called launch.json. Now we are getting somewhere! Hoping it is all good - I am tired of all this Linuxy thing - I press the green Debug arrow. Oops! It appears I didn't select the Task Runner. A list of options is presented to me, from which two seem promising: MSBuild and .NET Core. Fuck MSBuild! Let's go all Core, see if it works.

Choosing .NET Core creates a new json file, this time called tasks.json, containing a link to documentation and some settings that tell me nothing. The version number for the file is encouraging: 0.1.0. Oh, remember the good old Linux days when everything was open source, undocumented, crappy and everyone was cranky if you even mentioned a version number higher or equal to 1?

I press the damn green arrow again and I get another error: the preLaunchTask "build" terminated with exit code 1. I debug anyway and it says that I have to configure launch.json program setting, with the name of the program I have to debug. BTW, launch.json has a 0.2.0 version. Yay! Looking more carefully at the launch.json file I see that the name of the program ends with .dll. I want an .exe, yet changing the extension is not the only thing that I need to do. Obviously I need to make my program compile first.

I press Ctrl-P and type > (the same thing can be achieved by Ctrl-Shift-P or going to the menu and choosing Command Palette) and look for Build and I find Tasks: Run Build Task. It even has the familiar Ctrl-Shift-B shortcut. Maybe that will tell me more? It does nothing. Something rotates in the status bar, but no obvious result. And then I remember the good old trusty Output window! I go to View and select Toggle Output. Now I can finally see what went wrong. Can you guess it? Another json file. This time called project.json and having the obvious problem that it doesn't exist. Just for the fun of it I create an empty json file and it still says it doesn't exist.

What now? I obviously have the same problem as when I started: I have no idea how to create a project. Armed with a little bit more information, I go browse the web again. I find the documentation page for project.json, which doesn't help much because it doesn't have a sample file, but also, finally a tutorial that make sense: Console Application. And here I find that I should have first run the command line dotnet new console in the folder I created, then open the project with VS Code.

Hello world! - by tutorial


Reset! Close Code, delete everything from the folder. Also, make sure - if you run a file manager or some other app and you just installed .NET Core - that you have C:\Program Files\dotnet\ in the PATH. Funny thing: the prompt for deleting some files from Code is asking whether to send them to Recycle Bin. I have Recycled Bin disabled, so it fails and then presents you with the option to delete them permanently.

Now, armed with knowledge I go to the folder Code Hello World, run the command 'dotnet new console' ("console" is the name of the project template. Version 1.0 allowed you to omit the template and it would default to console. From version 1.1 you need to specify it explicitly) and it creates a project.json .csproj file (with the name of the folder you were in) and a Program.cs file that is identical to mine, if you count the extra using System line. I run 'dotnet restore', 'dotnet build' and I notice that obj and bin folders have been created. The output, though, is not an exe file, but a dll file. 'dotnet run' actually runs as it should and displays "Hello, World!".

Let's open it with Code. I get a "Required assets to build and debug are missing from your project. Add them?" and I say Yes, which creates the .vscode folder, containing launch.json and tasks.json. Ctrl-Shift-B pressed and I get "Compilation succeeded." Is it possible that now I could press F5 and see the program run? No, of course not, because I must "set up the launch configuration file for my application". What does it mean? Well, apparently if I go to the Debug icon and press the green arrow icon (that has the keyboard shortcut F5) the program does run. I need to press the button for the Debug Console that is at the top of the Debug panel to see the result, but it works. From then on, pressing F5 works, too, no matter where I am.

Unconvinced by the whole thing, I decide to do things again, but this time do as little as possible from the console.

Hello world! - by Code


Reset! Delete the folder entirely and restart Visual Studio code. Then proceed with the following steps:
  1. Go to the Explorer icon and click on Open Folder (or FileOpen Folder)
  2. Create a Code Hello World folder
  3. Right click under the folder in Explorer and choose Open in Command Prompt - if you have it. Some Windows versions removed this option from their context menu. If not, select Open in New Window, go to the File menu and select Open Command Prompt (as Administrator, if you can) from there
  4. Write 'dotnet new console' in the console window, then close the command prompt and the Windows Explorer window, if you needed it
  5. Select the newly created Code Hello World folder
  6. From the open folder, open Program.cs
  7. To the warning "Required assets to build and debug are missing from your project. Add them?" click Yes
  8. To the info "There are unresolved dependencies from '<your project>.csproj'. Please execute the restore command to continue." click Restore
  9. Click the Debug icon and press the green play arrow

That's it!


But let's discuss one poignantly ridiculous part of the step list. Why did we have to open and close the folder? It is in order to get that prompt to add required assets. If you try to run the app without doing that, Code will create a generic launch.json file with placeholders instead of actual folder names. Instead of
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": ".NET Core Launch (console)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/Code Hello World.dll",
            "args": [],
            "cwd": "${workspaceRoot}",
            "externalConsole": false,
            "stopAtEntry": false
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach",
            "processId": 0
        }
    ]
}
you get something like
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": ".NET Core Launch (console)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
            "args": [],
            "cwd": "${workspaceRoot}",
            "stopAtEntry": false,
            "externalConsole": false
        },
        {
            "name": ".NET Core Launch (web)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
            "args": [],
            "cwd": "${workspaceRoot}",
            "stopAtEntry": false,
            "launchBrowser": {
                "enabled": true,
                "args": "${auto-detect-url}",
                "windows": {
                    "command": "cmd.exe",
                    "args": "/C start ${auto-detect-url}"
                },
                "osx": {
                    "command": "open"
                },
                "linux": {
                    "command": "xdg-open"
                }
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            }
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach",
            "processId": 0
        }
    ]
}
and a warning telling you to configure launch.json. It only works after changing the program property to '/bin/Debug/netcoreapp1.0/Code Hello World.dll' and, of course, the web and attach configuration sections are pointless.


Debugging


I placed a breakpoint on Console.WriteLine. The only declared variable is the args string array. I can see it in Watch (after adding it by pressing +) or in the Locals panel, I can change it from the Debug Console. I can step through code, I can set a condition on the breakpoint. Nothing untoward here. There is no Intellisense in the Debug Console, though.

In order to give parameters to the application in debug you need to change the args property of launch.json. Instead of args:[], something like args:["test",test2"]. In order to run the application from the command line you need to run it with dotnet, like this: dotnet "Code Hello World.dll" test test2.

Conclusion


.Net Code is not nearly ready as a comfortable IDE, but it's getting there, if enough effort will be put into it. It seems to embrace concepts from both the Windows and Linux world and I am worried that it may gain traction with neither. I am yet to try to build a serious project though and next on the agenda is trying an ASP.Net Core application, maybe a basic API.

While I am not blown away by what I have seen, I declare myself intrigued. If creating extensions for Code is easy enough, I may find myself writing my own code editor tools. Wouldn't that be fun? Stay tuned for more!

0 comments: