Here is my main program:
class Program
{
static void Main(string[] args)
{
Printer printer = new Printer();
IntPtr printerHandle = printer.getPrinterHandle("TASKalfa 2551ci");
UInt32 jobId = printer.getJobId();
Console.WriteLine(printerHandle+","+jobId);
printer.getJob(printerHandle, jobId);
Console.ReadLine();
}
}
I got the following error message from VS 2015 Community Edition, when I call printer.getJob Method, even I have catched the System.NullReferenceException.
System.NullReferenceException was unhandled
Message: An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll
Additional information: Object reference not set to an instance of an object.
I have checked that both variable printerHandle and jobId are not null, so I cannot figure out what is problem.
However the value of printerHandle is not a constant, is it correct?
Here is my printer object source code:
using System;
using System.Collections;
using System.Management;
using System.Runtime.InteropServices;
class Printer
{
public Printer()
{
}
public ArrayList getPrinterNameList()
{
ArrayList result = new ArrayList();
var printerQuery = new ManagementObjectSearcher("SELECT * from Win32_Printer");
foreach (var printer in printerQuery.Get())
{
result.Add(printer.GetPropertyValue("Name"));
}
return result;
}
public UInt32 getJobId()
{
UInt32 jobId=0;
var printJobQuery = new ManagementObjectSearcher("select * from Win32_PrintJob");
foreach (var printJob in printJobQuery.Get())
{
jobId= (UInt32)printJob.Properties["JobId"].Value;
}
return jobId;
}
public IntPtr getPrinterHandle(String printerName)
{
IntPtr result=new IntPtr(0);
Console.WriteLine ("OpenPrinter="+OpenPrinter(printerName,out result, result));
return result;
}
public void getJob(IntPtr printerHandle,UInt32 jobId)
{
int BUFFER_SIZE = 250;
IntPtr pcbNeeed = new IntPtr(0);
byte[] byteBuffer = new byte[BUFFER_SIZE];
try
{
Console.WriteLine("GetJob="+GetJob(printerHandle, (Int32)jobId, 1, out byteBuffer, BUFFER_SIZE, out pcbNeeed));
}
catch (System.NullReferenceException err)
{
Console.WriteLine(err.Message);
}
}
[DllImport("winspool.drv", SetLastError = true)]
static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport(
"winspool.drv",
EntryPoint = "GetJobW",
SetLastError = true,
CharSet = CharSet.Ansi,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] Int32 JobId,
[InAttribute()] Int32 Level,
[OutAttribute()] out byte[] pJob,
[InAttribute()] Int32 cbBuf,
[OutAttribute()] out IntPtr pcbNeeded);
}
Here is my WIN API version:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string msg = null;
var hPrinter = new IntPtr();
bool open = NativeMethods.OpenPrinterW("TASKalfa 2551ci", ref hPrinter, IntPtr.Zero);
Debug.Assert(open);
/* Query for 99 jobs */
const uint firstJob = 0u;
const uint noJobs = 99u;
const uint level = 1u;
// Get byte size required for the function
uint needed;
uint returned;
IntPtr tempptr = IntPtr.Zero;
bool b1 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, IntPtr.Zero, 0, out needed, out returned);
uint lastError = NativeMethods.GetLastError();
Console.WriteLine("b1="+b1);
//Debug.Assert(lastError == NativeConstants.ERROR_INSUFFICIENT_BUFFER);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError=" + msg);
// Populate the structs
IntPtr pJob = Marshal.AllocHGlobal((int)needed);
uint bytesCopied;
uint structsCopied;
bool b2 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, pJob, needed, out bytesCopied, out structsCopied);
lastError = NativeMethods.GetLastError();
Console.WriteLine("b2="+b2);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError="+ msg);
var jobInfos = new JOB_INFO_1W[structsCopied];
int sizeOf = Marshal.SizeOf(typeof(JOB_INFO_1W));
IntPtr pStruct = pJob;
for (int i = 0; i < structsCopied; i++)
{
var jobInfo_1W = (JOB_INFO_1W)Marshal.PtrToStructure(pStruct, typeof(JOB_INFO_1W));
jobInfos[i] = jobInfo_1W;
pStruct += sizeOf;
}
Marshal.FreeHGlobal(pJob);
Console.WriteLine("structsCopied="+structsCopied);
Console.ReadLine();
}
public class NativeConstants
{
public const int ERROR_INSUFFICIENT_BUFFER = 122;
}
public partial class NativeMethods
{
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
public static extern uint GetLastError();
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
public extern static int FormatMessage(int flag, ref IntPtr source, uint msgid, int langid, ref string buf, int size, ref IntPtr args);
}
public partial class NativeMethods
{
[DllImport("Winspool.drv", EntryPoint = "OpenPrinterW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenPrinterW([In] [MarshalAs(UnmanagedType.LPWStr)] string pPrinterName,
ref IntPtr phPrinter, [In] IntPtr pDefault);
[DllImport("Winspool.drv", EntryPoint = "EnumJobsW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumJobsW([In] IntPtr hPrinter, uint FirstJob, uint NoJobs, uint Level, IntPtr pJob,
uint cbBuf, [Out] out uint pcbNeeded, [Out] out uint pcReturned);
}
[StructLayout(LayoutKind.Sequential)]
public struct JOB_INFO_1W
{
public uint JobId;
[MarshalAs(UnmanagedType.LPWStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pMachineName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pUserName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDocument;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPWStr)]
public string pStatus;
public uint Status;
public uint Priority;
public uint Position;
public uint TotalPages;
public uint PagesPrinted;
public SYSTEMTIME Submitted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
}
}
I am using Windows 10.
This is my solution:
using System;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;
namespace WinApi
{
class PrintJob
{
private const int ERROR_INSUFFICIENT_BUFFER = 122;
public PrintJob()
{
string sql = "select * from Win32_PrintJob";
var printJobQuery = new ManagementObjectSearcher(sql);
foreach (ManagementObject printJob in printJobQuery.Get())
{
getJobDetail(printJob);
Console.WriteLine("====================");
}
}
private void getJobDetail(ManagementObject thePrintJob)
{
UInt32 jobId = 0, needed = 0;
String printerName;
bool result;
IntPtr printerHandle = new IntPtr(0);
jobId = (UInt32)thePrintJob.Properties["JobId"].Value;
printerName = (String)thePrintJob.Properties["DriverName"].Value;
Console.WriteLine("Job Id=" + jobId + ",Printer Name=" + printerName);
result=OpenPrinter(printerName,out printerHandle, IntPtr.Zero);
Console.Write("Open Printer " + printerName);
if (result)
{
Console.WriteLine(" success.");
result = GetJob(printerHandle, jobId, 2, IntPtr.Zero,0,out needed);
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
Console.WriteLine("Get Job 1 failure, error code=" + Marshal.GetLastWin32Error());
else
{
Console.WriteLine("buffer size required=" + needed);
IntPtr buffer = Marshal.AllocHGlobal((int)needed);
result = GetJob(printerHandle, jobId, 2, buffer, needed, out needed);
JOB_INFO_2 jobInfo=(JOB_INFO_2)Marshal.PtrToStructure(buffer, typeof(JOB_INFO_2));
DEVMODE dMode = (DEVMODE)Marshal.PtrToStructure(jobInfo.pDevMode, typeof(DEVMODE));
Console.WriteLine("Job Id=" + jobInfo.JobId + ",Printer Name=" + Marshal.PtrToStringAnsi(jobInfo.pDriverName) + ",Copies=" + dMode.dmCopies);
Marshal.FreeHGlobal(buffer);
}
ClosePrinter(printerHandle);
Console.WriteLine("Printer " + printerName+" is closed");
}
else
Console.WriteLine(" failed.");
}
[DllImport("winspool.drv", SetLastError = true)]
static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport("winspool.drv", CharSet = CharSet.Auto)]
static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport(
"winspool.drv",
EntryPoint = "GetJob",
SetLastError = true,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] UInt32 JobId,
[InAttribute()] UInt32 Level,
[OutAttribute()] IntPtr pJob,
[InAttribute()] UInt32 cbBuf,
[OutAttribute()] out UInt32 pcbNeeded);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct JOB_INFO_2
{
public UInt32 JobId;
public IntPtr pPrinterName;
public IntPtr pMachineName;
public IntPtr pUserName;
public IntPtr pDocument;
public IntPtr pNotifyName;
public IntPtr pDatatype;
public IntPtr pPrintProcessor;
public IntPtr pParameters;
public IntPtr pDriverName;
public IntPtr pDevMode;
public IntPtr pStatus;
public IntPtr pSecurityDescriptor;
public UInt32 Status;
public UInt32 Priority;
public UInt32 Position;
public UInt32 StartTime;
public UInt32 UntilTime;
public UInt32 TotalPages;
public UInt32 Size;
public SYSTEMTIME Submitted;
public UInt32 Time;
public UInt32 PagesPrinted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
}
}
Related
i use an dll with callback methods function:
int result = SetCallEventCalback(uint hServer, uint CallbackParam,CallEventCallback* OnCallEvent, bool SearchPhonebook)
void CallEventCallback(uint hServer, uint CallbackParam, char* CallId, int
ChannelNumber, int EventType, wchar* Param, wchar* ExtraParam)
and
i write this class for use dll function and get event
but not work correctly .
what is my problem?
thanks.
public class Recording
{
public delegate int CallBackDel(uint hServer, uint CallbackParam, string CallId, int ChannelNumber, int EventType, string Param, string ExtraParam);
public Recording.CallBackDel CallBackdelegate = new CallBackDel(Recording.CallbackFunc);
public string CallidP = "";
public uint hServer = 0;
public uint hServerP=0;
public uint CallbackParamP = 0;
public string CallIdP="";
public int ChannelNumberP=0;
public int EventTypeP=0;
public int ConnectionStatus = 0;
public int connect = 0;
public string ParamP="";
public string ExtraParamP="";
public Recording(string Serverip, int type, string user, string password)
{
hServer = CreateServerHandle(Serverip, type);
if (hServer > 0)
{
int connect = Recording.Connect(hServer);
if (connect == 1)
{
Thread.Sleep(2000);
ConnectionStatus = Recording.SignIn(hServer, user, password);
}
if (ConnectionStatus == 1)
{
//CallBackdelegate(hServer, CallbackParamP, CallIdP, ChannelNumberP, EventTypeP, ExtraParamP);
Recording.SetCallEventCalback(hServer, CallbackParamP, CallBackdelegate, false);
}
else
{
}
}
}
public static int CallbackFunc(uint hServer, uint CallbackParam, string CallId, int ChannelNumber, int EventType, string Param, string ExtraParam)
{
return (int) hServer;
}
//1 CreateServerHandle
[DllImport("MJ.dll")]
public static extern uint CreateServerHandle(string ServerName, int ServerType);
//2 DestroyServerHandle
[DllImport("MJ.dll")]
public static extern void DestroyServerHandle(uint HNDL);
//3 Connect
[DllImport("MJ.dll")]
public static extern int Connect(uint hServer);
//4 Disconnect
[DllImport("MJ.dll")]
public static extern int Disconnect(uint hServer);
//5 SignIn
[DllImport("MJ.dll")]
public static extern int SignIn(uint hServer, string UserName, string Password);
//6 SignOut
[DllImport("MJ.dll")]
public static extern int SignOut(uint hServer);
//7 IsConnected
[DllImport("MJ.dll")]
public static extern bool IsConnected(uint hServer);
//8 IsSignedIn
[DllImport("MJ.dll")]
public static extern bool IsSignedIn(uint hServer);
//9 GetMetadata
[DllImport("MJ.dll")]
public static extern bool GetMetadata(uint hServer, string CallId, string Metadata);
//10 SetConnectingFinishedEventCalback
//public delegate int SetCallEventCalback2(uint hServer, uint CallbackParam, Delegate SetCallEventCalback2, bool SearchPhonebook);
[DllImport("MJ.dll", CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.Cdecl)]
public static extern int SetCallEventCalback(uint hServer, uint CallbackParam, CallBackDel SetCallEventCalback2, bool SearchPhonebook);
//11 CallEventCallback
//void CallEventCallback(uint hServer, uint CallbackParam, char* CallId, int ChannelNumber, int EventType, wchar* Param, wchar* ExtraParam)
[DllImport("MJ.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void CallEventCallback(uint hServer, uint CallbackParam, string CallId, int ChannelNumber, int EventType, string Param, string ExtraParam);
//12 Export(uint hServer, char* DestFilePath, char* CallId, int FormatType,bool RemovePilot)
[DllImport("MJ.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Export(uint hServer, string DestFilePath, string CallId, int FormatType, bool RemovePilot);
}
my problem solve by add EntryPoint = "SetCallEventCallback"
[DllImport("BSF API.dll", CharSet = CharSet.Ansi,CallingConvention = CallingConvention.Cdecl, EntryPoint = "SetCallEventCallback")]
public static extern int SetCallEventCalback(uint hServer, uint CallbackParam, CallBackDel SetCallEventCalback2, bool SearchPhonebook);
Trying to use the following code example which works fine in WinForm application but not in VSTO. Is there some sort of permissions that allow access?
Can set the default printer but can't get or set printer settings.
Get the following exception from within addin:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
http://www.pinvoke.net/default.aspx/winspool.SetDefaultPrinter
http://www.pinvoke.net/default.aspx/winspool/OpenPrinter.html
visual studio project template is a {Word/Outlook} 2013 and 2016 VSTO Add-in
string name = #"\\{printer server name}\{printer name}";
PRNsettings p = new PRNsettings();
var v = p.ChangePrinterSetting(name, new PrinterData { colour = 1, copies = 1, duplex = 1, source = 7 });
public class PrinterData
{
public PrinterData()
{
copies = -1;
colour = -1;
duplex = -1;
source = -1;
}
public int copies { get; set; }
public int colour { get; set; }
public int duplex { get; set; }
public int source { get; set; }
}
public class PRNsettings
{
private IntPtr hPrinter = new System.IntPtr();
private PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS();
private PRINTER_INFO_2 pinfo = new PRINTER_INFO_2();
private DEVMODE dm;
private IntPtr ptrDM;
private IntPtr ptrPrinterInfo;
private int sizeOfDevMode = 0;
private int lastError;
private int nBytesNeeded;
private long nRet;
private int intError;
private System.Int32 nJunk;
private IntPtr yDevModeData;
[DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern Int32 GetLastError();
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter,
[MarshalAs(UnmanagedType.LPStr)] string pDeviceNameg, IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode);
[DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
[DllImport("winspool.drv", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command);
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Name);
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{
public int pDatatype;
public int pDevMode;
public int DesiredAccess;
}
[StructLayout(LayoutKind.Sequential)]
private struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPStr)] public string pServerName;
[MarshalAs(UnmanagedType.LPStr)] public string pPrinterName;
[MarshalAs(UnmanagedType.LPStr)] public string pShareName;
[MarshalAs(UnmanagedType.LPStr)] public string pPortName;
[MarshalAs(UnmanagedType.LPStr)] public string pDriverName;
[MarshalAs(UnmanagedType.LPStr)] public string pComment;
[MarshalAs(UnmanagedType.LPStr)] public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPStr)] public string pSepFile;
[MarshalAs(UnmanagedType.LPStr)] public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPStr)] public string pDatatype;
[MarshalAs(UnmanagedType.LPStr)] public string pParameters;
public IntPtr pSecurityDescriptor;
public Int32 Attributes;
public Int32 Priority;
public Int32 DefaultPriority;
public Int32 StartTime;
public Int32 UntilTime;
public Int32 Status;
public Int32 cJobs;
public Int32 AveragePPM;
}
private const short CCDEVICENAME = 32;
private const short CCFORMNAME = 32;
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
public string dmFormName;
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public uint dmMediaType;
}
private const int DM_DUPLEX = 0x1000;
private const int DM_IN_BUFFER = 8;
private const int DM_OUT_BUFFER = 2;
private const int PRINTER_ACCESS_ADMINISTER = 0x4;
private const int PRINTER_ACCESS_USE = 0x8;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
public int returnSource;
public int returnDuplex;
public int returnColor;
public int returnCopies;
public bool SetDefault(string name)
{
try
{
return SetDefaultPrinter(name);
}
catch (Exception) { return false; }
}
public bool ChangePrinterSetting(string PrinterName, PrinterData PS)
{
try
{
dm = this.GetPrinterSettings(PrinterName);
// Sent back to allow reset of the settings back to original.
returnSource = dm.dmDefaultSource;
returnDuplex = dm.dmDuplex;
returnColor = dm.dmColor;
returnCopies = dm.dmCopies;
if (PS.source > -1)
dm.dmDefaultSource = (short)PS.source;
if (PS.duplex > -1)
dm.dmDuplex = (short)PS.duplex;
if (PS.colour > -1)
dm.dmColor = (short)PS.colour;
if (PS.copies > -1)
dm.dmCopies = (short)PS.copies;
Marshal.StructureToPtr(dm, yDevModeData, true);
pinfo.pDevMode = yDevModeData;
pinfo.pSecurityDescriptor = IntPtr.Zero;
Marshal.StructureToPtr(pinfo, ptrPrinterInfo, false);
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
// Error
if (nRet == 0)
return false;
if (hPrinter != IntPtr.Zero)
ClosePrinter(hPrinter);
return Convert.ToBoolean(nRet);
}
catch (Exception) { return false; }
}
public DEVMODE GetPrinterSettings(string PrinterName)
{
PrinterData PData = new PrinterData();
DEVMODE dm;
const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
PrinterValues.pDatatype = 0;
PrinterValues.pDevMode = 0;
PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(PrinterName,
out hPrinter, PrinterValues));
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
Marshal.AllocCoTaskMem(nBytesNeeded);
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, out nJunk));
pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterInfo, typeof(PRINTER_INFO_2));
IntPtr Temp = new IntPtr();
if (pinfo.pDevMode == IntPtr.Zero)
{
IntPtr ptrZero = IntPtr.Zero;
sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrZero, ref ptrZero, 0);
ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
int i = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrDM, ref ptrZero, DM_OUT_BUFFER);
pinfo.pDevMode = ptrDM;
}
intError = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, IntPtr.Zero, ref Temp, 0);
yDevModeData = Marshal.AllocHGlobal(intError);
intError = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, yDevModeData, ref Temp, 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
return dm;
}
}
If you get this error when building for AnyCPU or x64 you might find my answer here helpfull:
WinSpool OpenPrinter Access Denied - building for AnyCPU\x64
I have a class that is attempting to create a process from within a service using credentials provided.
When launching the process I am seeing an error Cannot create a file when that file already exists. What is causing this?
I've tried calling all types of executables, so I know it's not the process being created throwing this.
public class ProcessAsUser
{
static ProcessAsUser()
{
UserToken = IntPtr.Zero;
}
private static IntPtr UserToken { get; set; }
public int StartProcess(ProcessStartInfo processStartInfo)
{
UserToken = IntPtr.Zero;
LogInOtherUser(processStartInfo);
var startUpInfo = new Native.STARTUPINFO();
uint creationFlags = 0;
if (processStartInfo.CreateNoWindow) creationFlags |= Native.CREATE_NO_WINDOW;
var processInfo = new Native.PROCESS_INFORMATION();
bool processStarted = Native.CreateProcessAsUser(
UserToken, // user token
processStartInfo.FileName, // application name
processStartInfo.Arguments, // commandline
IntPtr.Zero, // process attributes
IntPtr.Zero, // thread attributes
true, // inherrit handle
creationFlags, // creation flags
IntPtr.Zero, // environment
processStartInfo.WorkingDirectory+"\\", // current directory
ref startUpInfo,
out processInfo
);
if (!processStarted)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
return 0;
}
int processId = (int)processInfo.dwProcessId;
Native.CloseHandle(processInfo.hProcess);
Native.CloseHandle(processInfo.hThread);
ProcessId = processId;
return ProcessId;
}
public int ProcessId;
private static void LogInOtherUser(ProcessStartInfo processStartInfo)
{
if (UserToken == IntPtr.Zero)
{
var tempUserToken = IntPtr.Zero;
var password = SecureStringToString(processStartInfo.Password);
bool loginResult = Native.LogonUser(processStartInfo.UserName, processStartInfo.Domain, password,
Native.LOGON32_LOGON_BATCH, Native.LOGON32_PROVIDER_DEFAULT,
ref tempUserToken);
if (loginResult)
{
UserToken = tempUserToken;
}
else
{
Native.CloseHandle(tempUserToken);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
private static String SecureStringToString(SecureString value)
{
var stringPointer = Marshal.SecureStringToBSTR(value);
try
{
return Marshal.PtrToStringBSTR(stringPointer);
}
finally
{
Marshal.FreeBSTR(stringPointer);
}
}
public static void ReleaseUserToken()
{
Native.CloseHandle(UserToken);
}
}
internal class Native
{
internal const int LOGON32_LOGON_INTERACTIVE = 2;
internal const int LOGON32_LOGON_BATCH = 4;
internal const int LOGON32_PROVIDER_DEFAULT = 0;
public const int DUPLICATE_SAME_ACCESS = 2;
public const int CREATE_NO_WINDOW = 0x08000000;
public const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
[StructLayout(LayoutKind.Sequential)]
internal class PROCESS_INFORMATION
{
public IntPtr hProcess = IntPtr.Zero;
public IntPtr hThread = IntPtr.Zero;
public uint dwProcessId = 0;
public uint dwThreadId = 0;
}
[StructLayout(LayoutKind.Sequential)]
internal class STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop = string.Empty;
public string lpTitle;
public int dwX = 0;
public int dwY = 0;
public int dwXSize = 0;
public int dwYSize = 0;
public int dwXCountChars = 0;
public int dwYCountChars = 0;
public int dwFillAttribute = 0;
public int dwFlags = 0;
public short wShowWindow = 0;
public short cbReserved2 = 0;
public IntPtr lpReserved2 = IntPtr.Zero;
public IntPtr hStdInput = IntPtr.Zero;
public IntPtr hStdOutput = IntPtr.Zero;
public IntPtr hStdError = IntPtr.Zero;
public STARTUPINFO()
{
cb = Marshal.SizeOf(this);
}
}
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES
{
public SECURITY_ATTRIBUTES()
{
nLength = Marshal.SizeOf(this);
}
public int nLength;
public IntPtr lpSecurityDescriptor = IntPtr.Zero;
public bool bInheritHandle;
}
[DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserA", SetLastError = true, CharSet = CharSet.Ansi)]
internal static extern bool CreateProcessAsUser(
IntPtr hToken,
[MarshalAs(UnmanagedType.LPStr)] string lpApplicationName,
[MarshalAs(UnmanagedType.LPStr)] string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandle,
uint dwCreationFlags,
IntPtr lpEnvironment,
[MarshalAs(UnmanagedType.LPStr)] string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
internal static extern bool CloseHandle(IntPtr handle);
}
Hello I've used this example on how to access printer status using winspool.
//Code written by Mark Middlemist - #delradie
//Made available at http://delradiesdev.blogspot.com
//Interop details from http://pinvoke.net/
using System;
using System.Runtime.InteropServices;
namespace DelradiesDev.PrinterStatus
{
public class WinSpoolPrinterInfo
{
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
[DllImport("winspool.drv", SetLastError = true)]
public static extern int ClosePrinter(IntPtr hPrinter);
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pServerName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pShareName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPortName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDriverName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pComment;
[MarshalAs(UnmanagedType.LPTStr)]
public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPTStr)]
public string pSepFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPTStr)]
public string pParameters;
public IntPtr pSecurityDescriptor;
public uint Attributes;
public uint Priority;
public uint DefaultPriority;
public uint StartTime;
public uint UntilTime;
public uint Status;
public uint cJobs;
public uint AveragePPM;
}
public PRINTER_INFO_2? GetPrinterInfo(String printerName)
{
IntPtr pHandle;
PRINTER_DEFAULTS defaults = new PRINTER_DEFAULTS();
PRINTER_INFO_2? Info2 = null;
OpenPrinter(printerName, out pHandle, ref defaults);
Int32 cbNeeded = 0;
bool bRet = GetPrinter(pHandle, 2, IntPtr.Zero, 0, out cbNeeded);
if (cbNeeded > 0)
{
IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
bRet = GetPrinter(pHandle, 2, pAddr, cbNeeded, out cbNeeded);
if (bRet)
{
Info2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pAddr, typeof(PRINTER_INFO_2));
}
Marshal.FreeHGlobal(pAddr);
}
ClosePrinter(pHandle);
return Info2;
}
}
}
However, When I call the function, I do not know what kind of data I would pass except the printername. Can somebody help me?
OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault)
GetPrinter(IntPtr hPrinter, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded)
ClosePrinter(IntPtr hPrinter)
What Data would I pass on that functions?
I'm not sure I understand your question. You will only have to call your GetPrinterInfo-method and it in turn will use the functions from the Winspool.drv generating the managed PRINTER_INFO_2 struct for you.
i have a project about USB disk.i have achieved eject the usb disk in my code.but then i want to know how to reload it? Can anyone give me some suggestion.
better an example!thx
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
private void btnenable_Click(object sender, EventArgs e)
{
const string keyName = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\USBSTOR";
// int tLong = (int )Registry.GetValue(keyName, "Start",0);
Registry.SetValue(keyName, "Start", "00000003");
MessageBox.Show("USB MassStorage Enabled");
}
private void btndisable_Click(object sender, EventArgs e)
{
const string keyName = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\USBSTOR";
// int tLong = (int )Registry.GetValue(keyName, "Start",0);
Registry.SetValue(keyName, "Start", "00000004");
MessageBox.Show("USB MassStorage Disabled");
}
I have resolved this question in this way,flow is my code:
win32.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace SystemDevices
{
[StructLayout(LayoutKind.Sequential)]
public struct SP_BROADCAST_HANDLE
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
public IntPtr dbch_handle;
public IntPtr dbch_hdevnotify;
public Guid dbch_eventguid;
public long dbch_nameoffset;
public byte dbch_data;
public byte dbch_data1;
}
[StructLayout(LayoutKind.Sequential)]
public class DEV_BROADCAST_DEVICEINTERFACE
{
public int dbcc_size;
public int dbcc_devicetype;
public int dbcc_reserved;
}
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
public int cbSize;
public Guid classGuid;
public int devInst;
public IntPtr reserved;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINSTALL_PARAMS
{
public int cbSize;
public int Flags;
public int FlagsEx;
public IntPtr hwndParent;
public IntPtr InstallMsgHandler;
public IntPtr InstallMsgHandlerContext;
public IntPtr FileQueue;
public IntPtr ClassInstallReserved;
public int Reserved;
[MarshalAs(UnmanagedType.LPTStr)]
public string DriverPath;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_PROPCHANGE_PARAMS
{
public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
public int StateChange;
public int Scope;
public int HwProfile;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_CLASSINSTALL_HEADER
{
public int cbSize;
public int InstallFunction;
};
public class Win32
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, DEV_BROADCAST_DEVICEINTERFACE NotificationFilter, UInt32 Flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern UInt32 UnregisterDeviceNotification(IntPtr hHandle);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPStr)]String Enumerator, IntPtr hwndParent, Int32 Flags);
[DllImport("setupapi.dll")]
public static extern IntPtr SetupDiGetClassDevsEx(ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPStr)]String Enumerator,
IntPtr hwndParent, Int32 Flags, IntPtr DeviceInfoSet,
[MarshalAs(UnmanagedType.LPStr)]String MachineName,
IntPtr Reserved);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Boolean SetupDiEnumDeviceInfo(IntPtr lpInfoSet, Int32 dwIndex, SP_DEVINFO_DATA devInfoData);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property,
UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern Boolean SetupDiSetClassInstallParams(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, SP_PROPCHANGE_PARAMS ClassInstallParams, int ClassInstallParamsSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiCallClassInstaller(UInt32 InstallFunction, IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiClassNameFromGuid(ref Guid ClassGuid, StringBuilder className, Int32 ClassNameSize, ref Int32 RequiredSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiGetClassDescription(ref Guid ClassGuid, StringBuilder classDescription, Int32 ClassDescriptionSize, ref Int32 RequiredSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, Int32 DeviceInstanceIdSize, ref Int32 RequiredSize);
public const int DIGCF_ALLCLASSES = (0x00000004);
public const int DIGCF_PRESENT = (0x00000002);
public const int INVALID_HANDLE_VALUE = -1;
public const int SPDRP_DEVICEDESC = (0x00000000);
public const int MAX_DEV_LEN = 200;
public const int DEVICE_NOTIFY_WINDOW_HANDLE = (0x00000000);
public const int DEVICE_NOTIFY_SERVICE_HANDLE = (0x00000001);
public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = (0x00000004);
public const int DBT_DEVTYP_DEVICEINTERFACE = (0x00000005);
public const int DBT_DEVNODES_CHANGED = (0x0007);
public const int WM_DEVICECHANGE = (0x0219);
public const int DIF_PROPERTYCHANGE = (0x00000012);
public const int DICS_FLAG_GLOBAL = (0x00000001);
public const int DICS_FLAG_CONFIGSPECIFIC = (0x00000002);
public const int DICS_ENABLE = (0x00000001);
public const int DICS_DISABLE = (0x00000002);
public static bool StateChange(bool Enable, int SelectedItem, IntPtr DevInfo)
{
bool result = false;
SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA(); ;
devInfoData.cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
if (true == SetupDiEnumDeviceInfo(DevInfo, SelectedItem, devInfoData))
{
SP_PROPCHANGE_PARAMS pcp = new SP_PROPCHANGE_PARAMS(); ;
pcp.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(SP_CLASSINSTALL_HEADER));
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
pcp.Scope = DICS_FLAG_GLOBAL;
pcp.StateChange = (Enable ? DICS_ENABLE : DICS_DISABLE);
if (true == SetupDiSetClassInstallParams(DevInfo, devInfoData, pcp, Marshal.SizeOf(pcp)))
{
if (true == SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DevInfo, devInfoData))
{
result = true;
}
}
}
return result;
}
public static String GetClassNameFromGuid(Guid guid)
{
String result = String.Empty;
StringBuilder className = new StringBuilder();
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);
className = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);
if (true == b)
{
result = className.ToString();
}
return result;
}
public static String GetClassDescriptionFromGuid(Guid guid)
{
String result = String.Empty;
StringBuilder classDesc = new StringBuilder(0);
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);
classDesc = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);
if (true == b)
{
result = classDesc.ToString();
}
return result;
}
public static String GetDeviceInstanceId(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData)
{
String result = String.Empty;
StringBuilder id = new StringBuilder(0);
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);
id = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);
if (true == b)
{
result = id.ToString();
}
return result;
}
}
}
in the win32.cs there is some function to control the hardware.
function StateChange(bool Enable, int SelectedItem, IntPtr DevInfo) is used to control the hardware start or stop.
there are three Parameters.when the Enable is true,this function makes the hardware whos id is SelectedItem start,if false stop.i get the id in this code:
Guid classGuid = Guid.Empty;
IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, Win32.DIGCF_ALLCLASSES | Win32.DIGCF_PRESENT);
if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
{
Console.WriteLine("read hardware information error");
}
else
{
int i = 0;
StringBuilder deviceName = new StringBuilder();
deviceName.Capacity = Win32.MAX_DEV_LEN;
do
{
SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA();
devInfoData.cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
devInfoData.classGuid = Guid.Empty;
devInfoData.devInst = 0;
devInfoData.reserved = IntPtr.Zero;
bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
if (false == result)
{
break;
}
Console.WriteLine("Device: {0}", i);
Console.WriteLine("\tGuid={0}", devInfoData.classGuid);
Console.WriteLine("\tName={0}", Win32.GetClassNameFromGuid(devInfoData.classGuid));
Console.WriteLine("\tDescription={0}", Win32.GetClassDescriptionFromGuid(devInfoData.classGuid));}
There is a tool (devcon) available from Microsoft that can be used to achieve the functionality of the device manager.
The following command is used to remove a specific device (Assuming your device name is Kingston)
> devcon remove *Kingston*
This causes the device to be disabled. So it is no longer available.
The command rescan enables the device.
> devcon rescan
You can execute this command through the Process.Start() method.
This does not work with devices that have marked for 'Safe Removal'