How to enable c# 7 features on Unity3D projects - c#

I wrote a new method in my Unity3D project (using Visual Studio 2017), and for that method I need C# 7 or greater. So I followed the instructions in this guide.
Now, when I try to open the project's properties, Visual Studio opens it, but then it suddenly closes right after opening. Now I can't even open project's properties.
This is how it looks:
Why am I getting the first and third errors? (the ones I showed in the gif)

EDIT
The Roslyn compiler is now supported in Unity 2018.3, which allows you to use the latest C# 7 features!
See: https://blogs.unity3d.com/2018/09/13/unity-2018-3-beta-get-early-access-now/
For Unity3D < 2018.3.*
I will tell you how I have enabled C# 7.3 in Unity3D projects (although some of its features can't be compiled yet). But beware: this method is a hack! It is a premature and experimental usage of C# 7 in Unity.
If you follow the instructions below, I believe you may be able to easily track down the issue, given that in the case of your question it is quite difficult to provide a full MCVE for the SO community. But I believe that what you actually are trying to achieve is enabling C# 7 for Unity, and not solve the bizarre bug in the project properties window.
Before proceeding, I would recommend completely reinstalling Visual Studio 2017 and Unity3D, just to make sure that you are not having any issue related to a bad installation. Always download Unity directly from Unity's webpage instead of using Viual Studio's Installer, so you can get the latest version available.
Enabling C# 7 in Unity 3D projects (tested on Unity3D v.2018.2.10f, VS 2017 v.15.8.5)
First create a new fresh empty project.
Go to Edit -> Project Settings -> Player, find the Other Settings section, then under Configuration / Scripting Runtime Version choose .NET 4.x Equivalent.
We want to tell mcs.exe to process the C# code using the new "experimental" features of C# 7. For that, just create the file mcs.rsp inside your Assets folder. Edit it and write the this line inside it:
-langversion:experimental
Now, create a new folder named Editor inside your Assets folder. Any scripts added to this folder will make Unity create a *.Editor.csproj project file, which holds contain scripts aimed to modify the Unity Editor.
We need to tell Visual Studio that your project supports the C# 7.3 language. This doesn't mean that Unity will be able to compile all features of C# 7.3, but at least Visual Studio will not bitch about the features you are trying to use experimentally.
However if you edit a csproj file directly, Unity will automatically overwrite it at some point (Unity always auto-generate project and solution files). So what you can do is to install a hook which is called when the project file is auto-generated, so you can open the project file yourself and add your customization to it (your customizations are not limited just to changing the language version: you could do more stuff, but you must understand what you are doing here).
For this purpose, place the following script inside the Editor folder:
#if ENABLE_VSTU
using SyntaxTree.VisualStudio.Unity.Bridge;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class ProjectFilesGeneration
{
private class Utf8StringWriter : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
static ProjectFilesGeneration()
{
ProjectFilesGenerator.ProjectFileGeneration += (string name, string content) =>
{
// Ignore projects you do not want to edit here:
if (name.EndsWith("Editor.csproj", StringComparison.InvariantCultureIgnoreCase)) return content;
Debug.Log($"CUSTOMIZING PROJECT FILE: '{name}'");
// Load csproj file:
XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
XDocument xml = XDocument.Parse(content);
// Find all PropertyGroups with Condition defining a Configuration and a Platform:
XElement[] nodes = xml.Descendants()
.Where(child =>
child.Name.LocalName == "PropertyGroup"
&& (child.Attributes().FirstOrDefault(attr => attr.Name.LocalName == "Condition")?.Value.Contains("'$(Configuration)|$(Platform)'") ?? false)
)
.ToArray();
// Add <LangVersion>7.3</LangVersion> to these PropertyGroups:
foreach (XElement node in nodes)
node.Add(new XElement(ns + "LangVersion", "7.3"));
// Write to the csproj file:
using (Utf8StringWriter str = new Utf8StringWriter())
{
xml.Save(str);
return str.ToString();
}
};
}
}
#endif
If you want to fully understand what has changed in your project file, just use any diff tool, to compare the previous version and the new version of the csproj file. The hack above basically does something similar to the link you've posted when changing the language version, except that it does that every time Unity auto-generates the project file. Microsoft also provides plenty of documentation on the definitions inside csproj files.

It looks like you are using Unity (you mention it in your post). I cannot tell by your gif because its like 4 pixels wide.
If you are indeed using Unity, you will be unable to use C# 7 features yet. They've only just allowed experimental support for C# 6 (see here).
Unfortunately you are out of luck if you want to use C# 7 in Unity right now.

The properties window not opening sounds like some issue with your installation of Visual Studio (which I can't give much advice on)
For the coding errors, it looks like you're trying to declare a method inside another method (which is quite odd):
void Update() {
...
public void Method1();
}
I imagine that's not your intention. It's complaining because the version of C# you're compiling in doesn't support that (and local methods in C#7 can't be marked public in any case). It's also complaining because your method isn't abstract (or extern) but doesn't have a body, which C# doesn't allow. Is this what you meant?
void Update() {
if (Input.GetKeyDown(KeyCode.R)) // Note no ; here!
{
GetComponent<Renderer>().material.color = Color.red;
}
}
public void Method1() {
// Some code
}
ALSO you have an erroneous ; after your if () statement in line 15. That will cause the GetComponent<Renderer> line (line 17) to always be run, not just if the condition is true. Again, this is probably not what you intended I imagine.

Related

VS Code will not display errors in my C# script for Unity (possible omnisharp problem)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Driver : MonoBehaviour
{
void Start()
{
}
void Update()
{
// transform.Rotate(0,0,0.1f);
transform.Translate(0,.01f,0);
}
}
above is my code. If I add anything incorrectly, no error appears. It appears to be a problem with omnisharp. I have tried reinstalling, fidgeting with the settings, and installing older versions of the C# extension. However, no matter what I change, errors do not appear as I code.
VS Code cannot automatically complete the code or check errors, and the plugin fails.
The following steps are helpful:
First make sure the plugins are installed.
List of plugins:
Debugger for Unity.
Unity Tools.
Unity Colde Snippets.
Make sure the development environment is complete.
An incomplete development environment can also cause this problem. It is also possible that the .net version created by the project does not match the .net version of the development environment.
Solution:
2.1. Use a text editor to open the file with the extension csproj in the root directory of the project.
2.2. Ctrl + F Search "TargetFrameworkVersion" keyword, you can see the information "v4.7.1". This means that your computer lacks the 4.7.1 version of .net Framework, and different computers default Versions may vary.
2.3. Microsoft official website to download the corresponding version. It should be noted that you need to download the develop pack (development package) version, not the normal version. Otherwise useless.
2.4. Restart vscode.
VS code editor settings.
3.1. Enter the vscode editor and press ctrl + shift + P at the same time.
3.2. Enter in the pop-up input box: OmniSharp: select project.
3.3. Manually select the project file.
Normally, vscode cannot complete the error check because the version of omnisharp is wrong, omnishap may conflict with other versions of your vs code during the upgrade process, so you need to keep omnisharp to the latest version.
Solution:
4.1. Go to the console. Then click on the ouput bar and change the output type to ominisharp log. Windows version shortcut key: ctrl + shift + u.
4.2. Search for ominisharp in the setting.json file of vs code and change its path parameter to latest.
{
"[csharp]": {
"editor.defaultFormatter": "bilal-arikan.csharp-auto-formatter"
},
"omnisharp.path": "latest"
}
4.3. Restart vs code.
Hope it helps you.

Using Visual Studio Code and using defined symbols

EDIT: I have edited the whole question, since this is not only for Unity3D, but at all .sln projects.
I have a installation of Visual Studio Code(Not Visual Studio, but this:https://code.visualstudio.com/) on my Macbook at work. VSCode is otherwise working just fine with normal and Unity3D projects. I get Intellisense on all classes, including Unity3D specific ones, like GameObject. So I think my installation and startup sequence is correct.
Only problem I have, is that VSCode does not seem to recognize constants defined in the .csproj files. First I noticed this with some Unity3D plugins, but it is persistent on normal Visual Studio projects too.
My sample project is a dummy application downloaded from internet, but it is fully working on MonoDevelop. This is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DummyConsoleApplication
{
class Program
{
static void Main(string[] args)
{
tester();
}
#if DEBUG
static void tester(){
}
#endif
}
}
The function call in Main causes a not found exception on the editor, but it compiles fine, since the .csproj file has this line:
<DefineConstants>DEBUG;TRACE</DefineConstants>
Any verification on if this is normal behaviour for VSCode would be greately appreciated. Also, if anyone is aware of any solution, even hacky ones, to get past this bug and force Intellisense to autocomplete would help out too.
The error I get is:
The name 'tester' does not exist in the current context [DummyConsoleApplication]
My hardware is a Macbook with Yosemite and my compiler is dnx-mono.1.0.0-beta4.
This is a known limitation with OmniSharp, the C# engine that Visual Studio Code is built around. There is an open enhancement request for adding <DefineConstants> support, but it is tied to a larger issue with regards to MSBuild Support.
Currently, this isn't a supported configuration under Visual Studio Code. You can try to define your constants through the launch.json instead, but support is minimal at best.
It should work...
As a sanity check, have you:
"Sync MonoDevelop Project" recently?
Make sure Visual Studio Code has the -csharp solution (.sln) selected? (Click the flame in the status bar to change)

Compile/Run C# file in Xamarin Studio on Mac

Sheepishly looking for a short step-by-step guide on taking a single .cs file like:
using System
namespace Simple
{
class Program // declare a class
{
static void Main()
{
Console.WriteLine ("Hi there!");
}
}
}
and be able to compile and run it in Xamarin Studio (version 5.5.1, build 15) on the Mac (Mono SDK is already installed). I am not interested (yet!) in anything complex like developing an app or anything, but just a way to practice learning C#. I do know how to compile and run using Terminal, but can't seem to figure out how to compile/run a simple .cs file from XS. Thanks :) Hopefully my participation here at SO will be a bit more sophisticated in the future :)
I'm assuming you have created a solution and project in Xamarin Studio? There is a run button in the interface (looks like play on a remote). If you created your .cs file outside Xamarin, you'll probably have to import it into the solution by right clicking the project and clicking add files. I'm pretty sure you can also open a .cs in Xamarin without it having any solution/project attachments. Again, you should be able to hit the play button.
If you haven't got yourself a solution, fire up Xamarin to the welcome page and click new solution. You should have the option to choose C# console project (or even an empty project if you want to start from scratch) or something similar (I'm fuzzy on the details: I typically use MonoDevelop and my copy of Xamarin is buggy right now). Fill out the forms and voilĂ ! A "hello world!" file should be there.
Hope this helps!

How do I get Visual Studio's test window to use my ITestContainerDiscoverer?

I'm trying to write a test adapter for Visual Studio 2013 (I'm running Premium with Update 1, and have the VS SDK in, so I could reference all of the VS DLLs). Because it will work off raw content files and not compiled dll/exe's, it seems I need to create an ITestContainerDiscoverer.
I've found a number of public repos online that appear to have implemented these; eg:
TypeScript, Json, Node, and many more
However; my code appears to be same (and the same references to VS DLLs), yet never seems to fire. I've put File.Write, Console.WriteLine, Debuuger.Launch, and also attached another VS instance to it. Here's what my class currently looks like:
[Export(typeof(ITestContainerDiscoverer))]
public class MyTestContainerDiscoverer : ITestContainerDiscoverer
{
[ImportingConstructor]
public MyTestContainerDiscoverer([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
{
File.WriteAllText(#"M:\Coding\Applications\LuaTestAdapter\LuaTestAdapter\bin\Debug\Danny.txt", "TEST!");
Console.WriteLine("IT'S RUNNING!");
Debugger.Launch();
}
public Uri ExecutorUri
{
get { return TestExecutor.ExecutorUri; }
}
public IEnumerable<ITestContainer> TestContainers
{
get
{
return new[] {
new TestContainer(this, #"M:\TestProject\Test.lua")
};
}
}
public event EventHandler TestContainersUpdated;
}
I'm building this in a DLL that ends with .TestAdapter.dll and manually copying it into C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Extensions and then launching VS. The TestAdapter is being correctly loaded by VS, because in the same project my TestDiscoverer (which currently includes DLL as an extension for debugging) is outputting to the console:
[FileExtension(".lua")]
[FileExtension(".dll")]
[DefaultExecutorUri(TestExecutor.ExecutorUriString)]
public class TestDiscoverer : ITestDiscoverer
{
public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink)
{
logger.SendMessage(TestMessageLevel.Informational, "This one works!");
}
}
So I presume it must be something wrong with the TestContainerDiscovered; but I just can't see anything in the samples I found online doing anything differently :O(
Looks like I might have found the difference... If I create a Visual Studio Package project and install my TestAdapter "the old way", then my code executes fine.
It looks like "normal" TestAdapters (eg. those using compiling DLLs/EXEs and therefore can use the provided TestContainerDiscoverers) work fine (this is why NUnit, xUnit etc. can work with NuGet based packages, or copying the DLLs into the Extensions folder), but to get mine to work, I needed it to be installed via a Package project with the following "Asset" included (presumably because of the use of MEF to wire up the ITestContainerDiscoverer).
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="LuaTestAdapter" Path="|LuaTestAdapter|" />
It seems that by default Visual Studio only find test discoverers in .exe and .dll.
So, when you want to extend (e.g. .lua) you need to implement these two interfaces as well:
ITestContainer
ITestContainerDiscoverer
And also the standard ones:
ITestDiscoverer
ITestExecutor
To test if it will run, you can execute this command:
cd Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow
vstest.console.exe /listdiscoverers /useVsixExtensions:True
If it outputs something like this:
It means your discovers are being loaded. Since it is a new one with different file extension I guess you can't just copy the files, I guess it needs to be installed.
When I created this adapter I copied everything from this example provided by Microsoft and modified it. Make sure your vsixmanifest looks the same etc...
Besides examples, I didn't find any actual documentation...
Hope this helps somehow...

Get a list of files in a Solution/Project using DXCore console application

I understand that the following snippets can be used to extract a VS solution info when used in a plug-in.
EnvDTE.Solution solution = CodeRush.ApplicationObject.Solution;
EnvDTE.Projects projects = solution.Projects;
Q: I would like to build a console application and access these file details. My aim is to create a console application (that can be run without VS) to generate a report based on the design issues I find in the input .sln file. What functions do I use for this?
The original (and updated) post is located here.
Actually, DXCore is not designed to be used outside of Visual Studio, but there are always workarounds... In this article I'm going to show you how to use the DXCore Framework inside the regular C# Console Application to parse an entire solution and work with the abstract parsed tree. The solution should be passed-in as an argument to the program as a full complete path to the *.sln file. If there's no argument used, the hard-coded path to the test program is used, so the program will parse itself and print information about the solution, such as a list of all types used and the number of members inside of each class.
Let's create a new C# Console Application, call it TestDXCoreConsoleApp and save it inside the "C:\Project" folder:
Then, we should change the Target Framework version of the new project to Framework 4.0, so it's not a "Target Framework 4.0 Client Profile", because some required assembly references don't support this version of the Target Framework:
Now, let add required assembly references. Here's the list of what we need:
DXCore assemblies:
DevExpress.CodeRush.Common
DevExpress.CodeRush.Core
DevExpress.CodeRush.StructuralParser
DevExpress.CodeRush.VSCore
DevExpress.DXCore.AssemblyResolver
DevExpress.DXCore.Parser
These assemblies canbe found inside your DevExpress IDE Tools installation folder. For example, the path may look like this:
C:\Program Files\DevExpress 2011.1\IDETools\System\DXCore\BIN
Now, three additional assemblies for different program language support:
DX_CPPLanguage
DX_CSharpLanguage
DX_VBLanguage
With these assemblies we are able to parse CSharp, Visual Basic and C++ projects. They can be found here:
C:\Program Files (x86)\DevExpress 2011.1\IDETools\System\DXCore\BIN\SYSTEM
.NET Framework assemblies:
Microsoft.Build.BuildEngine.dll
And, finally, a couple of Visual Studio assemblies:
EnvDTE
VsLangProj
These two can be found in the "PublicAssemblies" folder:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\
Now, the DXCore support code. This code is required to load a solution, its projects and initialize DXCore parsers. I've added two folders:
The Helpers folder contains the following classes:
LanguageHelper.cs - detects the language of projects (e.g. CSharp, Visual Basic or C++).
ParserHelper.cs - initializes DXCore parsers, and a few important DXCore services - the Source Model service and the Language service which are used to parse source code.
SolutionParser.cs - a helper class, which takes the path to the solution that you are going to parse. Calling the GetParsedSolution method will return the SolutionElement, which holds the abstract source tree of the entire solution.
The Loaders folder contains the Visual Studio project and solution loaders for different Visual Studio versions. They are used to parse *.XXproj and *.sln files. There are versions for VS2002, VS2003 and VS2005. There are no dedicated loaders for VS2008 and VS2010, because those loaders for the old VS versions are perfectly fine to reading and loading newer Visual Studio project and solution format files (e.g. 2008, 2010).
Here's the final structure of the TestDXCoreConsoleApp:
The TestDXCoreConsoleApp with the full source is here (267,457 bytes, C#, VS2010), so you may review the code and use it as you'd like. Here's the Main function of the Program class:
static void Main(string[] args)
{
string SolutionPath;
if (args != null && args.Length > 0)
SolutionPath = args[0];
else
SolutionPath = #"c:\Projects\TestDXCoreConsoleApp\TestDXCoreConsoleApp.sln";
try
{
ParserHelper.RegisterParserServices();
Console.Write("Parsing solution... ");
SolutionParser solutionParser = new SolutionParser(SolutionPath);
SolutionElement solution = solutionParser.GetParsedSolution();
if (solution == null)
return;
Console.WriteLine("Done.");
foreach (ProjectElement project in solution.AllProjects)
foreach (SourceFile file in project.AllFiles)
foreach (TypeDeclaration type in file.AllTypes)
{
Console.Write(type.FullName);
Console.WriteLine(", members: " + ((ITypeElement)type).Members.Count);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
ParserHelper.UnRegisterParserServices();
}
Console.ReadLine();
}
If you put the sources into the "C:\Projects" folder and run the program without any arguments specified, you should see the following result:
Press the Enter key to close the window. Bear in mind, that the parsing process may take some time, so you might need to wait a few seconds, until the entire solution is parsed.

Categories

Resources