I want to communicate with a subprocess using a pipe other than stdin, stdout and stderr. I'm trying to use Mono.Unix.UnixPipes.CreatePipes for this. However, I can't find any examples and my best guess of how to use it isn't working. It seems that the child process I create with Process.Start cannot write to the inherited file handle. I am wondering if perhaps it has not actually inherited the handle at all. Here's my (reduced) code:
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Collections.Generic;
using Mono.Unix;
class Program
{
static void Main(string[] args)
{
if (args.Length==0)
{
InvokeChildProcess(args);
}
else
{
RunAsChildProcess(args);
}
}
static int InvokeChildProcess(string[] aArgs)
{
var childToParentPipe = Mono.Unix.UnixPipes.CreatePipes();
var childToParentStream = childToParentPipe.Reading;
string childHandle = childToParentPipe.Writing.Handle.ToString();
var startInfo = new ProcessStartInfo(
System.Reflection.Assembly.GetExecutingAssembly().Location,
childHandle)
{
UseShellExecute = false,
};
Process childProcess = Process.Start(startInfo);
childToParentPipe.Writing.Close();
using (var reader = new StreamReader(childToParentStream))
{
Console.WriteLine("[PARENT] Waiting for child output...");
string output = reader.ReadToEnd();
Console.Write("[PARENT] Received output ({0} chars): ", output.Length);
Console.WriteLine(output);
Console.WriteLine("[PARENT] Waiting for child to exit...");
childProcess.WaitForExit();
Console.WriteLine("[PARENT] Saw child exit with code {0}.", childProcess.ExitCode);
return childProcess.ExitCode;
}
}
static void RunAsChildProcess(string[] args)
{
int handle=int.Parse(args[0]);
Console.WriteLine("[CHILD] Writing to file handle {0}.", handle);
var pipeToParent = new Mono.Unix.UnixStream(handle);
Thread.Sleep(2000);
using (var writer = new StreamWriter(pipeToParent))
{
writer.WriteLine("Message from child.");
writer.Flush();
Environment.Exit(123);
}
}
}
Here's the output when it runs:
weeble#weeble-vm-oneiric32:~/dev$ mono MinimalPipeTest.exe
[PARENT] Waiting for child output...
[PARENT] Received output (0 chars):
[PARENT] Waiting for child to exit...
[CHILD] Writing to file handle 4.
Unhandled Exception: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Can not write to stream
at System.IO.StreamWriter..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Int32 bufferSize) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter..ctor (System.IO.Stream stream) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (System.IO.Stream)
at Program.RunAsChildProcess (System.String[] args) [0x00000] in <filename unknown>:0
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[PARENT] Saw child exit with code 1.
weeble#weeble-vm-oneiric32:~/dev$
This example was compiled and run with Mono 2.10 as distributed in Ubuntu Oneiric.
What am I doing wrong? How can I ensure that the child process will be able to write to the pipe?
EDIT - It looks like Process.Start does indeed close all file descriptors in the child process except for 0, 1 and 2. See here in CreateProcess:
https://github.com/mono/mono/blob/master/mono/io-layer/processes.c#L988
for (i = getdtablesize () - 1; i > 2; i--) {
close (i);
}
I guess that means I can't use UnixPipes and Process.Start. Is there another way?
As I understand it, you cannot use a pipe bi-directionally here. In other words, you cannot read and write with the same pipe. You need two.
Related
I'm running Arch Linux with the following version of mcs:
>mcs --version
Mono C# compiler version 4.0.4.0
And the following version of dbus-sharp
>pacman -Ss dbus-sharp
extra/dbus-sharp 0.8.1-1 [installed] C# implementation of D-Bus
extra/dbus-sharp-glib 0.6.0-1 [installed] C# GLib implementation of D-Bus
This is my test program, based on the example code found here: https://gist.github.com/Ummon/4317268
I'm just trying to access the settings of the currently active connection, which should be returned as a 'Dict of {String, Dict of {String, Variant}}' as I've checked in the d-feet tool for the org.freedesktop.NetworkManager.Settings.Connection interface
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using DBus;
namespace NetworkManagerDictTest {
public class MyTest {
[Interface("org.freedesktop.NetworkManager.Settings.Connection")]
public interface IConnection {
IDictionary<string, IDictionary<string, object>> GetSettings();
}
readonly static string BUS_NAME = "org.freedesktop.NetworkManager";
public static void Main(string[] argv) {
org.freedesktop.DBus.Properties NetworkManagerProps = Bus.System.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, new ObjectPath("/org/freedesktop/NetworkManager"));
ObjectPath[] activeConnections = NetworkManagerProps.Get(BUS_NAME, "ActiveConnections") as ObjectPath[];
if (activeConnections.Length > 0) {
org.freedesktop.DBus.Properties ActiveConnectionProperties = Bus.System.GetObject<org.freedesktop.DBus.Properties>(BUS_NAME, activeConnections[0]);
ObjectPath ActiveConnectionPath = ActiveConnectionProperties.Get("org.freedesktop.NetworkManager.Connection.Active", "Connection") as ObjectPath;
Console.WriteLine("Using connection path: " + ActiveConnectionPath);
IConnection connection = Bus.System.GetObject<IConnection>(BUS_NAME, ActiveConnectionPath);
Console.WriteLine("Connection Object ok");
IDictionary<string, IDictionary<string, object>> settings = connection.GetSettings();
Console.WriteLine(settings);
}
}
}
}
Compilation went without errors nor warnings:
mcs Test.cs -r:/usr/lib/mono/dbus-sharp-2.0/dbus-sharp.dll -r:/usr/lib/mono/dbus-sharp-glib-2.0/dbus-sharp-glib.dll
However my program crashes during execution with the following output:
>mono Test.exe
Using connection path: /org/freedesktop/NetworkManager/Settings/0
Connection Object ok
Unhandled Exception:
DBus.Protocol.MessageReader+PaddingException: Read non-zero byte at position 28 while expecting padding. Value given: 200
at DBus.Protocol.MessageReader.ReadPad (Int32 alignment) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadStruct (System.Type type) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadValue (System.Type type) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadDictionary[String,IDictionary`2] () [0x00000] in <filename unknown>:0
at NetworkManagerDictTest.MyTest+IConnectionProxy.GetSettings () [0x00000] in <filename unknown>:0
at NetworkManagerDictTest.MyTest.Main (System.String[] argv) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: DBus.Protocol.MessageReader+PaddingException: Read non-zero byte at position 28 while expecting padding. Value given: 200
at DBus.Protocol.MessageReader.ReadPad (Int32 alignment) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadStruct (System.Type type) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadValue (System.Type type) [0x00000] in <filename unknown>:0
at DBus.Protocol.MessageReader.ReadDictionary[String,IDictionary`2] () [0x00000] in <filename unknown>:0
at NetworkManagerDictTest.MyTest+IConnectionProxy.GetSettings () [0x00000] in <filename unknown>:0
at NetworkManagerDictTest.MyTest.Main (System.String[] argv) [0x00000] in <filename unknown>:0
What can I do to work around this problem? Am I making a mistake when working with the DBus? It seems that all the method calls up to GetSettings went without issues. I've also encountered a similar problem while trying to fix a bug in another project where dbus-sharp would throw an exception when calling GetSettings. Could this be an issue of dbus-sharp instead?
Taking a look at the source code it seems that dbus-sharp infers the return type directly from the signature of the declared method. Unfortunately it doesn't check if I'm using a parent class or interface of Dictionary, eventually it tries to read a DBus struct because of a fallback case which causes the exception as DBus structs are 8 byte padded while dicts use 4 bytes
Replacing all the IDictionary types with Dictionary worked fine and solved my problem.
Everything works fine in debug mode but when we run it in release the ExtractToDirectory call fails.
Here is the function for reference. Just to make sure we are not doing anything weird.
private bool UnzipFiles()
{
bool toReturn = true;
try
{
UpdateStatus("Almost done...");
string file = Path.Combine (DownloadFolder, "ZipFile.zip");
if(System.IO.Directory.Exists(UnzippingDestinationFolder))
{
System.IO.Directory.Delete(UnzippingDestinationFolder, recursive:true);
}
System.IO.Compression.ZipFile.ExtractToDirectory(file, UnzippingDestinationFolder);
UpdateStatus("Finished!");
var files = System.IO.Directory.GetFiles(UnzippingDestinationFolder);
int m = 3;
}
catch (Exception e)
{
toReturn = false;
}
Finally, here is the exception we get.
System.NullReferenceException: Object reference not set to an instance of an object
at SharpCompress.Common.Zip.Headers.ZipFileEntry.DecodeString (System.Byte[] str) [0x00000] in <filename unknown>:0
at SharpCompress.Common.Zip.Headers.DirectoryEntryHeader.Read (System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
at SharpCompress.Common.Zip.ZipHeaderFactory.ReadHeader (UInt32 headerBytes, System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
at SharpCompress.Common.Zip.SeekableZipHeaderFactory+<ReadSeekableHeader>c__Iterator0.MoveNext () [0x00000] in <filename unknown>:0
at SharpCompress.Archive.Zip.ZipArchive+<LoadEntries>c__Iterator0.MoveNext () [0x00000] in <filename unknown>:0
at SharpCompress.LazyReadOnlyCollection`1+LazyLoader[SharpCompress.Archive.Zip.ZipArchiveEntry].MoveNext () [0x00000] in <filename unknown>:0
at System.IO.Compression.ZipArchive.CreateZip (System.IO.Stream stream, ZipArchiveMode mode) [0x00000] in <filename unknown>:0
at System.IO.Compression.ZipArchive..ctor (System.IO.Stream stream, ZipArchiveMode mode, Boolean leaveOpen, System.Text.Encoding entryNameEncoding) [0x00000] in <filename unknown>:0
at System.IO.Compression.ZipFile.Open (System.String archiveFileName, ZipArchiveMode mode, System.Text.Encoding entryNameEncoding) [0x00000] in <filename unknown>:0
at System.IO.Compression.ZipFile.ExtractToDirectory (System.String sourceArchiveFileName, System.String destinationDirectoryName, System.Text.Encoding entryNameEncoding) [0x00000] in <filename unknown>:0
at System.IO.Compression.ZipFile.ExtractToDirectory (System.String sourceArchiveFileName, System.String destinationDirectoryName) [0x00000] in <filename unknown>:0
at NewBaron.Screens.DownloadContentScreen.UnzipFiles () [0x00000] in <filename unknown>:0
A slight changes to Victor's solution. Not linking the SDKs generated an apk that was 53MBs. Too large for the play store's apk size limit.
I set the linking behavior to link SDK assemblies only and it brought the apk size down to 29MBs
Here is the updated window.
#mattewrobbinsdev's suggestion was exactly it. For future readers, here's the dialog in Xamarin Studio:
I'm trying to use Raspberry# library to perform basic task whith GPIO pin on Raspberry PI (on and off).
As per example on github: https://github.com/raspberry-sharp/raspberry-sharp-io/wiki/Raspberry.IO.GeneralPurpose
Code:
var led1 = ConnectorPin.P1Pin11.Output();
var connection = new GpioConnection(led1);
for (var i = 0; i < 100; i++)
{
connection.Toggle(led1);
System.Threading.Thread.Sleep(250);
}
connection.Close();
on line var connection = new GpioConnection(led1); I get exception:
"Operation is not valid due to the current state of the object"
Stack trace
Unhandled Exception:
System.InvalidOperationException: Operation is not valid due to the current state of the object
at Raspberry.IO.GeneralPurpose.GpioConnectionDriver..ctor () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnectionSettings.get_DefaultDriver () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnectionSettings..ctor () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnection..ctor (Raspberry.IO.GeneralPurpose.GpioConnectionSettings settings, IEnumerable`1 pins) [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnection..ctor (Raspberry.IO.GeneralPurpose.PinConfiguration[] pins) [0x00000] in <filename unknown>:0
at Hello.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Operation is not valid due to the current state of the object
at Raspberry.IO.GeneralPurpose.GpioConnectionDriver..ctor () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnectionSettings.get_DefaultDriver () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnectionSettings..ctor () [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnection..ctor (Raspberry.IO.GeneralPurpose.GpioConnectionSettings settings, IEnumerable`1 pins) [0x00000] in <filename unknown>:0
at Raspberry.IO.GeneralPurpose.GpioConnection..ctor (Raspberry.IO.GeneralPurpose.PinConfiguration[] pins) [0x00000] in <filename unknown>:0
at Hello.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
I am able to switch pin state with Python so nothing is wrong with device.
Execute your Mono program as root. /dev/mem is not accessible to normal users.
public GpioConnectionDriver() {
using (var memoryFile = UnixFile.Open("/dev/mem", UnixFileMode.ReadWrite | UnixFileMode.Synchronized)) {
gpioAddress = MemoryMap.Create(
IntPtr.Zero,
Interop.BCM2835_BLOCK_SIZE,
MemoryProtection.ReadWrite,
MemoryFlags.Shared,
memoryFile.Descriptor,
Interop.BCM2835_GPIO_BASE
);
}
}
Explanation from here:
http://www.raspberrypi.org/forums/viewtopic.php?f=29&t=22515
To open /dev/mem you need both regular access permissions on the device file and the security capability CAP_SYS_RAWIO, or to be root. There is no getting around this, because full access to memory allows a lot more than just GPIO. It has huge security implications.
I am c# beginner and trying to read a binary file to calculate the frequency of the symbols inside the binary file. (Frequency is the number of time the symbols repeats).
In my first step I took I kept the data type of "symbol" read as "int" and code worked fine.
But now I wanted to make this symbol of generic type (I mean <T> type).
The code compiles with out any error in ubantu terminal.
But when I execute using "mono filename.exe BinaryFile.bin" This binary file is read at sole argument. Please see at last that how i got this Binary file toto.bin.
The error is :
hp#ubuntu:~/Desktop/Internship_Xav/templatescplus$ mono test.exe toto.bin
Unhandled Exception: System.ArgumentException: Destination array is not long enough to copy all the items in the collection. Check array index and length.
at System.BitConverter.PutBytes (System.Byte* dst, System.Byte[] src, Int32 start_index, Int32 count) [0x00000] in <filename unknown>:0
at System.BitConverter.ToInt64 (System.Byte[] value, Int32 startIndex) [0x00000] in <filename unknown>:0
at shekhar_final_version_Csharp.Huffman`1[System.Int64]..ctor (System.String[] args, System.Func`3 converter) [0x00000] in <filename unknown>:0
at shekhar_final_version_Csharp.MyClass.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Destination array is not long enough to copy all the items in the collection. Check array index and length.
at System.BitConverter.PutBytes (System.Byte* dst, System.Byte[] src, Int32 start_index, Int32 count) [0x00000] in <filename unknown>:0
at System.BitConverter.ToInt64 (System.Byte[] value, Int32 startIndex) [0x00000] in <filename unknown>:0
at shekhar_final_version_Csharp.Huffman`1[System.Int64]..ctor (System.String[] args, System.Func`3 converter) [0x00000] in <filename unknown>:0
at shekhar_final_version_Csharp.MyClass.Main (System.String[] args) [0x00000] in <filename unknown>:0
hp#ubuntu:~/Desktop/
My full code to do so is (narrowed code):
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Final
{
public class A < T > where T: struct, IComparable < T > , IEquatable < T >
{
public class Node
{
public T symbol;
public Node next;
public int freq;
} public Node Front;
public A(string[] args, Func < byte[], int, T > converter)
{
int size = Marshal.SizeOf(typeof (T));
Front = null;
using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0])))
{
while (stream.BaseStream.Position < stream.BaseStream.Length)
{
byte[] bytes = stream.ReadBytes(size);
T processingValue = converter(bytes, 0);
Node pt, temp;
pt = Front;
while (pt != null)
{ Console.WriteLine("check1");
if (pt.symbol.Equals(processingValue))
{
pt.freq++;
break;
}
Console.WriteLine("Symbol : {0} frequency is : {1}", pt.symbol, pt.freq);
temp = pt;
pt = pt.next;
}
}
}
}
} //////////////////////////////////////////////////
public class MyClass
{
public static void Main(string[] args)
{
A < long > ObjSym = new A < long > (args, BitConverter.ToInt64);
}
}
}
I think the problem is created while creating object of type Huffman in public class MyClass. Could some one please help me how to get a rid of this problem by giving a solution (any piece of code would be highly appreciated)? Thanks.
If the size of the file is not a multitude of 8 bytes (64 bits), the last ReadBytes() will result in a byte[] smaller than 8 bytes, causing ToInt64() to fail.
Unhandled Exception: System.Security.Cryptography.CryptographicException: Private/public key mismatch
at Mono.Security.Cryptography.RSAManaged.ImportParameters (RSAParameters parameters) [0x00000] in <filename unknown>:0
at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters (RSAParameters parameters) [0x00000] in <filename unknown>:0
at BlaBlaFunc() [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Security.Cryptography.CryptographicException: Private/public key mismatch
at Mono.Security.Cryptography.RSAManaged.ImportParameters (RSAParameters parameters) [0x00000] in <filename unknown>:0
at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters (RSAParameters parameters) [0x00000] in <filename unknown>:0
at BlaBlaFunc() [0x00000] in <filename unknown>:0
Here is the Source Code:
string foo = "blabla";
System.Security.Cryptography.RSAParameters rsa_params = new System.Security.Cryptography.RSAParameters();
rsa_params.Modulus = Enumerable.Range(0, pubkey.Length)
.Where(x => x % 2 == 0)
.Select(x => System.Convert.ToByte(pubkey.Substring(x, 2), 16))
.ToArray();
rsa_params.Exponent = new byte[] { 1, 0, 1 };
System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
System.Security.Cryptography.RSAParameters d = rsa.ExportParameters(false);
rsa.ImportParameters(rsa_params);
byte[] sp = rsa.Encrypt(Encoding.UTF8.GetBytes(foo), false);
The .exe file which works fine in windows is compiled with vs2010. It was runned with mono under Ubuntu.
Run with this command:
mono --runtime=v4.0.30319 xxx.exe
How can i fix this?
Apparently the ExportParameters call generates a keypair, including private key, even though you specified false for the includePrivateParameters argument. (See the source code). The ImportParameters then overwrites only the public key (because you don't provide the private one) hence the mismatch. This may be a mono bug if it doesn't match documented behaviour. Check that and file a bug if applicable.
As a workaround, you can remove the ExportParameters or create a new instance that you import into.