Start C# program from command line on Linux - c#

What command should I use to start this C# program from the command line in Linux? I've already compiled it (using Monodevelop), but I don't know how to start it from the command line.
using System;
class ExampleClass
{
static void Main()
{
Console.WriteLine("Hello, world!");
}
}

The command line you need to start a C# (or any other .NET) program on Linux depends on how you have your Linux system configured.
The standard answer is to run the mono program, and pass the name of your executable assembly as a parameter. The name of your executable assembly is typically the same as the name of your project file, though you can easily change it; just look for a file ending in .exe after you're done compiling. It will be found in a folder named bin\Debug, or bin\Release or something similar (it depends on how you have your project build settings set up). So, if you built a program called hello.exe you would go into your project folder and run:
~/projects/hello $ mono bin\Debug\hello.exe
The reason you need to run the mono program is because Linux does not know, by default, how to run the .NET runtime automatically. When you install .NET on Windows, it actually changes the part of the OS that loads programs, so Windows just automatically recognizes a .NET program and loads the runtime. On Linux, you need to do that yourself, by running the mono program first.
If you run a lot of managed code on Linux, you can also configure the Linux kernel to work the same way that Windows does. Linux has support for "miscellaneous binary formats" that allows you to tell Linux how to execute binaries that are not native Linux format. This is somewhat advanced - it likely requires you to build a custom kernel, though I would not be surprised if your Linux distribution had a better way to do it. More information on this process can be found here:
http://www.kernel.org/doc/Documentation/mono.txt

Related

C# System.DllNotFoundException

I have a simple application using a product activation system offered by cryptlex (cryptlex.com).
The program works correctly on my computer, but when I try to run the program on another machine it returns this error:
I've already made sure that the dll is inside the executable folder and everything looks OK.
When I remove all part of cryptlex the program works perfectly on any machine (x86-x64)
I used depencywalker to check for errors and found these two in the executable that uses cryptlex:
Windows 7 64bits,
.NET Version: 4.0
You can use Process Monitor to record all file activities of the program. Set a filter for your executable. After reproducing the error, save the log as XML file.
Then run ProcMon Analyzer (note: I'm the author of it). It will analyze the file and give a list of DLLs that were not found.
You could also do that manually, but note that some DLLs may not be found at first, but later be found when looking in the %PATH% environment variable etc. The tool will remove all those entries which have PATH NOT FOUND first but SUCCESS later.
While the DLL is present, have you checked the bitrate?
Most C# projects default to building against Any CPU - if the DLL is specific to a bitrate (ie x86 or x64) then it might be that the program picks the wrong bitrate on end machines (usually x86) but the right one on your machine (x64). This is usually best resolved by building out different x86 and x64 versions; it's messier, but only .NET itself is good at using the Any CPU paradigm.
The exception should have detail about what DLL in particular was not found - maybe look closer?
GPSVC and IESHIMS missing should not be a problem; as indicated by the hour glass, they're deferred dependencies anyway.

How to create a command line application

With VisualStudio it is easy to create application types for Console, Forms, etc, but I see no option for a command line application. I intend to install the small program below as a simple .exe in c:\windows\system32. If I open a command terminal and CD to the bin\debug dir of the VS project, I can type DateTime and get nice output. However, if I copy the DateTime.exe to c:\windows\system32 and open another command terminal, the command DateTime gives an error saying that the application could not be started, because of .Net Shim errors.
Should I do something different to create a commandline application rather than a Console app?
Should I install more files from the bin\debug directory in c:\windows\system32 ?
using System;
namespace DateTime
{
class Program
{
static void Main()
{
Console.Write(System.DateTime.Now.ToString("o"));
}
}
}
NB: reason for the above command line app is that the system commands Date/T and Time/T do not provide seconds output. My app shows e.g. 2015-07-13T10:58:29.7329261+02:00 (, and you can get other formats with an argument, see previous edits of this question)
Console project is a command line project.
You can use the args [] to track command line parameters.
Your executable may have dependencies: You can use something like obfuscator or another tool to package them into the .exe so you don't need external files.
Alternatively, install your project into its own folder, and modify the PATH variable to include the path to the directory - this will let you run your .exe from any folder, much like you can run 'dir' in any folder.
I'm not clear what your DateTime problem is, but you can use the .ToString() overload to adjust the formatting, and .Parse() to interpret the date from a variety of formats.
var dt = new DateTime();
dt.ToString("dd/MM/yyyy hh:mm:ss");
As advised by SLC, I tried to write this app in C++. It turns out that VisualStudio offers a choice for C++ Console apps: with CLR, or as Win32, where CLR stands for the dot-Net Framework. Indeed the Win32 project builds as a simple .EXE file that can be installed in any directory mentioned in %PATH%, e.g., C:\Windows\System32\ .
VisualStudio does not offer this choice for C# Console apps.
Unfortunately, C++ is a step backwards from C#: it is more complex. It should run faster for certain types of apps, but cost more time to develop. Compare this C++ code with the C# source above:
#include "stdafx.h"
#include <iostream>
#include <ctime>
int main()
{
// get current time
time_t time_now = time(0);
// convert to local time struct
struct tm tstruct;
localtime_s(&tstruct, &time_now);
// format to string
char str_time[80];
strftime(str_time, sizeof(str_time), "%Y-%m-%d %H:%M:%S", &tstruct);
// to stdout
std::cout << str_time << std::endl;
return 0;
}
As said, the above C++ code, as a Win32 Console project, will run as a single .EXE file from a directory in %PATH%.
For completeness, here is a nicer source code in C++, as a CLR Console project, i.e., with the .Net Framework, that will code comparably fast as C#, but will also NOT run as a single .EXE file from a directory in %PATH%.
#include "stdafx.h"
using namespace System;
int main()
{
Console::WriteLine(DateTime::Now);
Console::WriteLine(DateTime::Now.ToString(L"o"));
Console::WriteLine(DateTime::Now.ToString(L"yyyy-MM-dd HH:mm:ss"));
return 0;
}
Output is, e.g.:
14-7-2015 16:23:27
2015-07-14T16:23:27.6978497+02:00
2015-07-14 16:23:27
The above apps are also tested from PowerShell, but then the CLR/.Net based apps can also not be run from %PATH%.
There is a simple NuGet package that helps you to create your own command-line application without handling many things line parsing the arguments and mapping the types etc.,
https://www.nuget.org/packages/CommandLineTool/

Generate a CIL executable not EXE then execute it

I have a c# project that generates an EXE file. Now, I'm in a "secure" corporate environment, where I can compile my project, but I cannot execute the EXE file.
As a Java programmer, I'm wondering if there is not a way to compile the c# project into something that would not be an EXE file, but a CIL file and then execute the CIL file by something that corresponds to java.exe in the dotnet world.
EDIT in response to comments:
I can run exe files that have been installed by a package manager
Yes, I know the corporate policy is stupid.
Well, this should be pretty easy.
.NET executables are simply DLLs like any other - the main difference being the executable format itself, and the fact that EXE files have an entry point, while DLLs don't.
It also means that you can load the EXE into memory exactly the same way as you would with a DLL:
Assembly.LoadFrom("SomeExe.exe");
You're already half way there - now we just need to find and execute the entry point. And unsurprisingly, this is also pretty trivial:
var assembly = Assembly.LoadFrom("SomeExe.exe");
assembly.EntryPoint.Invoke(null, null);
For most applications, this should work perfectly fine; for some, you'll have to make sure the thread you're using to invoke the entry point has STAThread or MTAThread respectively (Thread.TrySetThreadApartment if you're starting a new thread).
It might need tweaking for some applications, but it shouldn't be too hard to fix.
So you can just make some bootstrap application ("interpreter") that only really contains these two lines of code. If you can't get even that approved, and you really need something as an "official package", try some .NET application that allows you to execute arbitrary code - for example, LINQPad, or PowerShell.
EDIT:
This does have limitations, of course, and it does introduce some extra setup work:
The bootstrapper has to target the same or higher version of .NET Framework. .NET Portable might be particularly tricky, but I assume you have that well under control. It also has to have the same bitness (if specified explicitly).
You need to run the debugging through the bootstrapper. That actually isn't all too hard - just go to project properties, debug and select "Start external program".
The bootstrapper has to run under full trust conditions - it's necessary for reflection to work. On most systems, this simply means you have to have the exe as a local file (e.g. not from a network share). Tools like LINQPad will run under full trust by default.
The application must not depend on Assembly.GetEntryAssembly. This isn't used all that often, so it shouldn't be a problem. Quite a few similar issues should also be fine since you build the application you're trying to run yourself.

DllNotFoundException with DllImport in Mono on Mac

I'm trying to use DLLImport in my Mono Mac project in order to use my own .dylib but I get the DllNotFoundException. I'm guessing it has something to do with my .dylib since I'm able to do this with existing .dylib files such as the libmojoshader.dylib.
Here's how I use DLLImport
[DllImport("libtestDylib.dylib")]
static extern int libsum(int a, int b);
I then call the libsum function in order to see if it works.
I've found that running the app through the terminal with the MONO_LOG_LEVEL="debug" MONO_LOG_MASK="dll" mono myGame.exe command is a great way to debug issues like this, however I can't get my app .exe to run. I've tried using both the .exe in build folder and the one in the .app/contents/MonoBundle, I've also tried running file in .app/contents/MacOs as this is referenced in some places I've found while researching.
The last file throws a "File does not contain a valid CIL image." and the two others "No Info.plist file in application bundle or no NSPrincipalClass in the Info.plist file".
So, I would guess that the first step is to manage to run the app through the terminal in order to get proper debug information as for why my .dylib can't be found.
The .dylib I made is an empty BSD C lib made in XNA4.
Edit
I can't even seem to get the existing dylibs to work now.
I found the problem by making a new Mono Mac project with a single c# file which I then compiled through the terminal and ran it with the debug command. With the terminal feedback found out where the program was searching for the .dylib, and that the lib I made was built with the wrong architecture which was simply solved by building for 32-bit systems.

How do you use the standard library in IronPython?

I'll prefix this question with: No, Setting IRONPYTHONPATH is not the answer.
Anyway...
I was planning on using IronPython as a replacement for Powershell for a project, but I've been stumped before I've even started.
The very first thing I tried to do was use os.path, resulting in:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named os
After messing around I finally discovered I could use the standard library by adding it manually to the path:
import sys
sys.path.append(r"C:\Program Files\IronPython 2.7\Lib")
import os
However, this is a daft idea. Hard coding the path to the python library inside my scripts is a 100% guaranteed way of making them not work at some point.
I discovered this almost immediately when I tried to use the script on a windows 7 machine and the path was slightly different ('Program Files (x86)').
So, a couple of questions here:
1) Why is it so hard to use the standard library? At the very least I would have thought the interactive prompt in VS and basic ipy.exe would have this.
2) How can I determine the directory that iron python is installed in regardless of the system I'm using? (IronPython installer setting a var perhaps?)
Just a note here; yes, I have seen some other posts saying "set your IRONPYTHONPATH". This in unhelpful. If I have a blank machine that means I have to:
1) Install IronPython
2) Run some crazy powershell script to search out where-ever-the-heck the standard library was installed and set a global IRONPYTHONPATH variable to it.
3) Run python scripts
I'm looking for a better way.
--
Edit:
The fact I'm using this to do powershell like things is basically irrelevant, but I'm trying to achieve something like:
import clr
from System.Management.Automation import RunspaceInvoke
import os
scriptRoot = os.getcwd()
runSpace = RunspaceInvoke()
cmdPath64 = os.join(scriptRoot, "..\java\...")
cmdPath32 = os.join(scriptRoot, "..\java\...")
proc = runSpace.Invoke("Get-WmiObject Win32_Processor ... ")
if proc.AddressWidth == 32:
runSpace.Invoke(cmdPath32)
else:
runSpace.Invoke(cmdPath64)
I find that for ensuring that everything works for non-developer third parties, it's usually better to use pyc.py to create DLL's and and executable. I routinely create a DLL of the python standard modules and reference that in code. See my previous answer at this question IronPython: EXE compiled using pyc.py cannot import module "os"
It's a bit workaroundish but, given that the LIB directory of ironpython is installed under the x86 program files folder in 64bit systems and on the usual program files path on 32bit systems, you could do in this way:
import sys
import System
if System.IntPtr.Size * 8 == 32: # detect if we are running on 32bit process
sys.path.append(System.Environment.GetEnvironmentVariable("ProgramFiles") + "\IronPython 2.7\Lib")
else:
sys.path.append(System.Environment.GetEnvironmentVariable("ProgramFiles(x86)") + "\IronPython 2.7\Lib")
import os # it works !!
Here we use %ProgramFiles% and %ProgramFiles(x86)% to determine the path where IronPython is installed.
Quoting wikipedia about %ProgramFiles% variable (link):
%ProgramFiles%
This variable points to Program Files directory, which stores all the
installed program of Windows and others. The default on
English-language systems is C:\Program Files. In 64-bit editions of
Windows (XP, 2003, Vista), there are also %ProgramFiles(x86)% which
defaults to C:\Program Files (x86) and %ProgramW6432% which defaults
to C:\Program Files. The %ProgramFiles% itself depends on whether the
process requesting the environment variable is itself 32-bit or 64-bit
(this is caused by Windows-on-Windows 64-bit redirection).
This is very odd, because if you run the the IronPython installer, and then run C:\Program Files\IronPython 2.7\ipy.exe or C:\Program Files (x86)\IronPython 2.7\ipy.exe, you shouldn't need to do anything to have the stdlib available.
My guess is that you have more than one IronPython and you're running the wrong one, but only because I can't think of another reason this would happen. It's supposed to Just Work.

Categories

Resources