Compile C# code with code runner with Mono - c#

I am trying to compile this simple C# code on OS X:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("hello");
}
}
This was the code runner template.
I have installed Mono, and the run command is mono $compiler. I first tried using the default Compile.sh file, and it didn't work, so I've found on the web a guide that says to write a shell script like this one:
enc[4]="UTF8" # UTF-8
enc[10]="UTF16" # UTF-16
enc[5]="ISO8859-1" # ISO Latin 1
enc[9]="ISO8859-2" # ISO Latin 2
enc[30]="MacRoman" # Mac OS Roman
enc[12]="CP1252" # Windows Latin 1
enc[3]="EUCJIS" # Japanese (EUC)
enc[8]="SJIS" # Japanese (Shift JIS)
enc[1]="ASCII" # ASCII
file=$1
file=${file/\.cs/\.exe}
mcs "$1"
echo "$file"
exit 0
So I've changed it (backup-ed the old one), but I still get this error on the console:
bash: Run Command: No such file or directory

Unless you have a specific need to compile from the command line, I would strongly suggest using MonoDevelop instead of trying to figure out the appropriate command line parameters.

Related

PowerShell and LuaInterface.dll

LuaInterface
Here is an example on c#
Im newbie. How is properly to call this dll?
I was trying this:
[System.Reflection.Assembly]::LoadFile("E:\\lua\\LuaInterface.dll")
$Lua = new-object LuaInterface.Lua # Here IntelliSense see class lua after dot
$lua.DoString("local a=5") # Here IntelliSense see all methods after dot
And this:
Add-Type -path "E:\lua\LuaInterface.dll"
[LuaInterface.Lua]::DoString("local a=5")
But unsuccessfully. Pls, show me example of "3+2" from LuaInterface.
Methods from class Lua PS somehow cant see.
On screenshot powershell can see methods from luaDLL class. But there needed always one more parameter luastate.
You're really close, but :: is only for static member access.
I got the following working in a 32-bit console (PowerShell 5.1):
# Load LuaInterface
Add-Type -Path path\to\luainterface.dll
# Create Lua instance
$lua = [LuaInterface.Lua]::new()
# Set global variable values
$lua['a'] = 2
$lua['b'] = 3
# return result of `a+b`
$lua.DoString("return a+b")

ANSI-Coloring Console Output with .NET

I try to generate colored console output using ANSI escape codes with the following minimal C# program:
using System;
// test.cs
class foo {
static void Main(string[] args) {
Console.WriteLine("\x1b[36mTEST\x1b[0m");
}
}
I am running Ansicon v1.66 on Windows 7 x64 with csc.exe (Microsoft (R) Visual C# Compiler version 4.6.0081.0).
Colored output works fine in this configuration; Ansicon itself is working flawlessly.
To cross-check I use a node.js one-liner that is 100% equivalent to the C# program:
// test.js
console.log("\x1b[36mTEST\x1b[0m");
And, even more basic, a hand-crafted text file:
Both of which which correctly do the expected thing: Print a teal-colored string "TEST":
Only the test.exe I built with csc prints something else. Why?
I've created a small plugin (available on NuGet) that allows you to easily wrap your strings in ANSI color codes. Both foreground and background colors are supported.
It works by extending the String object, and the syntax is very simple:
"colorize me".Pastel("#1E90FF");
After which the string is ready to be printed to the console.
Your program needs to be compiled for /platform:x64 if you use the AnsiCon x64 environment and with /platform:x86 if you use the AnsiCon x86/32 bits version. The exact reason is a mystery...
Originally I thought you need all this:
You need to grab the StandardOutput and let the Console.WriteLine believe you write to a File instead of to a Console and use an ASCII encoding.
This is how it will work:
var stdout = Console.OpenStandardOutput();
var con = new StreamWriter(stdout, Encoding.ASCII);
con.AutoFlush = true;
Console.SetOut(con);
Console.WriteLine("\x1b[36mTEST\x1b[0m");
The .Net Console.WriteLine uses an internal __ConsoleStream that checks if the Console.Out is as file handle or a console handle. By default it uses a console handle and therefor writes to the console by calling WriteConsoleW. In the remarks you find:
Although an application can use WriteConsole in ANSI mode to write ANSI characters, consoles do not support ANSI escape sequences. However, some functions provide equivalent functionality. For more information, see SetCursorPos, SetConsoleTextAttribute, and GetConsoleCursorInfo.
To write the bytes directly to the console without WriteConsoleW interfering a simple filehandle/stream will do which is achieved by calling OpenStandardOutput. By wrapping that stream in a StreamWriter so we can set it again with Console.SetOut we are done. The byte sequences are send to the OutputStream and picked up by AnsiCon.
Do notice that this is only useable with an applicable terminal emulator, like AnsiCon, as shown here:
I encountered this question today and I could not get the accepted answer to work. After some research on my own I found an answer which will get it to work.
It is a pitty, but we need to go very low level on this and call the Windows API directly. For this purpose I'm using the PInvoke.Kernel32 NuGet for convenience reasons, but if it is too heavy-weight for you, you might create the P\Invoke mapping yourself.
The following method illustrates, how one may activate the ANSI Codes:
bool TryEnableAnsiCodesForHandle(Kernel32.StdHandle stdHandle)
{
var consoleHandle = Kernel32.GetStdHandle(stdHandle);
if (Kernel32.GetConsoleMode(consoleHandle, out var consoleBufferModes) &&
consoleBufferModes.HasFlag(Kernel32.ConsoleBufferModes.ENABLE_VIRTUAL_TERMINAL_PROCESSING))
return true;
consoleBufferModes |= Kernel32.ConsoleBufferModes.ENABLE_VIRTUAL_TERMINAL_PROCESSING;
return Kernel32.SetConsoleMode(consoleHandle, consoleBufferModes);
}
To enable it for StdOut you call it like:
TryEnableAnsiCodesForHandle(Kernel32.StdHandle.STD_OUTPUT_HANDLE);
If the method returns true, the ANSI Codes are enabled, else they are not.
The solution uses the very low level Windows API GetConsoleMode and SetConsoleMode to check if the control buffer mode ENABLE_VIRTUAL_TERMINAL_PROCESSING is set, and if it is not set it tries to set the mode.

Run C# code on linux terminal

How can I execute a C# code on a linux terminal as a shell script.
I have this sample code:
public string Check(string _IPaddress,string _Port, int _SmsID)
{
ClassGlobal._client = new TcpClient(_IPaddress, Convert.ToInt32(_Port));
ClassGlobal.SMSID = _SmsID;
string _result = SendToCAS(_IPaddress, _Port, _SmsID );
if (_result != "") return (_result);
string _acoknoledgement = GetFromCAS();
return _acoknoledgement;
}
When I run a shell bash I use #!/bin/bash. There is how to do the same with C#?
Of course it can be done and the process is extremely simple.
Here I am explaining the steps for Ubuntu Linux.
Open terminal:
Ctrl + Alt + T
Type
gedit hello.cs
In the gedit window that opens paste the following example code:
using System;
class HelloWorld {
static void Main() {
Console.WriteLine("Hello World!");
}
}
Save and close gedit.
Back in terminal type:
sudo apt update
sudo apt install mono-complete
mcs -out:hello.exe hello.cs
mono hello.exe
Output:
Hello World!
NOTE: #adabru's answer below makes my solution obsolete unless you are using an older mono platform.
C# scripts can be run from the bash command line just like Python and Perl scripts, but it takes a small bit of bash magic to make it work. As Corey mentioned above, you must first install Mono on your machine. Then, save the following code in an executable bash script on your Linux machine:
if [ ! -f "$1" ]; then
dmcs_args=$1
shift
else
dmcs_args=""
fi
script=$1
shift
input_cs="$(mktemp)"
output_exe="$(mktemp)"
tail -n +2 $script > $input_cs
dmcs $dmcs_args $input_cs -out:${output_exe} && mono $output_exe $#
rm -f $input_cs $output_exe
Assuming you saved the above script as /usr/bin/csexec, an example C# "script" follows:
#!/usr/bin/csexec -r:System.Windows.Forms.dll -r:System.Drawing.dll
using System;
using System.Drawing;
using System.Windows.Forms;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello Console");
Console.WriteLine("Arguments: " + string.Join(", ", args));
MessageBox.Show("Hello GUI");
}
}
Save the above code to a file such as "hello.cs", make it executable, change the first line to point to the previously saved bash script, and then execute it, you should see the following output along with a dialog saying "Hello GUI":
bash-4.2$ ./hello.cs foo bar baz
Hello Console
Arguments: foo, bar, baz
Note that the GUI requires that you be at run level 5. Here is a simpler C# script that runs at a pure text console:
#!/usr/bin/csexec
using System;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello Console");
Console.WriteLine("Arguments: " + string.Join(", ", args));
}
}
Notice that the command line arguments are passed to the C# script, but the shebang arguments (in the first C# script above "-r:System.Windows.Forms.dll -r:System.Drawing.dll") are passed to the C# compiler. Using the latter functionality, you can specify any compiler arguments you require on the first line of your C# script.
If you are interested in the details of how the bash script works, shebang (#!) lumps together all arguments passed to it on the first line of the C# script, followed by the script name, followed by command line arguments passed to the script itself. In the first C# example above, the following 5 arguments would be passed into the bash script (delineated by quotes):
"-r:System.Windows.Forms.dll -r:System.Drawing.dll" "hello.cs" "foo" "bar" "baz"
The script determines that the first argument is not a filename and assumes it contains arguments for the C# compiler. It then strips off the first line of the C# script using 'tail' and saves the result to a temporary file (since the C# compiler does not read from stdin). Finally, the output of the compiler is saved to another temporary file and executed in mono with the original arguments passed to the script. The 'shift' operator is used to eliminate the compiler arguments and the script name, leaving behind only the script arguments.
Compilation errors will be dumped to the command line when the C# script is executed.
The #! (hashbang) tag is used to tell the shell which interpreter to use so that your perl, php, bash, sh, etc. scripts will run right.
But C# is not a scripting language, it is intended to be compiled into an executable format. You need to install at least a compiler and runtime if you want to use C#, and preferably an IDE (Integrated Development Environment) to help you develop and debug your applications.
Install Mono for the compiler and runtime, then MonoDevelop for the IDE.
After installing mono you can use csharp hello.cs. Starting with Mono 2.10, you can also use the shebang like this:
#!/usr/bin/csharp
Console.WriteLine ("Hello, World");
If you need assemblies, you can load them e.g. with the line LoadAssembly("System.IO.Compression") inside your script.
Reference: man csharp.
You can't execute C# like a script, you have to compile it first. For that, you could install mono.
You can then compile your program with mcs and execute it with mono.
First, you have to install mono
sudo apt install mono-complete
Commands to execute
mcs -out:$1.exe $1.cs
mono $1.exe
You can add these in a script to make the process easier. Create a shell sript and add the parent directory to the PATH environment variable.
Example:
export PATH=$PATH":$HOME/Desktop/customcommands"
And also give execute permission to the script file.
Shell script:
#!/bin/sh
dpkg -s mono-complete > /dev/null
if [ $? -eq 0 ]; then
echo
else
read -p "Package mono-complete not installed. Press y to install or n to quit." response
yes="y"
if [ "$response" = "y" ];
then
sudo apt install mono-complete
echo " "
echo " "
fi
fi
mcs -out:$1.exe $1.cs
mono $1.exe

Why PowerShell does not 'understand' the instructions of a response file?

I have created the following response file (I'm following the examples found in this article: Working with the C# 2.0 Command Line Compiler):
# MyCodeLibraryArgs.rsp
#
# These are the options used
# to compile MyCodeLibrary.dll
# Output target and name.
/t:library
/out:MyCodeLibrary.dll
# Location of C# files.
/recurse:*.cs
# Give me an XML doc.
/doc:myDoc.xml
Then I try to execute it using the C# Compiler (csc.exe) from the PowerShell:
csc #MyCodeLibraryArgs.rsp
Then it generates the following error:
Cannot expand the splatted variable '#MyCodeLibraryArgs'. Splatted variables
cannot be used as part of a property or array expression. Assign the result of
the expression to a temporary variable then splat the temporary variable instead.
At line:1 char:23 + csc #MyCodeLibraryArgs <<<< .rsp
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : NoPropertiesInSplatting
So, I decide to use the prompt (command-line), and it works correctly.
What is the cause (s) of this problem with PowerShell (v.3.0)?
Thanks in advance for your responses and comments.
# is a special syntax in powershell for "splatting" variables. You want to escape the # like so
csc `#MyCodeLibraryArgs.rsp
Splatting allows you to pass cmdlet arguments in a hashtable. This is convenient if you want to dynamically build the arguments you are passing. It can also be more readable if there are a lot of arguments. More info on splatting here.

How to make program accept glob (wildcards) at command line?

I would like users to be able to run my program (from Windows cmd) with syntax like this
app.exe *.pdf
app.exe February/*.pdf March/*.pdf
app.exe contracts.pdf
The app would then do its business for each of the relevant files. In Unix this is called globbing and it's done by the shell.
How can I achieve this for a Windows C# command line app?
Hypothetical syntax
void Main(string[] args)
{
foreach(var file in args.SelectMany(arg => Glob.Expand(arg)))
{
Process(file)
}
}
take a look at NuGet package Microsoft.Extensions.FileSystemGlobbing
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.filesystemglobbing.matcher
The easiest way to do this is to convert the command line parameter into a regular expression. See glob pattern matching in .NET for an example on how to convert the command line argument into a regular expression.

Categories