无法更改打印机的 DEVMODE
我需要更改当前打印任务的打印机的 DEVMODE
以通过标准和设备特定的设置。我执行以下操作:
PrintDocument d = new PrintDocument();
d.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"; // example printer name
byte[] devmode_data; // contains a valid value that is obtained from registry
IntPtr devmode = IntPtr.Zero;
GCHandle handle = GCHandle.Alloc(devmode_data, GCHandleType.Pinned);
try
{
devmode = handle.AddrOfPinnedObject();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);
}
finally
{
if (handle.IsAllocated) handle.Free();
}
当我尝试使用 NullReferenceException
执行 PrinterSettings.SetHdevmode
且没有任何有意义的错误信息时,它会失败。 d.PrinterSettings
不为 null,异常在 PrinterSettings.SetHdevmode
方法内部抛出。
所以我的问题是:出了什么问题? byte[]
到 IntPtr
的转换是否错误?也许 SetHdevmode
需要 byte[]
数组以外的东西?
我从注册表中获取了 byte[] devmode_data
数组。它是一个有效值,并且与当前打印机设置中使用的值相同。
I need to change DEVMODE
of printer for current printing task to pass standard and device-specific settings. I do the following:
PrintDocument d = new PrintDocument();
d.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"; // example printer name
byte[] devmode_data; // contains a valid value that is obtained from registry
IntPtr devmode = IntPtr.Zero;
GCHandle handle = GCHandle.Alloc(devmode_data, GCHandleType.Pinned);
try
{
devmode = handle.AddrOfPinnedObject();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);
}
finally
{
if (handle.IsAllocated) handle.Free();
}
It fails when I attempt to execute PrinterSettings.SetHdevmode
with a NullReferenceException
and without any meaningful error info. d.PrinterSettings
is not null, the exception is thrown inside of PrinterSettings.SetHdevmode
method.
So my question is: what is wrong? Is the byte[]
to IntPtr
cast wrong? Maybe SetHdevmode
expects something other than a byte[]
array?
I get the byte[] devmode_data
array from the registry. It is a valid value and it is same value that is used in current printer settings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我按以下方式修改了您的代码,因为我没有
devmode_data
的任何有效数据:现在这里也不例外。
请向我提供您的
devmode_data
数据,或者检查您自己的数据是否有效!I modified your code in the following way, since I don't have any valid data for
devmode_data
:and now there is no exception here.
Please, provide me with your data for
devmode_data
or check for your own, if it is valid or not!SetHdevmode
需要一个HGLOBAL
。您可以通过Marshal.AllocHGlobal
从 .Net 获取HGLOBAL
。然后,您可以使用Marshal.Copy(byte[], int, IntPtr, int)
将托管字节数组复制到HGLOBAL
。见下文:字节数组可以部分作为结构处理,但这需要 p/调用定义。然而,PrinterSettings 类不接受结构,因此在这种情况下不需要这样做。此外,DEVMODE 结构是可变长度的,以允许打印机驱动程序添加额外的不透明数据,因此不可能在不丢失数据的情况下进行转换。
有关详细信息,请参阅如何保存和恢复“PrinterSettings”?。
SetHdevmode
expects anHGLOBAL
. You can get anHGLOBAL
from .Net viaMarshal.AllocHGlobal
. Then, you can useMarshal.Copy(byte[], int, IntPtr, int)
to copy from your managed byte array to theHGLOBAL
. See below:The byte array can be partially handled as a structure, but that will require p/Invoke definitions. The
PrinterSettings
class, however, will not accept a structure, so doing so would be unneeded in this case. Additionally, theDEVMODE
structure is variable length to allow for printer drivers to add additional opaque data, so it would not be possible to convert without data loss.See How can I save and restore `PrinterSettings`? for more.