The command dotnet build for a razor page app with .net-6.0 throws lots of warnings like
CSC : warning RSG002: TargetPath not specified for additional file:
C:\dev\Foo\Foo\Pages\Admin\Administration\Users\Delete.cshtml.
[C:\dev\Foo\Foo\Foo.csproj]
.... lots of other files with the same warning
This is my build engine
C:\dev\Foo\Foo>dotnet build
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Questions
Do all developers need to have the same local file structure?
For example if Sheldon uses C:\dev\foo are Raj and Howard not allowed to use d:\mycode\bar\foo?
How do i specify the TargetPath?
Or in other words What do i have to do to remove the cause for the warning?
Related
In old .NET we used to be able to run the csc compiler to compile a single .cs file or several files.
With .NET Core we have dotnet build that insists on having a proper project file. Is there a stand-alone command line compiler that would allow to compile source code files without having a project (and listing referenced dependencies on the same command line)?
On Linux, when I have the old csc and the new .NET Core installed, I get these timings:
[root#li1742-80 test]# time dotnet build
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
test -> /root/test/bin/Debug/netcoreapp2.0/test.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.94
real 0m7.027s
user 0m5.714s
sys 0m0.838s
[root#li1742-80 test]# time csc Program.cs
Microsoft (R) Visual C# Compiler version 2.3.0.61801 (3722bb71)
Copyright (C) Microsoft Corporation. All rights reserved.
real 0m0.613s
user 0m0.522s
sys 0m0.071s
[root#li1742-80 test]#
Note 7 seconds with .NET Core versus several hundred milliseconds with the old csc for the same file, Program.cs.
I'd like to be able to compile as fast with .NET Core as I used to be able with csc.
Yes, it is possible to compile a single file with csc or vbc compilers in .NET Core.
To invoke the Roslyn compiler directly it is necessary to use the command line driver csc.{exe|dll} and since Roslyn in contrast to the old csc.exe does not reference mscorlib.dll implicitly it is necessary to pass a reference to the required dependencies, i.e. System.Runtime and System.Private.CoreLib libraries and any other required references. The following listing shows how to compile the following Hello, World! program.
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
Using WSL with Ubuntu 16.04 (Xenial Xerus) and dotnet-sdk-2.0.0 installed:
time dotnet /usr/share/dotnet/sdk/2.0.0/Roslyn/csc.exe -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Private.CoreLib.dll -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Console.dll -r:/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/System.Runtime.dll HelloWorld.cs
Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6)
Copyright (C) Microsoft Corporation. All rights reserved.
real 0m0.890s
user 0m0.641s
sys 0m0.250s
ls -li
total 4
4785074604720852 -rw-rw-rw- 1 developer developer 178 Dec 7 15:07 HelloWorld.cs
11821949022487213 -rw-rw-rw- 1 developer developer 4096 Dec 7 15:13 HelloWorld.exe
The required dependencies, which are passed to the compiler, are different on different platforms, i.e. on Windows it is enough to pass System.Runtime.dll and System.Console.dll while on Ubuntu 16.04 it is necessary to pass in addition System.Private.CoreLib.dll. Different SDK versions will have Roslyn and command line drivers located in different places - the SDK layout changes between versions - and the newest 2.2.2 SDK ships with csc.dll and vbc.dll instead of csc.exe and vbc.exe. Therefore, before using this method it is necessary to check your SDK layout.
Detailed explanation
The Roslyn compiler was designed in a bit different way than the previously used csc.exe and vbc.exe compilers. First of all, Roslyn is written in C# and VB.NET and is a managed .NET application. On Windows it used mainly as a common service running in a server process VBCSCompiler.exe (.dll). However, Roslyn ships with managed command line drivers, csc.exe and vbc.exe (the latest .NET SDK versions ship with csc.dll and vbc.dll) which can be used to compile source files directly from the command line. Anyway, it is exactly what the build system in .NET does, invoking Roslyn via the command line. Running a simple dotnet csc.exe -help command will print usage information which will guide in using the compiler directly from the command line (see the last listing).
The major difference between old native compilers and Roslyn is due to the fact that the latter is a managed application is a startup time. Roslyn, even after being compiled to R2R native assemblies (Ready To Run), would need to start by loading the whole .NET framework, initializing it and then loading Roslyn assemblies and starting the compilation process. It is always a bit slower than running the native compiler, however, as can be seen from above timings, not that much slower.
There was a new documentation article added to the corefx repository describing Advanced scenario - Build and run application code with csc/vbc and CoreRun. Anyone interested can use it as a guideline how to work at the low level of .NET Core.
Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6)
Copyright (C) Microsoft Corporation. All rights reserved.
Visual C# Compiler Options
- OUTPUT FILES -
/out:<file> Specify output file name (default: base name of
file with main class or first file)
/target:exe Build a console executable (default) (Short
form: /t:exe)
/target:winexe Build a Windows executable (Short form:
/t:winexe)
/target:library Build a library (Short form: /t:library)
/target:module Build a module that can be added to another
assembly (Short form: /t:module)
/target:appcontainerexe Build an Appcontainer executable (Short form:
/t:appcontainerexe)
/target:winmdobj Build a Windows Runtime intermediate file that
is consumed by WinMDExp (Short form: /t:winmdobj)
/doc:<file> XML Documentation file to generate
/refout:<file> Reference assembly output to generate
/platform:<string> Limit which platforms this code can run on: x86,
Itanium, x64, arm, anycpu32bitpreferred, or
anycpu. The default is anycpu.
- INPUT FILES -
/recurse:<wildcard> Include all files in the current directory and
subdirectories according to the wildcard
specifications
/reference:<alias>=<file> Reference metadata from the specified assembly
file using the given alias (Short form: /r)
/reference:<file list> Reference metadata from the specified assembly
files (Short form: /r)
/addmodule:<file list> Link the specified modules into this assembly
/link:<file list> Embed metadata from the specified interop
assembly files (Short form: /l)
/analyzer:<file list> Run the analyzers from this assembly
(Short form: /a)
/additionalfile:<file list> Additional files that don't directly affect code
generation but may be used by analyzers for producing
errors or warnings.
/embed Embed all source files in the PDB.
/embed:<file list> Embed specific files in the PDB
- RESOURCES -
/win32res:<file> Specify a Win32 resource file (.res)
/win32icon:<file> Use this icon for the output
/win32manifest:<file> Specify a Win32 manifest file (.xml)
/nowin32manifest Do not include the default Win32 manifest
/resource:<resinfo> Embed the specified resource (Short form: /res)
/linkresource:<resinfo> Link the specified resource to this assembly
(Short form: /linkres) Where the resinfo format
is <file>[,<string name>[,public|private]]
- CODE GENERATION -
/debug[+|-] Emit debugging information
/debug:{full|pdbonly|portable|embedded}
Specify debugging type ('full' is default,
'portable' is a cross-platform format,
'embedded' is a cross-platform format embedded into
the target .dll or .exe)
/optimize[+|-] Enable optimizations (Short form: /o)
/deterministic Produce a deterministic assembly
(including module version GUID and timestamp)
/refonly Produce a reference assembly in place of the main output
/instrument:TestCoverage Produce an assembly instrumented to collect
coverage information
/sourcelink:<file> Source link info to embed into PDB.
- ERRORS AND WARNINGS -
/warnaserror[+|-] Report all warnings as errors
/warnaserror[+|-]:<warn list> Report specific warnings as errors
/warn:<n> Set warning level (0-4) (Short form: /w)
/nowarn:<warn list> Disable specific warning messages
/ruleset:<file> Specify a ruleset file that disables specific
diagnostics.
/errorlog:<file> Specify a file to log all compiler and analyzer
diagnostics.
/reportanalyzer Report additional analyzer information, such as
execution time.
- LANGUAGE -
/checked[+|-] Generate overflow checks
/unsafe[+|-] Allow 'unsafe' code
/define:<symbol list> Define conditional compilation symbol(s) (Short
form: /d)
/langversion:<string> Specify language version mode: ISO-1, ISO-2, 3,
4, 5, 6, 7, 7.1, Default, or Latest
- SECURITY -
/delaysign[+|-] Delay-sign the assembly using only the public
portion of the strong name key
/publicsign[+|-] Public-sign the assembly using only the public
portion of the strong name key
/keyfile:<file> Specify a strong name key file
/keycontainer:<string> Specify a strong name key container
/highentropyva[+|-] Enable high-entropy ASLR
- MISCELLANEOUS -
#<file> Read response file for more options
/help Display this usage message (Short form: /?)
/nologo Suppress compiler copyright message
/noconfig Do not auto include CSC.RSP file
/parallel[+|-] Concurrent build.
/version Display the compiler version number and exit.
- ADVANCED -
/baseaddress:<address> Base address for the library to be built
/checksumalgorithm:<alg> Specify algorithm for calculating source file
checksum stored in PDB. Supported values are:
SHA1 (default) or SHA256.
/codepage:<n> Specify the codepage to use when opening source
files
/utf8output Output compiler messages in UTF-8 encoding
/main:<type> Specify the type that contains the entry point
(ignore all other possible entry points) (Short
form: /m)
/fullpaths Compiler generates fully qualified paths
/filealign:<n> Specify the alignment used for output file
sections
/pathmap:<K1>=<V1>,<K2>=<V2>,...
Specify a mapping for source path names output by
the compiler.
/pdb:<file> Specify debug information file name (default:
output file name with .pdb extension)
/errorendlocation Output line and column of the end location of
each error
/preferreduilang Specify the preferred output language name.
/nostdlib[+|-] Do not reference standard library (mscorlib.dll)
/subsystemversion:<string> Specify subsystem version of this assembly
/lib:<file list> Specify additional directories to search in for
references
/errorreport:<string> Specify how to handle internal compiler errors:
prompt, send, queue, or none. The default is
queue.
/appconfig:<file> Specify an application configuration file
containing assembly binding settings
/moduleassemblyname:<string> Name of the assembly which this module will be
a part of
/modulename:<string> Specify the name of the source module
The accepted answer refers to using System.Private.CoreLib.dll which is a runtime assembly and is not recommended. From C# compiler developer's comments:
Attempting to use runtime assemblies as compile references is not
supported and frequently breaks do to the structure of the runtime
assemblies
Instead, reference assemblies should be used. Reference assemblies are fetched from NuGet during dotnet build and a full csc invocation can be seen when running the dotnet CLI with increased verbosity (dotnet build --verbosity normal). One might see references to assemblies like System.Runtime.dll and System.Console.dll from microsoft.netcore.app NuGet package.
However, for a simple single file Hello, World! compilation, one can reference netstandard.dll which for .NET Core 2.2 exists under <installation-directory>/sdk/2.2.203/ref/netstandard.dll.
Note that in order to run the resulting executable with dotnet HelloWorld.exe a corresponding HelloWorld.runtimeconfig.json has to be created, containing the targeting .NET Core runtime version. We will simplify it by creating a common runtimeconfig for console (NETCoreApp) apps, and an accompanying alias csc_run.
Add the following in your ~/.profile:
#!/usr/bin/env sh
# IMPORTANT: make sure dotnet is present in PATH before the next lines
# prepare csc alias
DOTNETDIR=$(dirname $(dirname $(dotnet --info | grep "Base Path" | cut -d' ' -f 6)))
CSCPATH=$(find $DOTNETDIR -name csc.dll -print | sort | tail -n1)
NETSTANDARDPATH=$(find $DOTNETDIR -path *sdk/*/ref/netstandard.dll ! -path *NuGetFallback* -print | sort | tail -n1)
alias csc='dotnet $CSCPATH /r:$NETSTANDARDPATH '
# prepare csc_run alias
if [ ! -w "$DOTNETDIR" ]; then
mkdir -p $HOME/.dotnet
DOTNETDIR=$HOME/.dotnet
fi
DOTNETCSCRUNTIMECONFIG=$DOTNETDIR/csc-console-apps.runtimeconfig.json
alias csc_run='dotnet exec --runtimeconfig $DOTNETCSCRUNTIMECONFIG '
if [ ! -f $DOTNETCSCRUNTIMECONFIG ]; then
DOTNETRUNTIMEVERSION=$(dotnet --list-runtimes |
grep Microsoft\.NETCore\.App | tail -1 | cut -d' ' -f2)
cat << EOF > $DOTNETCSCRUNTIMECONFIG
{
"runtimeOptions": {
"framework": {
"name": "Microsoft.NETCore.App",
"version": "$DOTNETRUNTIMEVERSION"
}
}
}
EOF
fi
Exit and start shell to reload profile (or source it . ~/.profile if you don't want to leave the current session).
Usage:
cat << EOF > ./Program.cs
class Program
{
static void Main() => System.Console.WriteLine("Hello World!");
}
EOF
csc -out:hwapp.exe Program.cs
csc_run hwapp.exe
# Hello World!
The compiler can be directly invoked using
$ /usr/local/share/dotnet/sdk/2.0.0/Roslyn/RunCsc.sh
However, this particular command may not be very helpful without a supporting project infrastructure because you'd need to pass in all .NET Core or .NET Standard reference assemblies in manually, which is normally handled by the SDK and NuGet. You'll get errors like this:
$ /usr/local/share/dotnet/sdk/2.0.0/Roslyn/RunCsc.sh Program.cs
Microsoft (R) Visual C# Compiler version 2.3.2.61921 (ad0efbb6)
Copyright (C) Microsoft Corporation. All rights reserved.
Program.cs(1,7): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
Program.cs(5,11): error CS0518: Predefined type 'System.Object' is not defined or imported
Program.cs(7,26): error CS0518: Predefined type 'System.String' is not defined or imported
Program.cs(7,16): error CS0518: Predefined type 'System.Void' is not defined or imported
This is the scripts:
#!/bin/bash
#dotnethome=`dirname "$0"`
dotnethome=`dirname \`which dotnet\``
sdkver=$(dotnet --version)
fwkver=$(dotnet --list-runtimes | grep Microsoft.NETCore.App | awk '{printf("%s", $2)}')
dotnetlib=$dotnethome/shared/Microsoft.NETCore.App/$fwkver
if [ "$#" -lt 1 ]; then
dotnet $dotnethome/sdk/$sdkver/Roslyn/bincore/csc.dll -help
echo dotnethome=$dotnethome
echo sdkver=$sdkver
echo fwkver=$fwkver
echo dotnetlib=$dotnetlib
exit 1
fi
progfile=$1
prog="${progfile%.*}"
echo -r:$dotnetlib/netstandard.dll > /tmp/$prog.rsp
echo -r:$dotnetlib/System.dll >> /tmp/$prog.rsp
echo -r:$dotnetlib/Microsoft.CSharp.dll >> /tmp/$prog.rsp
for f in $dotnetlib/System.*.dll; do
echo -r:$f >> /tmp/$prog.rsp
done
dotnet $dotnethome/sdk/$sdkver/Roslyn/bincore/csc.dll -out:$prog.dll -nologo #/tmp/$prog.rsp $*
if [ $? -eq 0 ]; then
if test -f "$prog.dll"; then
if ! test -f "$prog.runtime.config"; then
echo "{
\"runtimeOptions\": {
\"framework\": {
\"name\": \"Microsoft.NETCore.App\",
\"version\": \"$fwkver\"
}
}
}" > "$prog.runtimeconfig.json"
fi
fi
fi
echo /tmp/$prog.rsp:
cat /tmp/$prog.rsp
rm /tmp/$prog.rsp
In short, it's not supported without a predefined project.
But #Andrew's comment shows that it's still possible if you are ready to list every single dependency including implicit system ones in command line options.
From error CS0518: Predefined type 'System.Object' is not defined or imported #12393:
At the moment, we have no plan to make it easy to use csc.exe in this
manner. The guidance is to use the dotnet CLI tooling for the time
being. Even if some modification where to be made here, it would be on
the framework to provide unified and/or simplified reference
assemblies for the compiler. The compiler will never have more
complicated type or assembly resolution than it does now (by design).
See also the closed Make it possible to invoke the compiler directly #7689.
I am using dotnet to build a .NET Core C# project from the command line. The project has multiple classes with a main method. Thus I get the error:
$ dotnet build
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.
Test.cs(18,28): error CS0017: Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.
Build FAILED.
Passing the /main switch results in the error:
$ dotnet build /main:Test
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.
MSBUILD : error MSB1001: Unknown switch.
Switch: /main:Test
How can I pass the /main switch to the dotnet command?
You can edit your csproj to define which class to use (inside a PropertyGroup):
<StartupObject>foo.Program2</StartupObject>
or specify this MSBuild property on the command line via:
$ dotnet build foo.csproj -p:StartupObject=foo.Program2
where
namespace foo
{
class Program2{ public static void Main() {} }
}
Just to add why calling dotnet with /main fails with that error, note that it says "Compile with /main"; /main is a parameter for the compiler (csc.exe), not dotnet build. dotnet build will invoke MSBuild.exe which, in turn, will invoke csc.exe, but you'll need to tell dotnet build what the startup class is so it can tell csc.exe. This is what the accepted answer does.
Alternatively, if you were calling csc.exe directly, you could pass /main to it like so...
csc.exe Program.cs Test.cs /main:TestNamespace.Test
I have this rather simple console application I developed using Visual Studio. With it, I have put together a simplistic C# program where using the "Developer Command Prompt for VS2015" I navigate to my directory and run "csc Program.cs" to compile the "Program.exe" file. From there I can type "Program ***" and pass a filename such as "Program file.asm".
Everything is working perfectly. However, I want to run this from the normal command prompt. When I compile within the Developer Command Prompt for VS2015 the below two lines are output:
Microsoft (R) Visual C# Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
And when I navigate I can see that under C:\Windows\Microsoft.NET\Framework I have folder options for:
v1.0.3705
v1.1.4322
v2.0.50727
v3.0
v3.5
v4.0.30319
When I do:
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe C:\directory...\Program.cs
Output is:
Microsoft (R) Visual C# 2008 Compiler Version 3.5.30729.5420 for Microsfot (R) .NET Framework version 3.5
Copyright (C) Microsoft COrporation. All rights reserved.
c:\Users\directory...\Program.cs(5,24): error CS0234: The type or namespace name 'Tasks' does not exist in the namespace 'System.Threading' (are you missing an assembly reference?)
I then tried with v4.0.30319:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe C:\directory...\Program.cs
Which outputs:
Microsoft (R) Visual C# Compiler Version 4.6.1055.0 for C# 5
Copyright (C) Microsoft COrporation. All rights reserved.
This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240
CSCD777AE6152014D6AAEC769E73B879B29.TMP: error CS1567: Error generating Win32 resource: Access is denied.
wrning CS1610: Unable to delete temporary file 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\CSCD777AE6152014D6AAEC769E73B879B29.TMP' used for default Win32 resource -- The system cannot find the file specified.
Can anyone help me understand why this is all working fine for Developer Command Prompt but failing for regular command prompt even when fully quantifying the path for "csc.exe"?
I think you are trying quite a few things without understanding what is happening.
I have put together a simplistic C# program where using the "Developer Command Prompt for VS2015" I navigate to my directory and run "csc Program.cs" to compile the "Program.exe" file.
When you run the C# compiler from this specific command prompt, csc.exe it is in the path. To find out what exact command is being run, on UNIX, we use a command called which. You can try gnu-utils or cygwin, or just manually iterate over all directories specified in the PATH (any case) variable to find out which exact path the csc.exe in question resides. This way you will know what is the exact path of the compiler.
UPDATED: You can use the where command on windows to find the full path of the command (Thanks to #ScottChamberlain)
c:\Users\directory...\Program.cs(5,24): error CS0234: The type or namespace name 'Tasks' does not exist in the namespace 'System.Threading' (are you missing an assembly reference?)
run csc.exe /? at the same prompt and see all the options that the compiler supports. One of them is /r for adding a reference to a dll
When I do:
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe C:\directory...\Program.cs
CSCD777AE6152014D6AAEC769E73B879B29.TMP: error CS1567: Error generating Win32 resource: Access is denied. wrning CS1610: Unable to delete temporary file 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\CSCD777AE6152014D6AAEC769E73B879B29.TMP' used for default Win32 resource -- The system cannot find the file specified.
You probably want to be in the directory of your file Program.cs. This way you have write permissions to the folder for generating necessary output files. You can also use the /out option to specify the output file name
Can anyone help me understand why this is all working fine for Developer Command Prompt but failing for regular command prompt even when fully quantifying the path for "csc.exe"?
Most probably since the PATH environment variable is different. The Visual Studio Command Prompt, sets up a bunch of environment variable after starting the command prompt. You can see the difference in the environment between the two prompts by running the set command on both the terminals and doing a diff of their outputs. Needless to say, certain environment variables will always be different and that is not due to VS.NET
And as #KeithNicholas had mentioned in the comments, you can simply invoke C:\Program Files (x86)\Microsoft Visual Studio *\Common7\Tools\VsDevCmd.bat to set up your regular command prompt like visual studio command prompt
I'm trying to build a module in C# for Powershell 2.0 on a machine where I don't have administrator permissions and no tools installed explicitly for building. I've got almost everything I think I'd need to make this work, but I'm botching the csc call somehow.
My Powershell version is:
PS C:\temp\> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
To get the System.Management.Automation dll out of the CAC, I followed this brilliant advice:
Copy ([PSObject].Assembly.Location) C:\temp
To build with csc, I'm trying to follow this advice from Mr. Skeet:
In addition to this, you can use /noconfig /nostdlib and then
explicitly reference the .NET 2.0 assemblies (in
c:\Windows\Microsoft.NET\Framework\v2.0.50727 for example). It looks
like the /lib command line option can make this slightly easier by
letting you specify a directory to look in for references, but I
haven't tried that myself.
Here's my current command line:
csc /out:shims.dll /target:library /noconfig /nostdlib /lib:c:\Windows\Microsoft.NET\Framework\v2.0.50727 /r:..\System.Management.Automation.dll;System.dll;mscorlib.dll PowershellPlay.cs
That builds fine, but when I try to import the module, I get that I'm using too new a version of the framework -- which, of course, is what I was trying to avoid with the /lib, /nostdlib, and /noconfig settings.
Import-Module : Could not load file or assembly 'file:///C:\temp\PowerCLI_1\shi
ms.dll' or one of its dependencies. This assembly is built by a runtime newer t
han the currently loaded runtime and cannot be loaded.
At line:1 char:14
+ Import-Module <<<< .\shims.dll
+ CategoryInfo : NotSpecified: (:) [Import-Module], BadImageForma
tException
+ FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerSh
ell.Commands.ImportModuleCommand
Wonder if I have to change which csc I use? Doesn't seem like that should be a requirement/matter.
c:\temp>where csc
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe
EDIT: Okay, I think I've got the answer: I'm doing things in my code that aren't .NET 2.0 kosher. I'm a little surprised the 2.0 version of csc seems to compile it, though. ??
Anyhow, the below works:
Code for cmdlet:
using System;
using System.Management.Automation;
[Cmdlet("Test", "PowershellCompilation")]
public class Test : Cmdlet
{
[Parameter]
public string Server = "";
protected override void ProcessRecord()
{
WriteObject(this.Server + "test");
}
}
csc call:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\csc /out:test.dll /target:library /r:..\System.Management.Automation.dll Test.cs
I've got that call in a bat file named buildTest.bat.
PS C:\temp\PowerCLI_1> .\buildTest.bat
C:\temp\PowerCLI_1>C:\Windows\Microsoft.NET\Framework64\v2.0.50727\csc /out:test
.dll /target:library /r:..\System.Management.Automation.dll Test.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.5483
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
PS C:\temp\PowerCLI_1> Import-Module .\test.dll
PS C:\temp\PowerCLI_1> Test-PowershellCompilation
test
PS C:\temp\PowerCLI_1> Test-PowershellCompilation -Server spam
spamtest
PS C:\temp\PowerCLI_1>
Note that I was unable to get the 4.0 version of csc to work using a command like this:
csc /out:test.dll /target:library /noconfig /nostdlib /lib:c:\Windows\Microsoft.NET\Framework\v2.0.50727 /r:..\System.Management.Automation.dll;System.dll;mscorlib.dll Test.cs
That gave the "runtime newer" error again.
So success. I'll try to convince Eris to turn the comment into an answer; if I'd tried the 2.0 version of csc first, I wouldn't've tried the "compile for 2 with csc for 4" madness.
Try using
[Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()\csc.exe
PowerShell v2 uses the framework in ...Framework64\v2.0.50727
C# CSC.exe
If we give it a C# file, a .CS , is it able to compile it and say for example a ";" is missing at line 12 of your code? In a form that later in my program - which is Java RCP app, I can show those compile errors in a Spreadsheet
How about MSBuild? Is that able to show compile errors same as my previous example?
Think of MSBuild as a glorified make or something more like ANT - it is a language for describing compilation/build tasks. When you use MSBuild for building your c# program, you are actually using csc.exe for the compilation part.
Say this is your code (program.cs):
namespace MyCustomBuild
{
class Program
{
static void Main(string[] args)
{
System.Console.WriteLine("Hello World")
}
}
}
You can call csc program.cs and receive the following output
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.
program.cs(7,52): error CS1002: ; expected
Alternatively you can use msbuild to achieve the exact same result! Here is the content of build.msbuild
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Default">
<Csc Sources="program.cs"/>
</Target>
</Project>
You can then call your msbuild file with varying levels of verbosity, as shown.
msbuild build.msbuild /verbosity:quiet and msbuild build.msbuild /verbosity:minimal
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.269]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
program.cs(7,52): error CS1002: ; expected [<filePath>\build.msbuild]
msbuild build.msbuild /verbosity:normal:
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.269]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 6/6/2012 12:13:00 PM.
Project "<filePath>\build.msbuild" on node 1 (default targets).
Default:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /out:program.exe program.cs
program.cs(7,52): error CS1002: ; expected [<filePath>\build.msbuild]
Done Building Project "<filePath>\build.msbuild" (default targets) -- FAILED.
Build FAILED.
"<filePath>\build.msbuild" (default target) (1) ->
(Default target) ->
program.cs(7,52): error CS1002: ; expected ["<filePath>\build.msbuild]
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.28
The remaining two verbosity levels are detailed and diagnostic and they present even more information if you want it. I'm not sure how much information you want for your spreadsheet, but hopefully one of these works for you.