-Commit WIP.

-Used Pipe code from rosdbg. Kudos to gschneider for the great code.
-Good bye horrible polling, temporary file deletion and weird live scrolling code!!!

svn path=/trunk/tools/Qemu GUI/; revision=862
This commit is contained in:
Samuel Serapion 2008-10-15 07:42:35 +00:00
parent a0ae2bf79d
commit 5b17db2627
13 changed files with 332 additions and 127 deletions

View File

@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Resources;
//
// General Information about an assembly is controlled through the following
@ -56,3 +57,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
[assembly: NeutralResourcesLanguageAttribute("en")]

View File

@ -446,8 +446,8 @@ namespace Qemu_GUI
}
else if (this.SerialPort.SRedirect)
{
/* fix me: use pipes!!!!!! */
buffer = "-serial file:\"" + this.SerialPort.FileName + "\" ";
//if (this.SerialPort.FileName.Length > 0)
buffer = "-serial pipe:\"com_1\" ";
}

View File

@ -1,18 +1,13 @@
using System;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;
using System.Windows.Forms;
namespace Qemu_GUI
{
public partial class DebugForm : Form
{
string talker;
Process proc;
ThreadStart start;
Thread worker;
public DebugForm()
{
InitializeComponent();
@ -22,96 +17,55 @@ namespace Qemu_GUI
{
this.Close();
}
public void Listen(Process p, string Talker)
public void Listen()
{
if (p.HasExited)
return;
this.Show();
proc = p;
talker = Talker;
start = new ThreadStart(ThreadProc);
worker = new Thread(start);
worker.Priority = ThreadPriority.Normal;
this.Show();//show the dialog
worker.Start();
BackgroundWorker work = new BackgroundWorker();
work.DoWork += new DoWorkEventHandler(work_DoWork);
work.RunWorkerAsync();
}
private void ThreadProc()
void work_DoWork(object sender, DoWorkEventArgs e)
{
FileStream log = null;
txtDebug.Text = "";
string buffer = "";
string temp = "";
NamedPipe pipe = new NamedPipe();
/* fix me: writting to a form from a diferent thread, unsafe. */
try
{
log = new FileStream(talker, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
while (!proc.HasExited)
{
int data = log.ReadByte();
if (data != -1)
{
worker.Priority = ThreadPriority.Normal;
buffer += Convert.ToChar(data);
//it might take a while for qemu to launch and wait for a pipe
System.Threading.Thread.Sleep(1000);
if (buffer.Contains("\n"))
{
temp = txtDebug.Text + buffer;
txtDebug.Text = "";
txtDebug.SelectedText = temp;
buffer = "";
}
}
else
worker.Priority = ThreadPriority.Lowest;
//Thread.Sleep(50);//wait a 1/4 of a second for more data
}
pipe.CreateClientPipe("com_1");
temp = txtDebug.Text + buffer;
txtDebug.Text = "";
txtDebug.SelectedText = temp;
log.Close();
DeleteTalker();
//txtDebug.Text += "QEMU GUI: Exited listener!" + Environment.NewLine;
}
catch (Exception e)
{
/* fix me: writting to a form from a diferent thread, unsafe. */
try
{
log.Close();
txtDebug.Text += "QEMU GUI: Exited listener on exception!" + Environment.NewLine;
txtDebug.Text += e.Message;
}
catch
{}
}
log.Close();
DeleteTalker();
pipe.PipeReceiveEvent += new PipeReceiveEventHandler(PipeRecievedHandler);
pipe.PipeErrorEvent += new PipeErrorEventHandler(PipeErrorHandler);
pipe.ReadLoop();
}
private void DeleteTalker()
{
/* sometimes it takes a while for qemu to free the handle to the file */
while (File.Exists(talker))
{
if (proc.HasExited)
{
worker.Priority = ThreadPriority.Lowest;
private void PipeErrorHandler(object sender, PipeErrorEventArgs args)
{
ErrorForm err = new ErrorForm();
err.txtError.Text += "PipeErrorHandler:" + Environment.NewLine;
err.txtError.Text += args.ErrorDesc;
err.Show();
}
try
{
File.Delete(talker);
if (!File.Exists(talker))
break;
}
catch
{ }
}
}
//MessageBox.Show("Temp File deleted!");
}
private void PipeRecievedHandler(object sender, PipeReceiveEventArgs args)
{
WriteString(args.Received);
}
private delegate void WriteStringDelegate(string text);
public void WriteString(string text)
{
if (txtDebug.InvokeRequired)
txtDebug.Invoke(new WriteStringDelegate(WriteString), text);
else
{
txtDebug.AppendText(text);
txtDebug.ScrollToCaret();
}
}
private void tsbuttonCopy_Click(object sender, EventArgs e)
{
@ -138,7 +92,7 @@ namespace Qemu_GUI
{
error = new ErrorForm();
error.txtError.Text = "Exception while trying to save file!" + Environment.NewLine;
error.txtError.Text += ex.Message;
error.txtError.Text = ex.Message ;
error.Show();
}
log.Close();

View File

@ -22,4 +22,4 @@ namespace Qemu_GUI
Clipboard.SetText(temp);
}
}
}
}

View File

@ -2,7 +2,6 @@ using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
@ -614,7 +613,7 @@ namespace Qemu_GUI
runner = new Runner(data);
if (runner.MountImage() == true)
{
Thread.Sleep(500);
System.Threading.Thread.Sleep(500);
Process p = new Process();
p.StartInfo.FileName = "explorer";

206
NamedPipe.cs Normal file
View File

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace Qemu_GUI
{
public enum ConnectionMode
{
MODE_CLIENT = 0x00000000,
MODE_SERVER = 0x00000001,
MODE_AUTO = 0x00000002
}
public class NamedPipe : Pipe
{
public const int PIPE_SIZE = 1024;
private PipeStream ioStream; /* stream for io operations */
private String wCommand; /* buffer of a single command line */
private List<String> cmdList; /*list of commands pending to be written */
public event PipeReceiveEventHandler PipeReceiveEvent;
public event PipeErrorEventHandler PipeErrorEvent;
private static ManualResetEvent newWriteData = new ManualResetEvent(false);
public NamedPipe()
{
cmdList = new List<string>();
}
public bool CreateServerPipe(string name)
{
/* create a pipe and wait for a client */
NamedPipeServerStream sStream = new NamedPipeServerStream(name, PipeDirection.InOut, 1,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous, PIPE_SIZE, PIPE_SIZE);
sStream.WaitForConnection();
if (sStream.IsConnected)
{
ioStream = sStream;
return true;
}
else
{
return false;
}
}
public bool CreateClientPipe(string name)
{
/* try to connect as a client */
/* (QEMU -serial pipe or VMware in pipe server mode) */
try
{
NamedPipeClientStream cStream = new NamedPipeClientStream(".", name, PipeDirection.InOut, PipeOptions.Asynchronous);
cStream.Connect(100);
if (cStream.IsConnected)
{
ioStream = cStream;
return true;
}
else
{
return false;
}
}
catch (Exception)
{
return false;
}
}
public bool CreatePipe(string name, ConnectionMode mode)
{
if (name == "" || name == null)
{
return false;
}
switch (mode)
{
case ConnectionMode.MODE_AUTO:
//check if pipe exists, if not create server pipe, wait certain time, check if pipe...
//TODO: server-client lookup should time out
while (true)
{
if (CreateClientPipe(name))
{
break;
}
if (CreateServerPipe(name))
{
break;
}
}
return true;
case ConnectionMode.MODE_CLIENT:
while (!CreateClientPipe(name)) ;
/* pipe open, everything fine */
return true;
case ConnectionMode.MODE_SERVER:
if (CreateServerPipe(name))
{
/* wait for a client*/
return true;
}
break;
}
return false;
}
public void Close()
{
if (ioStream != null)
ioStream.Close();
}
public void WriteLoop()
{
try
{
while (true)
{
if (cmdList.Count > 0)
{
byte[] wBuf = new byte[cmdList[0].Length];
UTF8Encoding.UTF8.GetBytes(cmdList[0], 0, cmdList[0].Length, wBuf, 0);
ioStream.Write(wBuf, 0, cmdList[0].Length);
/* remove written data from commandlist */
cmdList.RemoveAt(0);
}
else if (cmdList.Count == 0)
{
/* wait until new data is signaled */
newWriteData.Reset();
newWriteData.WaitOne();
}
}
}
catch (Exception e)
{
if (PipeErrorEvent != null)
PipeErrorEvent.Invoke(this, new PipeErrorEventArgs(e.Message));
}
}
public void ReadLoop()
{
byte[] buf = new byte[PIPE_SIZE];
int read = 0;
try
{
while (true)
{
read = ioStream.Read(buf, 0, PIPE_SIZE);
if (read > 0)
{
if (PipeReceiveEvent != null)
PipeReceiveEvent.Invoke(this, new PipeReceiveEventArgs(UTF8Encoding.UTF8.GetString(buf, 0, read)));
}
else
{
/* connecion closed */
break;
}
}
}
catch (Exception e)
{
if (PipeErrorEvent != null)
PipeErrorEvent.Invoke(this, new PipeErrorEventArgs(e.Message));
}
}
public bool Write(string str)
{
/* only forward a complete line */
wCommand += str;
if (str[str.Length - 1] == '\r')
{
cmdList.Add(wCommand);
wCommand = null;
/* wake up the write thread */
newWriteData.Set();
}
return true;
}
}
}

36
PipeClient.cs Normal file
View File

@ -0,0 +1,36 @@
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.IO;
using System.Collections;
namespace Qemu_GUI
{
public class PipeReceiveEventArgs
{
public readonly string Received;
public PipeReceiveEventArgs(string received)
{
Received = received;
}
}
public delegate void PipeReceiveEventHandler(object sender, PipeReceiveEventArgs args);
public class PipeErrorEventArgs
{
public readonly string ErrorDesc;
public PipeErrorEventArgs(string error)
{
ErrorDesc = error;
}
}
public delegate void PipeErrorEventHandler(object sender, PipeErrorEventArgs args);
public interface Pipe
{
event PipeReceiveEventHandler PipeReceiveEvent;
event PipeErrorEventHandler PipeErrorEvent;
bool Write(string output);
}
}

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.312
// Runtime Version:2.0.50727.1434
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -153,7 +153,7 @@ namespace Qemu_GUI.Properties {
internal static System.Drawing.Bitmap preferences_system {
get {
object obj = ResourceManager.GetObject("preferences-system", resourceCulture);
object obj = ResourceManager.GetObject("preferences_system", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}

View File

@ -154,7 +154,7 @@
<data name="harddisk" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\direct\harddisk.ico;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="preferences-system" type="System.Resources.ResXFileRef, System.Windows.Forms">
<data name="preferences_system" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\preferences-system.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="debug" type="System.Resources.ResXFileRef, System.Windows.Forms">

View File

@ -4,7 +4,13 @@
<security>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site">
<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
<IPermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
<IPermission class="System.Security.Permissions.RegistryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
<IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
</PermissionSet>
</applicationRequestMinimum>
</security>
</trustInfo>

View File

@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>8.0.50727</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{88020C53-D88A-4488-A479-E7ED0310D3D3}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -30,8 +30,10 @@
<GenerateManifests>true</GenerateManifests>
<SignManifests>false</SignManifests>
<IsWebBootstrapper>false</IsWebBootstrapper>
<TargetZone>LocalIntranet</TargetZone>
<PublishUrl>C:\Documents and Settings\Samuel\Desktop\qemu\</PublishUrl>
<TargetZone>Custom</TargetZone>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
@ -41,7 +43,9 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationVersion>0.1.0.%2a</ApplicationVersion>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -51,7 +55,7 @@
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>DEBUG</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
@ -69,12 +73,13 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>
</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
@ -94,6 +99,9 @@
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
@ -117,6 +125,7 @@
<Compile Include="AboutForm.Designer.cs">
<DependentUpon>AboutForm.cs</DependentUpon>
</Compile>
<Compile Include="PipeClient.cs" />
<Compile Include="DebugForm.cs">
<SubType>Form</SubType>
</Compile>
@ -135,6 +144,7 @@
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="NamedPipe.cs" />
<Compile Include="Network.cs" />
<Compile Include="program.cs" />
<Compile Include="Properties\Resources.Designer.cs">
@ -165,9 +175,19 @@
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<Visible>False</Visible>
<ProductName>.NET Framework 2.0</ProductName>
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
<Visible>False</Visible>
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="AboutForm.resx">

View File

@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C# Express 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QEmuGUI", "QEmuGUI.csproj", "{88020C53-D88A-4488-A479-E7ED0310D3D3}"
EndProject
Global

View File

@ -1,7 +1,5 @@
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
using System.Security.Permissions;
@ -70,26 +68,9 @@ namespace Qemu_GUI
return false;
}
if (data.Debug.SerialPort.SRedirect)
{
/* create a random name */
string filename = "serial" + DateTime.UtcNow.Ticks.ToString() + ".txt";
data.Debug.SerialPort.FileName = temp_path + filename;
}
try
{
p.StartInfo.WorkingDirectory = data.Paths.Qemu;
if (data.Debug.SerialPort.SRedirect)
{
output = new DebugForm();
/* create a unic name */
string filename = "serial" + DateTime.UtcNow.Ticks.ToString() + ".txt";
data.Debug.SerialPort.FileName = temp_path + filename;
}
p.StartInfo.Arguments = data.GetArgv();
}
catch (Exception e)
@ -104,10 +85,11 @@ namespace Qemu_GUI
try
{
p.Start();
if (data.Debug.SerialPort.SRedirect)
{
output = new DebugForm();
output.Listen(p, data.Debug.SerialPort.FileName);
output.Listen();
}
}
catch (Exception e)