Nurked
@Nurked
Птица-говорун. Писец пером, программец компьютером

Как правильно принимать данные по LPT?

Поразвелось в мире программ бухгалтерских, написанных в махровых годах. Каждая из них печатает на чём хочет и как хочет. В итоге, для того, чтобы поставить эти программы на современные операционки надо изобретать велосипеды.

Я написал софтину — перенаправлятель прнтеров — она сидит и прикидывается старым сетевым принтером на порту 9100. При поступлении текста на этот порт программа сохраняет его в читабельном виде и открывает виндовский диалог печати, предлагая пользователю распечатать документ на имеющихся принтерах. Это было легко — перехватить сетевой трафик на порту 9100. Сидишь и ждёшь поступления данных, а дальше сохраняешь их из потока в файл.

Но в организации появился софт древнее и дремучее. Эта софтина не признаёт никаких сетевых принтеров. Признает только порты LPT1-3 и COM1,2. Если ЛПТ ещё можно как-то обойти через net use LTP1 \\sharename то с комами приходится труднее. + пользователь мою софтину полюбил и ему нравится возможность сохранять распечатки в файлах и выбирать принтеры в системе. Поэтому меня попросили допилить программу до поддержки LPT и COM.

Я радостно сказал «Да!» и… Не нашёл приличных мануалов. Индусы щедро раздают информацию о том, как считать текущее состояние пина на ЛПТ, но этим всё и ограничивается.

Кто может помочь с информацией о том, как правильно «Притворяться» принтером на ЛПТ и КОМах, чтобы получать текст, который программа хочет распечатать?

Пишется всё это на Шарпах с четвёртым дотнэтом. (Я понимаю, что и второго хватило бы, но целевая аудитория сидит на виндах 7 и 8, а в последней со вторым дотнэтом нелады)

Готов отдать программу в руки общественности после того, как запилю поддержку LPT и COM — в помощь сисадминам, которые мучаются с восхитительными трудами Вась Пупкиных времён 18 века.
  • Вопрос задан
  • 4931 просмотр
Решения вопроса 1
Myrkr
@Myrkr
Нет ничего особо сложного в том чтобы общаться с драйвером
Сами драйверы можно скачать Тут
А удобный класс для работы с ними вот.

using System;
using System.Runtime.InteropServices;

namespace PortAccess {
	public class ParallelPort {
		[DllImport("inpout32.dll")]
		private static extern UInt32 IsInpOutDriverOpen();
		[DllImport("inpout32.dll")]
		private static extern void Out32(short portAddress, short data);
		[DllImport("inpout32.dll")]
		private static extern char Inp32(short portAddress);
		[DllImport("inpout32.dll")]
		private static extern void DlPortWritePortUshort(short portAddress, ushort data);
		[DllImport("inpout32.dll")]
		private static extern ushort DlPortReadPortUshort(short portAddress);
		[DllImport("inpout32.dll")]
		private static extern void DlPortWritePortUlong(int portAddress, uint data);
		[DllImport("inpout32.dll")]
		private static extern uint DlPortReadPortUlong(int portAddress);

		[DllImport("inpoutx64.dll")]
		private static extern bool GetPhysLong(ref int portAddress, ref uint data);
		[DllImport("inpoutx64.dll")]
		private static extern bool SetPhysLong(ref int portAddress, ref uint data);
		[DllImport("inpoutx64.dll", EntryPoint = "IsInpOutDriverOpen")]
		private static extern UInt32 IsInpOutDriverOpenmode();
		[DllImport("inpoutx64.dll", EntryPoint = "Out32")]
		private static extern void Out32mode(short portAddress, short data);
		[DllImport("inpoutx64.dll", EntryPoint = "Inp32")]
		private static extern char Inp32mode(short portAddress);
		[DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUshort")]
		private static extern void DlPortWritePortUshortmode(short portAddress, ushort data);
		[DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUshort")]
		private static extern ushort DlPortReadPortUshortmode(short portAddress);
		[DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUlong")]
		private static extern void DlPortWritePortUlongmode(int portAddress, uint data);
		[DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUlong")]
		private static extern uint DlPortReadPortUlongmode(int portAddress);
		[DllImport("inpoutx64.dll", EntryPoint = "GetPhysLong")]
		private static extern bool GetPhysLongmode(ref int portAddress, ref uint data);
		[DllImport("inpoutx64.dll", EntryPoint = "SetPhysLong")]
		private static extern bool SetPhysLongmode(ref int portAddress, ref uint data);

		private bool mode;
		private short portAddress;

		public ParallelPort(short portAddress) {
			mode = false;
			this.portAddress = portAddress;
			try {
				uint nResult = 0;
				try {
					nResult = IsInpOutDriverOpen();
				}
				catch (BadImageFormatException) {
					nResult = IsInpOutDriverOpenmode();
					if (nResult != 0) {
						mode = true;
					}
				}
				if (nResult == 0 ) {
					throw new ArgumentException("Unable to open InpOut32 driver");
				}
			}
			catch (DllNotFoundException) {
				throw new ArgumentException("Unable to find InpOut32.dll");
			}
		}

		public void Write(short data) {
			if (mode) {
				Out32mode(portAddress, data);
			}
			else {
				Out32(portAddress, data);
			}
		}

		public byte Read() {
			if (mode) {
				return (byte)Inp32mode(portAddress);
			}
			else {
				return (byte)Inp32(portAddress);
			}
		}
	}
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@mayorovp
Возможно, сейчас я скапинанствую, но надо писать драйвер виртуального порта.
Ответ написан
@Flexz
С LPT сложно. Дело в том, что в последних виндах (хотя какой там «в последних», это уже с w2k) к LPT порту, как к устройству, доступ можно получить только из драйвера. Либо с помощью «читерства» — примеры со всякими giveio.dll вы, наверное, уже встречали.

С COM возможно будет легче. Первое что приходит в голову — комп с двумя COM-портами (USB-COM или PCI-COM их сейчас не проблема добыть), порты соединяем кроссом, возможно, хватит TX-RX. Один порт открывает ваша программа-эмулятор, другой порт — печатающее ископаемое.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы