Не могу изменить DEVMODE принтера - PullRequest
3 голосов
/ 27 ноября 2011

Мне нужно изменить 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 ]

1 голос
/ 27 ноября 2011

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

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

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

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

0 голосов
/ 18 января 2015

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`? , чтобы узнать больше.

...