Working example of CreateJobObject/SetInformationJobObject pinvoke in .net?
This can be little bit late, but still.
I tried all of the examples here, but no one was working for me in 32 and 64 bit mode simultaneously. Finally, I was required to examine all the signatures myself and create corresponding PInvoke routines. I think, somebody else could find this helpful.
Disclaimer: the solution is based on Matt Howells' answer.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace JobManagement
{
public class Job : IDisposable
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr a, string lpName);
[DllImport("kernel32.dll")]
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)]
[return: MarshalAs(UnmanagedType.Bool)]
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);
}
}
#region Helper classes
[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
}
#endregion
}
Unusual ERROR_BAD_LENGTH while setting job memory limits in C#
As it turns out, the object structure in the given example isn't correct for my system. I don't know if this is simply an issue with the example that isn't found by the path its author takes, or if something has changed about the architecture.
All of the working code I've found and made uses 4 bytes for LimitFlags when running in 32bit mode, and 8 bytes when running in 64bit mode.
Pinvoke CreateProcess input/output from file
Based on comments.
- Set
startupInfo.dwFlags
to0x00000100
Add new function
CreateFile
:[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, DesiredAccess dwDesiredAccess, uint dwShareMode, ref SecurityAttributes lpSecurityAttributes, CreationDisposition dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);Create input/output handlers:
var input = Pinvoke.CreateFile(inputFile, DesiredAccess.GENERIC_READ, 0, ref securityAttributes,
CreationDisposition.OPEN_EXISTING, 0, IntPtr.Zero);
var output = Pinvoke.CreateFile(outputFile, DesiredAccess.GENERIC_WRITE, 0, ref securityAttributes,
CreationDisposition.CREATE_NEW, 0, IntPtr.Zero);
startupInfo.hStdInput = input;
startupInfo.hStdOutput = output;
...
public enum DesiredAccess : uint
{
GENERIC_WRITE = 30,
GENERIC_READ = 31
}
public enum CreationDisposition : uint
{
CREATE_NEW = 1,
CREATE_ALWAYS = 2,
OPEN_EXISTING = 3,
OPEN_ALWAYS = 4,
TRUNCATE_EXISTING = 5
}
PInvoke mciSendString
The p/invoke has one error that I can see. The return value should be of type int
or uint
since MCIERROR
is a 32 bit integer. In C# long
is 64 bits wide.
Beyond that, the way you are calling mciSendString
is fine. In fact, your code plays an mp3 file just fine when I run it, even with the erroneous return type declaration.
So, why does it fail for you? The most obvious reason is that the multimedia functions rely on the presence of a message loop. Perhaps the thread which calls this code does not service a message queue. Are you making the call from a console application for instance?
If the thread does have a message queue, and pumps it properly, then I'm not sure what else to suggest. The next step would be to perform some error checking which you do not do at the moment. Take note of the values returned by mciSendString
and see if they indicate errors.
You've now discovered that mciSendString
is returning error code MCIERR_INTERNAL
. To me that sounds like your problem is environmental. Your code works perfectly well for me so it seems that there is a problem with your audio setup/drivers or a problem with the .mp3 file. But there's nothing more that we can do to help you with your code since the problem is not in your code.
Related Topics
An Object Reference Is Required to Access Non-Static Member
SQL Command Insert Is Working But the Data Not Appear in Table
Windows Application Startup Error Exception Code: 0Xe0434352
Benchmarking Small Code Samples in C#, Can This Implementation Be Improved
What Does $ Mean Before a String
Does C++11 Have C#-Style Properties
Sharing Memory Between Two Applications
Howto Implement Callback Interface from Unmanaged Dll to .Net App
Webbrowser.Drawtobitmap() or Other Methods
How to Get Rendered HTML (Processed by JavaScript) in Webbrowser Control
Adding Your Own HTMLhelper in ASP.NET MVC 3
Kanji Characters from Webclient HTML Different from Actual Kanji in Website
What Are Independent Associations and Foreign Key Associations