Mono cannot access file even though linux shell can without root - c#

this might be a wrong place to ask this (but I think its right place since it involves programming).
So I got a raspberry pi zero for our school project. I SSH'd into it to check out what it can do with it. I made some research about how to use the GPIO pins on this card.
Basically:
$ echo 17 > /sys/class/gpio/export
$ echo out > /sys/class/gpio/gpio17/direction
$ echo 1 > /sys/class/gpio/gpio17/value
$ echo 17 > /sys/class/gpio/unexport
Enables GPIO pin 17 and writes digital 1 into it and 'unexport's it, no root is needed.
I also wanted to try out some of the languages in this card. I tried python, C# and Rust without a problem (even though rust compiles very slow, it works). So I started using my favourite language C# with mono. Installing it and compiling a basic program wasn't a big deal, It works.
So I write this:
using System;
using System.IO;
namespace Program
{
public static class Program
{
public static void Main()
{
if (Directory.Exists("/sys/class/gpio/gpio17/"))
File.WriteAllText("/sys/class/gpio/unexport", "17");
File.WriteAllText("/sys/class/gpio/export", "17");
File.WriteAllText("/sys/class/gpio/gpio17/direction", "out");
File.WriteAllText("/sys/class/gpio/gpio17/value", "1");
}
}
}
Basically, if it finds the 17 pin open, 'unexport' it then re-export it, set as output and write digital 1.
Compilation:
mcs program.cs -out:program.exe -debug && ./program.exe
Output:
Unhandled Exception:
System.UnauthorizedAccessException: Access to the path "/sys/class/gpio/gpio17/direction" is
denied.
What? How? It works with sudo mono ./program.exe and no it doesn't with mono ./program.exe
Sure, I can always use wiringPi or python but I am curious about this one and couldn't find an answer. It doesn't make sense to me. /sys/class/gpio/gpio17 is a symbolic link and I tried to access to original path too with no luck.
What might be the problem here?

Guesses:
You unexport it first, then export it and immediately access it, I had in the past several time problems on some OS e. g. deleting a file and immediately creating it again, add a waiting time (not really clean code, but if it works)
check the difference of the files/folders with linux command "ls -la" or more
call the shell command, that worked, from C# via e. g. Process class
Some few times Mono did not work like C# on Windows, a workaround had to be found
try to open a stream to these files and leave them open? Or even a pipe is possible to these files?

Related

How to get the Linux file type (regular, durector, symlink, char device, etc) in .NET?

There are 7 different types of files in Linux:
1. - : regular file
2. d : directory
3. c : character device file
4. b : block device file
5. s : local socket file
6. p : named pipe
7. l : symbolic link
A Linux shell way to get the type for a given file or path is via either ls command, or through a specific cheks like in:
if [ -f path/to/file ] then
which will go into an if the body only if the path/to/file is pointing at a regular file (not a directory, not a symlink, etc.
Is there a .NET way of checking the path type in Linux terms? For instance, I want to have a check which will return true only if File.Exists while pointing at a regular file? What about checking for other types.
Even if right now with .NET 5 checking this is impossible, fine for the question to stick around until this is made possible via managed code, without recording to "call bash -> get results -> process output -> wrap into POCO" way.
It's interesting that even a Linux-friendly language like Java doesn't offer a comprehensive solution to do so.
Fortunately, File.GetAttributes(string) method provides helpful (but still not as complete as question looks for) information.
var path = "/path/to/file";
var attributes = File.GetAttributes(path);
if (attributes.HasFlag(FileAttributes.Directory))
Console.WriteLine("directory");
else if (attributes.HasFlag(FileAttributes.Normal))
Console.WriteLine("file");
else if (attributes.HasFlag(FileAttributes.ReparsePoint))
Console.WriteLine("link");
else if (attributes.HasFlag(FileAttributes.System))
Console.WriteLine("system");
The code above is tested on multiple sample files over WSL2 and works fine. However, I didn't managed to test all sort of files but it seems some attributes like Device or System represents more than one type out of seven Linux file types.

How to specify compiler options in c# file?

I have a code.cs file that I compile with the following command line:
"%ProgramFiles(x86)%\MICROS~3\2017\ENTERP~1\MSBuild\15.0\Bin\Roslyn\csc.exe" ^
/target:library /out:fx1.dll fx1.cs ^
/reference:"C:\blah\blah\Microsoft.JScript.dll" ^
/reference:"C:\astor\loads\better\ease\zog.dll"
Is there a practical way to specify those options inside the fx1.cs file ?
This is mainly C#, but what about other .Net languages like Vb.Net and the others? Is there at least one language that can specify compiler parameters in a self-contained file?
Update: I also see there are answer files for csc, but they lack (or I can't see) enough flow control to embed one in a cs file.
The solution I came up with as baseline answer for this question is to turn the C# file into a "polyglot" *.cs.bat file that runs the full compile command on top of the C# source code.
/*? 2>NUL & #echo off
echo.
echo COMPILING...
"%ProgramFiles(x86)%\MICROS~3\2017\ENTERP~1\MSBuild\15.0\Bin\Roslyn\csc.exe" ^
/target:library /out:fx1.dll fx1.cs.bat ^
/reference:"C:\blah\blah\Microsoft.JScript.dll" ^
/reference:"C:\astor\loads\better\ease\zog.dll"
PAUSE
GOTO:EOF REM */
// C# program...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
// blah...
To compile I can just run fx1.cs or fx1.cs.bat. That certinly is practical.
This may be useful but the downsides are at least these:
text highlighting is lost in the various editors that have it for *.cs files... If only there was a (easy) way to run *.cs files as batch (type file | cmd seems to ignore PAUSE, EXIT /B, EXIT, GOTO:EOF)
The compiler path is hardcoded (but I think it can be determined with more batch fiddling)
It tries to run /*.exe, so the first line always gives me an error because I found no way to avoid it being run, so I can only put a ? in there (so it should not be a valid path ever) and hide it with error redirection.
While it is unpractical to edit in an IDE, I think this may be an easy format for distribution of simple utilities.
I'm not very good at this... so if someone has better ideas (for the polyglot route) please improve this answer by commenting or editing it.

Universal Windows Platform (UWP) C# app - How to run stand alone python inside your application

I am trying to find a way to call python from my UWP app. So far I have a .exe file that I have compiled from python using pyinstaller (www.pyinstaller.org/). This basically allows me to package up my python script as a standalone binary (ie: you don't need python to run it). This all works well and I can call my wrapped up python .exe via cmd.exe no problem:
$ process.exe -p "path\to\file"
$ Processing file: "path\to\file"...
$ Done.
So now I just need to call it from my UWP app - so I have added it to my application like so:
C# Project
Assets/process.exe
Frustratingly, I've not had much luck googling for answers to my problem - my attempted solutions so far have included:
Calling the "Assets/process.exe" directly from my app
Looked at "Launch an app and get results". I think this seams to be for external applications however... I certainly didn't get it going anyway.
Opening the cmd.exe (somehow) and calling my process.exe from there.
I'm not even sure if I'm trying to do this the correct way or not. Or if I have just not understood some of my findings. Or (fingers crossed) there is a simple solution to this I just don't know about and have somehow missed as I'm very new to UWP development and C#.
So any solutions/pointers here would be greatly appreciated thanks!!
UWP apps are 'sandboxed'; i.e. they have many security restrictions placed upon them to isolate them from the rest of Windows (like not being able to read/write to the Registry and not being able to directly access random files from the file system).
So there is no way to run an .exe (or any other executable) from your UWP app. If you have access to a StorageFile (say music, video or any other file format) then you can launch the file in the default program associated with that file type.

GhostScript PS to PDF with images only work during debug mode in Visual Studio

I'm trying to convert a ps file (word file with image) to pdf using Ghostscript.
Everything works fine when I'm debugging my code and just stepping thru it, It generates the pdf with the text,images and whatnot. But when I deploy the app using Visual Studio Setup Project, It does not work and gives me this error "An error occured when call to 'gsapi_new_instance' is made: -100."
Here's my command line arguments
var args = string.Format("-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=\"{1}\" -c save pop -f \"{0}\"", inputFile, #"C:\MedirefPrinter\converted\out.pdf");
Any idea why this isn't working? Thanks
Actual Code :
File Changed Handler
ShellCommand
Please excuse my noobness :)
Moved to an answer to allow more text.
There are three possible reasons for the error:
1) The 'instance' pointer is NULL. I can't see how this is ever possible with our executable as its a globally defined variable and the executable passes its address. This is a sanity check for people writing code against the Ghostscript API.
2) The application was unable to allocate sufficient memory for some internal structures. Again this seems unlikely as your system would have to be unreasonably short on memory.
3) The DLL instance count is already 1 or greater. This can happen if the DLL is shared between multiple processes. Unless you build the library with GS_THREADSAFE it isn't thread safe, and so you can't have multiple processes using the same instance of the DLL. I'd guess that this is your problem but obviously you haven't supplied a full set of code, so I don't know. If you are trying to run more than one copy of Ghostscript simultaneously, from the same directory, then you will get this error.
error -100 means 'something really bad happened so early on that I can't even tell you what it is'.
I very much doubt that the presence of images in the PostScript has any real impact, except that possibly it may slow the interpretation down enough to cause you to attempt to launch two processes.

Malwarebytes gives trojan warning for basic C# "Hello World!" program

Basically, I just ran a scan of my computer with Malwarebytes (updated the definitions before running), and it said my "helloworld" program written in C# has a trojan.
I know for a fact this is a false positive, as I only wrote the program 2-3 days ago and followed a small tutorial website to make the program that I trust. I am new to C#, but I can't see anything that would give a trojan warning at all.
The program flags the executable, but not the source file.
using System;
namespace HelloWorldApplication
{
class HelloWorld
{
static void Main(string[] args)
{
Console.WriteLine("\n\tHello World!");
Console.WriteLine("This is my first C# program.\nI'm so proud of myself!");
Console.WriteLine("\tTeehee!");
}
}
}
This is the code, written in Notepad++, and it is run from the command-line (Cygwin, actually). Why does it flags this? Is it something that, as a budding C# programmer, I should know about?
The problem could be that the Backdoor.MSIL.PGen Trojan is typically called 'hello.exe'. The name of your executable is presumably 'hello.exe' or 'helloworld.exe'.
Just rename your project or change the output executable to something not containing 'hello', and it should stop detecting it.
This answer is somewhat speculative, but given the name of your project, and a history of over-aggressive detection of this malware (see here), it seems a reasonable stab.
The answer by Baldrick is likely correct, but there is also another possibility: There are viruses which search for random executables on the system and modify them by inserting their own code into them (this is, in fact, the original definition of "computer virus"). When you find that an executable which you know is trustworthy suddenly is reported as infected, you might be dealing with such a virus.
But unless your virus scanner reports other executables as the same virus, this is unlikely.
I just figured this out: change the "Guid" in AssemblyInfo.cs a little, then try again.
That worked for me.

Categories