Working host process (including auto termination)

This commit is contained in:
Ben Olden-Cooligan 2016-01-03 18:52:54 -05:00
parent 3da97ca455
commit c773054558
8 changed files with 170 additions and 17 deletions

View File

@ -233,6 +233,7 @@
<Compile Include="Operation\OperationErrorEventArgs.cs" />
<Compile Include="Operation\OperationStatus.cs" />
<Compile Include="Util\Pipes.cs" />
<Compile Include="Util\ProcessJob.cs" />
<Compile Include="ImportExport\DirectImageTransfer.cs" />
<Compile Include="Util\StillImage.cs" />
<Compile Include="Util\StringWrapper.cs" />

View File

@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace NAPS2.Util
{
public class Job : IDisposable
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr a, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
private IntPtr handle;
private bool disposed;
public Job()
{
handle = CreateJobObject(IntPtr.Zero, null);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
LimitFlags = 0x2000
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) { }
Close();
disposed = true;
}
public void Close()
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
public bool AddProcess(IntPtr processHandle)
{
return AssignProcessToJobObject(handle, processHandle);
}
public bool AddProcess(int processId)
{
return AddProcess(Process.GetProcessById(processId).Handle);
}
}
[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public UInt32 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public UIntPtr Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public Int32 bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
}

View File

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Text;
@ -11,7 +12,7 @@ namespace NAPS2.Util
{
public static class X86HostManager
{
private const string PIPE_NAME_FORMAT = "net.pipe://localhost/NAPS2_32/{0}/x86host";
public const string PIPE_NAME_FORMAT = "net.pipe://localhost/NAPS2_32/{0}/x86host";
private static Process _hostProcess;
private static string _pipeName;
@ -34,8 +35,12 @@ namespace NAPS2.Util
{
Log.Error("Could not start 32-bit host process; terminating.");
Environment.Exit(1);
return;
}
var job = new Job();
job.AddProcess(_hostProcess.Handle);
_channelFactory = new Lazy<ChannelFactory<IX86HostService>>(
() => new ChannelFactory<IX86HostService>(new NetNamedPipeBinding(), new EndpointAddress(_pipeName)));
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
@ -9,7 +10,7 @@ namespace NAPS2.Util
{
public void DoWork()
{
MessageBox.Show("Hi!");
MessageBox.Show("Hi from " + Process.GetCurrentProcess().Id + "!");
}
}
}

View File

@ -11,10 +11,5 @@
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="NAPS2.Util.X86HostService">
<endpoint address="x86host" binding="netNamedPipeBinding" contract="NAPS2.Util.IX86HostService" />
</service>
</services>
</system.serviceModel>
</configuration>

View File

@ -8,10 +8,21 @@ namespace NAPS2_32
{
public class BackgroundForm : Form
{
public BackgroundForm()
private readonly string pipeName;
public BackgroundForm(string pipeName)
{
this.pipeName = pipeName;
WindowState = FormWindowState.Minimized;
ShowInTaskbar = false;
Load += BackgroundForm_Load;
}
void BackgroundForm_Load(object sender, EventArgs e)
{
MessageBox.Show("Listening at " + pipeName);
Close();
}
}
}

View File

@ -17,7 +17,7 @@
<WcfConfigValidationEnabled>True</WcfConfigValidationEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>

View File

@ -11,18 +11,19 @@ namespace NAPS2_32
{
static class Program
{
private const string PIPE_BASE_ADDR_FORMAT = "net.pipe://localhost/NAPS2_32/{0}/";
[STAThread]
static void Main()
{
var pipeBaseAddr = new Uri(string.Format(PIPE_BASE_ADDR_FORMAT, Process.GetCurrentProcess().Id));
var host = new ServiceHost(typeof(X86HostService), pipeBaseAddr);
host.Open();
using (var host = new ServiceHost(typeof (X86HostService)))
{
string pipeName = string.Format(X86HostManager.PIPE_NAME_FORMAT, Process.GetCurrentProcess().Id);
host.AddServiceEndpoint(typeof (IX86HostService), new NetNamedPipeBinding(), pipeName);
host.Open();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new BackgroundForm());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new BackgroundForm(pipeName));
}
}
}
}