Не могу изменить 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();
}

Не удается, когда я пытаюсь выполнить PrinterSettings.SetHdevmode с NullReferenceException и без какой-либо значимой информации об ошибке. d.PrinterSettings не является нулевым, исключение выбрасывается внутри PrinterSettings.SetHdevmode метод.
Итак, мой вопрос: что не так? Это byte[] в IntPtr бросить неправильно? Может быть SetHdevmode ожидает что-то другое, чем byte[] массив?

Я получаю byte[] devmode_data массив из реестра. Это допустимое значение, и это то же значение, которое используется в текущих настройках принтера.

2 ответа

Я изменил ваш код следующим образом, поскольку у меня нет действительных данных для devmode_data:

devmode = d.PrinterSettings.GetHdevmode();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);

и теперь здесь нет исключений.

Пожалуйста, предоставьте мне ваши данные для devmode_data или проверьте свой, действителен ли он или нет!

SetHdevmode ожидает HGLOBAL, Вы можете получить HGLOBAL из.Net через Marshal.AllocHGlobal, Затем вы можете использовать Marshal.Copy(byte[], int, IntPtr, int) скопировать из вашего управляемого байтового массива в HGLOBAL, Увидеть ниже:

var pDevMode = Marshal.AllocHGlobal(devmode_data.Length);
Marshal.Copy(devmode_data, 0, pDevMode, devmode_data.Length);

d.PrinterSettings.SetHdevmode(pDevMode);
Marshal.FreeHGlobal(pDevMode);

Массив байтов может быть частично обработан как структура, но для этого потребуются определения p/Invoke. PrinterSettings Класс, однако, не примет структуру, поэтому в этом случае это не потребуется. Кроме того, DEVMODE Структура переменной длины, позволяющая драйверам принтера добавлять дополнительные непрозрачные данные, поэтому преобразование невозможно без потери данных.

См. Как я могу сохранить и восстановить `PrinterSettings`? для большего.

Другие вопросы по тегам