Hello.
I develop on C#.
I can successfully execute a process with (IGuestSession.ProcessCreate), but when I try send a command string to Std input of the process - an erorr occures.
I use the method IGuestProcess.Write API (version - 4.3.12). The error I get:
System.Runtime.InteropServices.SafeArrayTypeMismatchException: Specified array was not of the expected type.
at System.StubHelpers.MngdSafeArrayMarshaler.ConvertSpaceToNative(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome)
at TestHostListener.IProcessA.Write(UInt32 aHandle, UInt32 aFlags, Array aData, UInt32 aTimeoutMS)
Please help to solve this problem
Problem with IGuestProcess.Write
-
- Site Moderator
- Posts: 5229
- Joined: 13. Jan 2012, 11:14
- Primary OS: Debian other
- VBox Version: OSE Debian
- Guest OSses: Debian, Win 2k8, Win 7
- Contact:
Re: Problem with IGuestProcess.Write
Post a sample code with the full context (e.g. stand alone code) that shows your issue.
Hyperbox - Virtual Infrastructure Manager - https://apps.kamax.lu/hyperbox/
Manage your VirtualBox infrastructure the free way!
Manage your VirtualBox infrastructure the free way!
Re: Problem with IGuestProcess.Write
I created the DLL as it is written on this page viewtopic.php?f=34&t=55033
IGuestProcess.Read works fine! But IGuestProcess.Write not want to work.
My code:
IGuestProcess.Read works fine! But IGuestProcess.Write not want to work.
My code:
Code: Select all
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using VirtualBox.Interop;
namespace TestHostListener
{
/// <summary>
/// Description of MainForm.
/// </summary>
///
[Guid("DFA39A36-5D43-4840-A025-67EA956B3111")]
[TypeLibType(4160)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IProcessA {
Array Arguments { get; }
Array Environment { get; }
string ExecutablePath { get; }
int ExitCode { get; }
string Name { get; }
uint PID { get; }
ProcessStatus Status { get; }
ProcessWaitResult WaitFor(uint aWaitFor, uint aTimeoutMS);
ProcessWaitResult WaitForArray(Array aWaitFor, uint aTimeoutMS);
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_I8)]
Array Read(uint aHandle, uint aToRead, uint aTimeoutMS);
uint Write(uint aHandle, uint aFlags, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I8)] Array aData, uint aTimeoutMS);
uint WriteArray(uint aHandle, Array aFlags, Array aData, uint aTimeoutMS);
void Terminate();
}
public partial class MainForm : Form
{
static IGuestProcess process;
static IProcessA processa;
public static Thread hostListeneThread = new Thread(startHostListener);
private static sbyte ByteToSByteConverter(byte b) { return (sbyte)b; }
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
hostListeneThread.Start();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
static void startHostListener()
{
VirtualBoxClient vboxclient = new VirtualBoxClient();
IMachine machine = vboxclient.VirtualBox.FindMachine("VBox");
Session session = vboxclient.Session;
try {
machine.LockMachine(session, LockType.LockType_Shared);
IGuestSession guestsession = session.Console.Guest.CreateSession("x", "x", "", "Guest Listener1");
Thread.Sleep(1000);
try {
process = guestsession.ProcessCreate("C:\\HostListener.exe", new String[0], new String[0], new ProcessCreateFlag[] { ProcessCreateFlag.ProcessCreateFlag_WaitForStdOut }, 0);
processa = (IProcessA)process;
process.WaitForArray(new ProcessWaitForFlag[] { ProcessWaitForFlag.ProcessWaitForFlag_Start }, 0);
while(process.Status!=ProcessStatus.ProcessStatus_TerminatedNormally
&& process.Status!=ProcessStatus.ProcessStatus_TerminatedAbnormally
&& process.Status!=ProcessStatus.ProcessStatus_TerminatedSignal
&& process.Status!=ProcessStatus.ProcessStatus_Terminating)
{
Array bytes = process.Read(1, 64 * 1024, 0);
if(bytes.Length>0)
{
Debug.WriteLine(Encoding.Default.GetString((Byte[])bytes));
}
Thread.Sleep(25);
}
} finally {
guestsession.Close();
}
} finally {
if (session.State == SessionState.SessionState_Locked) session.UnlockMachine();
}
}
void Button1Click(object sender, EventArgs e)
{
byte[] array = Encoding.UTF8.GetBytes(textBox1.Text);
//process.Write(0,(uint)ProcessInputFlag.ProcessInputFlag_EndOfFile,array,0); //I tried and so, all the same get the error
//processa.WriteArray(0,new ProcessInputFlag[]{ProcessInputFlag.ProcessInputFlag_None},Array.ConvertAll<Byte, SByte>(array, ByteToSByteConverter),0);
//ERROR
processa.Write(0, (uint)ProcessInputFlag.ProcessInputFlag_EndOfFile,Array.ConvertAll<byte, sbyte>(array, ByteToSByteConverter),0); //ERROR
}
}
}
-
- Posts: 22
- Joined: 11. Jun 2013, 08:35
- Primary OS: MS Windows 7
- VBox Version: PUEL
- Guest OSses: WinXP, WinVista, Win7, Win8
Re: Problem with IGuestProcess.Write
Hi batyr,
There are a couple of things that makes your code less likely to work, but the main issue is that there are problems with your IProcessA interface. If you replace it with:
You should be able to get it working. The thing is, in my experience writing to processes is rather finicky using the VirtualBox interface so you will probably have to spend quite a bit of effort getting it working as you want it. Getting it consistent can be even more difficult.
Why did you decide to create your own interface wrapper? There might have been an error in the guide I posted in the other thread to create a working interop DLL, but what happens if you use the interface from that instead - do you get the same error?
Other things to note:
You need to wait for the GuestSession to be ready before you can use it - use:
instead of the Thread.Sleep you have now.
There are a couple of things that makes your code less likely to work, but the main issue is that there are problems with your IProcessA interface. If you replace it with:
Code: Select all
[Guid("DFA39A36-5D43-4840-A025-67EA956B3111")]
[TypeLibType(4160)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IProcessA
{
string[] Arguments { get; }
string[] Environment { get; }
IEventSource EventSource { get; }
string ExecutablePath { get; }
int ExitCode { get; }
string Name { get; }
uint PID { get; }
ProcessStatus Status { get; }
ProcessWaitResult WaitFor([In] uint aWaitFor, [In] uint aTimeoutMS);
[return: ComAliasName("VirtualBox.ProcessWaitResult")]
ProcessWaitResult WaitForArray([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] [In] ProcessWaitForFlag[] aWaitFor, [In] uint aTimeoutMS);
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I1)]
byte[] Read([In] uint aHandle, [In] uint aToRead, [In] uint aTimeoutMS);
uint Write([In] uint aHandle, [In] uint aFlags, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I1)] [In] sbyte[] aData, [In] uint aTimeoutMS);
uint WriteArray([In] uint aHandle, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] [In] ProcessInputFlag[] aFlags, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I1)] [In] sbyte[] aData, [In] uint aTimeoutMS);
void Terminate();
}
Why did you decide to create your own interface wrapper? There might have been an error in the guide I posted in the other thread to create a working interop DLL, but what happens if you use the interface from that instead - do you get the same error?
Other things to note:
You need to wait for the GuestSession to be ready before you can use it - use:
Code: Select all
guestsession.WaitForArray(new GuestSessionWaitForFlag[] { GuestSessionWaitForFlag.GuestSessionWaitForFlag_Start }, 0);
Re: Problem with IGuestProcess.Write
Very thanks for such prompt and deep response.!
It works fine now )
Exactly, the problem was in the interface, particularly in the following line:
I found this interface somewhere in this forum. I had to create the interface because the VirtualBox native DLL fired the same error.
It works fine now )
Exactly, the problem was in the interface, particularly in the following line:
Code: Select all
uint Write(uint aHandle, uint aFlags, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I8)] Array aData, uint aTimeoutMS);