воскресенье, 2 февраля 2025 г.

Пример приложения печатающий текст в стиле терминала из фильма Matrix "Матрица"

Спустя 12 лет довел до ума пример приложения, который печатает текст в стиле терминала из фильма Матрица с DelphiX на OpenGL. Оригинальный пример, на основе которого сделан мой пример, взят с сайта Delphi-Graphics. Мой код базируется на Delphi, OpenGL, WinAPI. Код моего примера оставляю без комментарий, т. к. написание проводилось без детального разбора работы алгоритма оригинального приложения и осуществлялся банальный подбор функций OpenGL и их параметров. На рисунке 1 представлена работа моего примера в Windows 10. 

Рисунок 1. Пример приложения вывода текста в стиле терминала из фильма "Матрица"

program matrix;

uses
  Windows,
  Messages,
  OpenGL;

var
  h_Rc: HGLRC;
  h_Dc: HDC;
  h_Wnd: HWND;
  base: GLuint;

  keys: array [0..255] of BOOL;

  text: array[0..4] of String = ('Wake up, Neo.',
                                 'The Matrix has you.',
                                 'Follow the White Rabbit.',
                                 'Disconnecting...',
                                 '');

  Active: bool = true;
  FullScreen:bool = true;
  f,z: boolean;
  a,b: byte;
  sx: integer;
  cur: byte;
  all: string;

procedure ReSizeGLScene(Width: GLsizei; Height: GLsizei);
begin
  if (Height=0) then
     Height:=1;
  glViewport(0, 0, Width, Height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, Width, Height, 0, 1, -1);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

procedure BuildFont;
var
  font: HFONT;
  oldfont: HFONT;
begin

  base := glGenLists(96);

  font := CreateFont( -30,
                        0,
                        0,
                        0,
                        FW_BOLD,
                        0,
                        0,
                        0,
                        ANSI_CHARSET,
                        OUT_TT_PRECIS,
                        CLIP_DEFAULT_PRECIS,
                        ANTIALIASED_QUALITY,
                        FF_DONTCARE or DEFAULT_PITCH,
                        'Courier New');

  oldfont := SelectObject(h_DC, font);                       
  wglUseFontBitmaps(h_DC, 32, 96, base);
  SelectObject(h_DC, oldfont);
  DeleteObject(font);
end;

procedure KillFont;
begin
  glDeleteLists(base, 96);
end;

procedure glPrint(const Fmt: String);
begin

if Fmt = '' then
  Exit;

glPushAttrib(GL_LIST_BIT);
glListBase(base - 32);
glCallLists(Length(Fmt), GL_UNSIGNED_BYTE, Pointer(Fmt));
glPopAttrib();

end;

function IntToStr(Num: Integer) : String;
begin
  Str(Num, Result);  
end;

function InitGL:bool;
begin

  glClearColor(0.0, 0.0, 0.0, 0.0);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, 640, 480, 0, 0, 1);
  glDisable(GL_DEPTH_TEST);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  BuildFont();

  a:=0;
  b:=0;
  sx:=0;
  cur:=0;

  Result:=true;
end;

procedure addchar;
begin
  if length(all)=length(text[cur]) then
  begin
    inc(cur);
    sx:=0;
    z:=false;
    all:='';
    Exit;
  end;
  if cur<=5 then
  begin
    all := all + text[cur][length(all)+1];
  end
  else
  begin
    exit;
  end;
end;

function DrawGLScene():bool;
var
  i: integer;
  kk2:integer;
  kk: integer;
begin
  glClear(GL_COLOR_BUFFER_BIT);

  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glLoadIdentity();

  if not z then
    inc(sx);
  if sx=200 then
    z:=true;

  if z then
  begin
    inc(B);
    if b=20 then addchar;
    if b>20 then b:=0;
  end;

  if not f then
    inc(a,5)
  else dec(a,5);

  if (a>=255)or(a=0) then f:=not f;

  glColor3f(0.196078, 0.8, 0.196078);
  for i := 0 to cur - 1 do
  begin
    glRasterPos2f(0.0, 20.0 + i*30);
    glPrint(text[i]);
  end;

  if i=5 then
  begin
    i:=0;
    cur:=0;
    a:=0;
    b:=0;
    sx:=0;
    z:=false;
    f:=False;
    all:='';
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
  end;

  kk := 18*length(all);
  kk2 := cur*30;

  glRasterPos2f(0.0, 20.0 + cur*30);
  glPrint(all);

  glColor4f(0.196078, 0.8, 0.196078, a / 255); // Colour LimeGreen
  glRectf(0.0+kk, 0.0+kk2, 23.0+kk, 23.0+kk2);

  glDisable(GL_BLEND);
  glDisable(GL_ALPHA_TEST);

  Result := true;
end;


function WndProc(hWnd: HWND;
                 message: UINT;
                 wParam: WPARAM;
                 lParam: LPARAM):
                                  LRESULT; stdcall;
begin
  if message=WM_SYSCOMMAND then
  begin
      case wParam of
        SC_SCREENSAVE,SC_MONITORPOWER:
          begin
            result:=0;
            exit;
          end;
      end;
  end;
  
  case message of
    WM_ACTIVATE:
      begin
        if (Hiword(wParam)=0) then
          active:=true
        else
          active:=false;
        Result:=0;
      end;
    WM_CLOSE:
      Begin
        PostQuitMessage(0);
        result:=0
      end;
    WM_KEYDOWN:
      begin
        keys[wParam] := TRUE;
        result:=0;
      end;
    WM_KEYUP:
      begin
    	  keys[wParam] := FALSE;
        result:=0;
      end;
    WM_SIZe:
      begin
    	  ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
        result:=0;
      end
    else

      begin
      	Result := DefWindowProc(hWnd, message, wParam, lParam);
      end;
    end;
end;


procedure KillGLWindow;
begin
  if FullScreen then
    begin
      ChangeDisplaySettings(devmode(nil^),0);
      showcursor(true);
    end;
  if h_rc<> 0 then
    begin
      if (not wglMakeCurrent(h_Dc,0)) then
        MessageBox(0,'Release of DC and RC failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
      if (not wglDeleteContext(h_Rc)) then
        begin
          MessageBox(0,'Release of Rendering Context failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
          h_Rc:=0;
        end;
    end;
  if (h_Dc=1) and (releaseDC(h_Wnd,h_Dc)<>0) then
    begin
      MessageBox(0,'Release of Device Context failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
      h_Dc:=0;
    end;
  if (h_Wnd<>0) and (not destroywindow(h_Wnd))then
    begin
      MessageBox(0,'Could not release hWnd.',' Shutdown Error',MB_OK or MB_ICONERROR);
      h_Wnd:=0;
    end;
  if (not UnregisterClass('OpenGL',hInstance)) then
    begin
      MessageBox(0,'Could Not Unregister Class.','SHUTDOWN ERROR',MB_OK or MB_ICONINFORMATION);
    end;
end;


function CreateGlWindow(title:Pchar; width,height,bits:integer;FullScreenflag:bool):boolean stdcall;
var
  Pixelformat: GLuint;
  wc:TWndclass;
  dwExStyle:dword;
  dwStyle:dword;
  pfd: pixelformatdescriptor;
  dmScreenSettings: Devmode;
  h_Instance:hinst;
  WindowRect: TRect;
begin
  WindowRect.Left := 0;
  WindowRect.Top := 0;
  WindowRect.Right := width;
  WindowRect.Bottom := height;
  h_instance:=GetModuleHandle(nil);
  FullScreen:=FullScreenflag;
  with wc do
    begin
      style:=CS_HREDRAW or CS_VREDRAW or CS_OWNDC;
      lpfnWndProc:=@WndProc;
      cbClsExtra:=0;
      cbWndExtra:=0;
      hInstance:=h_Instance;
      hIcon:=LoadIcon(0,IDI_WINLOGO);
      hCursor:=LoadCursor(0,IDC_ARROW);
      hbrBackground:=0;
      lpszMenuName:=nil;
      lpszClassName:='OpenGl';
    end;
  if  RegisterClass(wc)=0 then
    begin
      MessageBox(0,'Failed To Register The Window Class.','Error',MB_OK or MB_ICONERROR);
      Result:=false;
      exit;
    end;
  if FullScreen then
    begin
      ZeroMemory( @dmScreenSettings, sizeof(dmScreenSettings) );
      with dmScreensettings do
        begin
          dmSize := sizeof(dmScreenSettings);
          dmPelsWidth  := width;
	        dmPelsHeight := height;
          dmBitsPerPel := bits;
          dmFields     := DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
        end;

      if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN))<>DISP_CHANGE_SUCCESSFUL THEN
        Begin

          if MessageBox(0,'This FullScreen Mode Is Not Supported. Use Windowed Mode Instead?'
                                             ,'Matrix',MB_YESNO or MB_ICONEXCLAMATION)= IDYES then
                FullScreen:=false
          else
            begin

              MessageBox(0,'Program Will Now Close.','Error',MB_OK or MB_ICONERROR);
              Result:=false;
              exit;
            end;
          end;
    end;
  if FullScreen then
    begin
      dwExStyle:=WS_EX_APPWINDOW;
      dwStyle:=WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
      Showcursor(false);
    end
  else
    begin
      dwExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
      dwStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
    end;
  AdjustWindowRectEx(WindowRect,dwStyle,false,dwExStyle);

  H_wnd:=CreateWindowEx(dwExStyle,
                               'OpenGl',
                               Title,
                               dwStyle,
                               0,0,
                               WindowRect.Right-WindowRect.Left,
                               WindowRect.Bottom-WindowRect.Top,
                               0,
                               0,
                               hinstance,
                               nil);
  if h_Wnd=0 then
    begin
      KillGlWindow();
      MessageBox(0,'Window creation error.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  with pfd do
    begin
      nSize:= SizeOf( PIXELFORMATDESCRIPTOR );
      nVersion:= 1;
      dwFlags:= PFD_DRAW_TO_WINDOW
        or PFD_SUPPORT_OPENGL
        or PFD_DOUBLEBUFFER;
      iPixelType:= PFD_TYPE_RGBA;
      cColorBits:= bits;
      cRedBits:= 0;
      cRedShift:= 0;
      cGreenBits:= 0;
      cBlueBits:= 0;
      cBlueShift:= 0;
      cAlphaBits:= 0;
      cAlphaShift:= 0;
      cAccumBits:= 0;
      cAccumRedBits:= 0;
      cAccumGreenBits:= 0;
      cAccumBlueBits:= 0;
      cAccumAlphaBits:= 0;
      cDepthBits:= 16;
      cStencilBits:= 0;
      cAuxBuffers:= 0;
      iLayerType:= PFD_MAIN_PLANE;
      bReserved:= 0;
      dwLayerMask:= 0;
      dwVisibleMask:= 0;
      dwDamageMask:= 0;
    end;
  h_Dc := GetDC(h_Wnd);
  if h_Dc=0 then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t create a GL device context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  PixelFormat := ChoosePixelFormat(h_Dc, @pfd);
  if (PixelFormat=0) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t Find A Suitable PixelFormat.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  if (not SetPixelFormat(h_Dc,PixelFormat,@pfd)) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t set PixelFormat.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  h_Rc := wglCreateContext(h_Dc);
  if (h_Rc=0) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t create a GL rendering context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  if (not wglMakeCurrent(h_Dc, h_Rc)) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t activate the GL rendering context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  ShowWindow(h_Wnd,SW_SHOW);
  SetForegroundWindow(h_Wnd);
  SetFOcus(h_Wnd);
  ReSizeGLScene(width,height);
  if (not InitGl()) then
    begin
      KillGLWindow();
      MessageBox(0,'initialization failed.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  Result:=true;
end;


function WinMain(hInstance: HINST;
		 hPrevInstance: HINST;
		 lpCmdLine: PChar;
		 nCmdShow: integer):
                        integer; stdcall;
var
  msg: TMsg;
  done: Bool;

begin
  done:=false;

  if MessageBox(0,'Would You Like To Run In FullScreen Mode?','Start FullScreen', MB_YESNO or MB_ICONQUESTION)=IDNO then
    FullScreen:=false
  else
    FullScreen:=true;

  if not CreateGLWindow('Matrix',640,480,16,FullScreen) then
  begin
    Result := 0;
    exit;
  end;

  while not done do
  begin
    if (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) then
    begin
      if msg.message=WM_QUIT then
        done:=true
      else
      begin
        TranslateMessage(msg);
        DispatchMessage(msg);
      end;
    end
    else
    begin

      if (Active and (not DrawGLScene()) or keys[VK_ESCAPE]) then
      begin
        done:=true;
      end;

      if (keys[VK_F1]) then
      begin
        Keys[VK_F1] := false;
        KillGLWindow();
        FullScreen := not FullScreen;

        if not CreateGLWindow('Matrix',640,480,16,fullscreen) then Result := 0;
      end;

      SwapBuffers(h_Dc);
    end;
  end;

  KillFont();
  killGLwindow();

  result:=msg.wParam;
end;

begin
  WinMain( hInstance, hPrevInst, CmdLine, CmdShow );
end.

пятница, 24 января 2025 г.

Несколько проблемных МФУ

Кому интересно, перечислю проблемные, относительно новые модели МФУ, которые я не рекомендую покупать.


Xerox VersaLink B405dn

1) Безобразно захватывает бумагу из обоих лотков. Направляющие бумаги у данного принтера реализованы плохо, из-за этого бумага идет не ровно и часто застревает. Замена роликов подачи бумаги или ролика лотка не решает проблему.

2) Печка портится очень быстро, покупка новой выходит дорого. Из-за этого МФУ придётся утилизировать.

3) Сенсорный экран может не нажиматься (Пересекался с двумя такими МФУ с такой проблемой). Может брак.

4) Оба лотка представляют из себя хлипкое изделие, которое болтается в руках как погремушка. При малейшем движение направляющие бумаги лотка разъезжаются.

Xerox WorkCentre 3345

1) Через 3-4 года сенсорный экран перестает реагировать на нажатия или сам по себе начнёт нажиматься без участия пользователя. Покупка сенсорной панели выходит очень дорого. Из-за этого МФУ придётся утилизировать.

HP Laser Jet Pro M428dnf

1) По сети документы Word или PDF печатаются с задержкой в 1 минуту на одну страницу документа. Переустановка драйверов не решает проблему.

2) Драйвера МФУ не корректно работают с масштабированием документа. Иногда в таких программах как Word, ты видишь на предварительном просмотре печати, что документ выглядит как надо, таблица заполняет всю страницу. Отправляешь на принтер, а он выдает таблицу на пол страницы, таким образом сжав таблицу по горизонтали. В свойствах драйвера это можно исправить, но каждый раз при такой проблеме необходимо заходить в свойства драйвера, чтобы распечатать документ.

HP Laser Jet Pro 4103dw

1) Такая же проблема с масштабированием как и в случае с HP Laser Jet Pro M428dnf

 

По мере накопления проблем с разными МФУ и принтерами, буду пополнять список.

среда, 20 ноября 2024 г.

Пример использования ВПР функции в LibreOffice Calc

Функция ВПР работает так же как и в Microsoft Office. Откройте LibreOffice Calc. Создайте второй лист (Смотрите рисунок 1 цифра 1). Переименуйте листы с именами «Лист 1» и «Лист 2» в листы «Результат» и «Детали» соответственно (Смотрите рисунок 1 цифра 2).

Рисунок 1. Добавление нового листа в LibreOffice Calc

На листе «Результат» создайте таблицу как показано на рисунке 2. На листе «Детали» создайте таблицу как показано на рисунке 3. 

Рисунок 2. Пример таблицы "Результат"
 

Рисунок 3. Пример таблицы "Детали"

Таблица «Детали» - это уникальная таблица не повторяющихся значений, содержит наименование детали и её инвентарный номер.
Таблица «Результат» - это сводная таблица, куда мы будем автоматически подставлять инвентарные номера деталей при помощи ВПР функции для соответствующей детали из таблицы «Детали».

Функция ВПР принимает в себя 4 параметра:
1 — номер ячейки значение которой будем искать
2 — диапазон ячеек в которых ищем значение из ячейки указной в параметре 1
3 — номер столбца, где будем брать значение для подстановки, которое соответствует найденному значению из параметра 1. Нумерация столбцов начинается с 1.
4 – Если выставлен 0, то ищется точное совпадение. Если выставлен 1, то ищется приближённое значение.

Заполнять будем столбец «Инвентарный номер детали» в таблице «Результат». Искать будем по значениям столбца «Наименование используемой детали» в таблице «Результат». Искать значения будем в таблице «Детали» и брать соответствующие значения из столбца «Инвентарный номер детали» таблицы «Детали», который имеет номер 2 для ВПР функции в параметре 3.

=ВПР(C4;$Детали.$A$2:$B$10;2;0)
=ВПР(C5;$Детали.$A$2:$B$10;2;0)
------------------------------------------------- и так для остальных ячеек (с C4 по C18)
=ВПР(C18;$Детали.$A$2:$B$10;2;0)

Разберём первую из ВПР функций.

=ВПР(C4;$Детали.$A$2:$B$10;2;0)

Эта функция выводит результат работы в ячейку D4 таблицы «Результат» столбца «Инвентарный номер детали» (Рисунок 2 цифра 2). Первый параметр ВПР функции получает значение ячейки C4 таблицы «Результат» столбца «Наименование используемой детали» (Рисунок 2 цифра 1), которое является «Деталь 2». Второй параметр ВПР функции получает диапазон значений ячеек с A2 по B10 таблицы «Детали» из первого (Наименование детали) и второго (Инвентарный номер детали) столбцов (Рисунок 3 цифра 1). Третий параметр ВПР функции указывает на столбец 2 (Инвентарный номер детали) таблицы «Детали». Четвертый параметр ВПР функции устанавливаем в ноль, искать будем точное совпадение.

Таким образом в ячейке D4 таблицы «Результат» отобразится значение 100-00002, которое соответствует «Деталь 2». И так для всех деталей в таблицы «Результат».

пятница, 25 октября 2024 г.

Запуск UltraVNC сервера на удаленном компьютере в локальной сети через PsExec

Есть такой программный комплекс LANDesk Remote Control, который используется для удаленного подключения к компьютерам в локальной сети. Данная программа состоит: 

- из программы LANDesk Remote Control Agent - это агент, который устанавливается на все компьютеры к которым нужно подключаться.  
- из программа LANDesk Remote Control Viewer – это удаленный просмоторщик, с помощью неё мы подключаемся к нужному компьютеру, где установлен агент.
- из  LANDesk Remote Control Console — это консоль управления, что-то вроде каталога базы данных, куда агенты посылают информацию о компьютерах.

Данный программный комплекс можно использовать по назначению, но есть несколько проблем, которые я бы хотел перечислить:

1) Агент бывает иногда некорректно устанавливается на компьютер
2) Каталог базы данных бывает иногда глючит и не может корректно общаться с агентом
3) Агент иногда теряет связь с каталогом базы данных

Данные проблемы с горем пополам удается решить, но на решение данных проблем уходит большое количество времени от 30 минут до 4 часов в зависимости от характеристик компьютера.

По этой причине мне пришлось искать другие решения для удаленного управления компьютерами в локальной сети. Пора научиться пользоваться программой под названием UltraVNC.

Поискав в Google информацию по настройке сервера UltraVNC я наткнулся на сайт, где рассказывается как можно автоматизировать установку и настройку сервера UltraVNC. Вот это ссылка. На основе этой статьи я написал свои batch файлы для автоматизации развертывания сервера UltraVNC и по необходимости его удаление.           

Первым делом качаем портативную версию UltraVNC с официального сайта она поставляется в заархивированном виде (ZIP файл) https://uvnc.com/component/jdownloads/summary/470-ultravnc-1-4-6-zip.html . На момент написания статьи последняя версия представленная на официальном сайте 1.4.3.6 версия. На всякий случаю оставлю ссылку на главную страницу скачивания UltraVNC https://uvnc.com/downloads/ultravnc.html . Распакуйте архив и вы увидите в нем UltraVNC для платформы x86 и x64. Тут принцип простой если вы подключаетесь к компьютеру с 32-х битной системой Windows, то используйте сервер UltraVNC (winvnc.exe) из папки x86, если вы подключаетесь к компьютеру с 64-х битной системой Windows, то используйте сервер UltraVNC (winvnc.exe) из папки x64. Теперь запустите у себя на компьютере файл winvnc.exe из папки x86 или х64 в зависимости от разрядности вышей Windows. В результате этого у вас откроется окно показанное на рисунке 1.

Рисунок 1. Настройка сервера UltraVNC

В этом окне необходимо выполнить два действия:

1) Установить разные пароли для режима управления и режима просмотра удаленного компьютера (Смотрите рисунок 1 цифра 1)
2) Установить опцию отключения значка в трее на панели задач рядом с часами (Смотрите рисунок 1 цифра 2)
Нажмите кнопку Apply и Ok для сохранения всех настроек сервера UltraVNC в файл UltraVNC.ini.

Так же скачайте утилиту PsExec с официального сайта Microsoft по этой ссылке. Или по прямой ссылке. Достаем из архива файл PsExec.exe сохраняем его в папку cmd2 на диске F или в другую любую папку на ваш выбор. За одно в папку cmd2 копируем файл winvnc.exe и файл UltraVNC.ini.  

Переходим к написанию batch файлов.  В папке cmd2 создайте файл uvnc.bat и файл uvnc_del.bat.

Важно! У вас должны быть права администратора на удаленном компьютере. Файлы uvnc.bat и uvnc_del.bat необходимо запускать в командной строке Windows. Синтаксис запуска скриптов следующий: 

 uvnc.bat pc01
 uvnc_del.bat pc01

pc01 - это имя удаленного компьютера, куда вы запускаете сервер UltraVNC.    

Содержимое файла uvnc.bat c комментариями:

@echo off
cls

net use O: /delete /y

if exist \\%1\C$\Temp\ (
   net use O: \\%1\C$\Temp
) else (
  net use O: \\%1\C$
  mkdir O:\Temp
  net use O: /delete /y
  net use O: \\%1\C$\Temp
)
mkdir O:\uvnc
copy "%~d0%~p0\winvnc.exe" "O:\uvnc" /y
copy "%~d0%~p0\UltraVNC.ini" "O:\uvnc" /y

psexec \\%1 net stop uvnc_service
psexec \\%1 "taskkill.exe" /f /im winvnc*

psexec \\%1 C:\Temp\uvnc\winvnc.exe -install

pause 

Комментарий по коду выше:
net use O: /delete /y (Удаляем сетевой диск O: если он существует)

if exist \\%1\C$\Temp\ (Этой строкой проверим существует ли на удаленном компьютере папка Temp в корне диска C, где %1 — автоматически подставится имя удаленного компьютера)
Если папка Temp существует, то строкой  net use O: \\%1\C$\Temp создаем сетевой диск O, который указывает на папку C:\Temp на удаленном компьютере.  
Если папка Temp не существует, то строкой  net use O: \\%1\C$ создаем сетевой диск O, который указывает в корень диска C на удаленном компьютере, строкой mkdir O:\Temp на сетевом диске O: создаем папку Temp, строкой net use O: /delete /y удаляем сетевой диск O:, строкой  net use O: \\%1\C$\Temp создаем сетевой диск O, который указывает на папку C:\Temp на удаленном компьютере.
Строкой  mkdir O:\uvnc создадим папку uvnc на сетевом диске O.

Строками
copy "%~d0%~p0\winvnc.exe" "O:\uvnc" /y
copy "%~d0%~p0\UltraVNC.ini" "O:\uvnc" /y      
скопируем из папки F:\cmd2 файл winvnc.exe и файл UltraVNC.ini в папку uvnc на сетевом диске O. (%~d0%~p0 — это строка означает путь откуда выполняется скрипт uvnc.bat, в частности это F:\cmd2)

Строками
psexec \\%1 net stop uvnc_service
psexec \\%1 "taskkill.exe" /f /im winvnc*

psexec \\%1 C:\Temp\uvnc\winvnc.exe -install

мы на удаленном компьютере останавливаем службу uvnc_service сервера UltraVNC (psexec \\%1 net stop uvnc_service), потом выгружаем на удаленном компьютере процессы из памяти с именем winvnc если такие имеют место быть (psexec \\%1 "taskkill.exe" /f /im winvnc*), потом устанавливаем на удаленном компьютере сервер UltraVNC в виде службы с именем uvnc_service (psexec \\%1 C:\Temp\uvnc\winvnc.exe -install).

Содержимое файла uvnc_del.bat c комментариями: 

@echo off
cls

psexec \\%1 net stop uvnc_service
psexec \\%1 "taskkill.exe" /f /im winvnc*

psexec \\%1 C:\Temp\uvnc\winvnc.exe -uninstall

del /q O:\uvnc\*
rd O:\uvnc

net use O: /delete /y
pause  

Строкой psexec \\%1 net stop uvnc_service мы на удаленном компьютере останавливаем службу uvnc_service сервера UltraVNC.
Строкой psexec \\%1 "taskkill.exe" /f /im winvnc* выгружаем на удаленном компьютере процессы из памяти с именем winvnc если такие есть.
Строкой psexec \\%1 C:\Temp\uvnc\winvnc.exe -uninstall удаляем на удаленном компьютере службу с именем uvnc_service

Строкой del /q O:\uvnc\* удаляем на удаленном компьютере все файлы в папке uvnc на сетевом диске O.
Строкой rd O:\uvnc удаляем на удаленном компьютере папку uvnc на сетевом диске O.
Строкой net use O: /delete /y удаляем сетевой диск O: если он существует.

Всё. Как только сервер UltraVNC заработает на удаленном компьютере, то вам останется запустить vncviewer.exe программу удаленный просмоторщик, ввести имя удаленного компьютера к которому мы хотим подключится, вводим пароль который мы установили при настройке сервера UltraVNC и нажимаем кнопку Connect (Смотрите рисунок 2).

Рисунок 2. Окно программы просмоторщика UltraVNC

В данном примере мы запустили сервер UltraVNC в режиме службы, я пытался запустить также сервер в режиме приложения, но данный режим по какой-то причине не работает, скорее всего не хватает прав, смотрите рисунок 3 как это выглядит при попытке подключения к удаленному компьютеру.
 
Рисунок 3. Просмоторщик UltraVNC запущенный в режиме приложения

понедельник, 7 октября 2024 г.

Проблемы подключения принтеров HP LaserJet P2014 и HP LaserJet P2015 в Windows 10 Pro 64 bit или 32 bit по USB

Сразу скажу, что принтера HP LaserJet P2014, HP LaserJet P2015 с Windows 10 Pro 64 bit или 32 bit дружат плохо (в частности пробовал заставить работать данный принтер на Windows 10 Pro 64 bit 20H2). У меня возникала проблема подключения принтера по USB кабелю. Даже при наличии в Windows предустановленных драйверов на принтер, он не желает устанавливаться ни автоматическом, ни в ручном режимах.

Симптомы проблемы следующие:

- в диспетчере устройств в разделе "Контроллеры USB устройств" вы видите устройство "Поддержка USB принтера", которое висит с восклицательным знаком. Если зайти в свойства этого устройства, то во вкладке общие в секции состояния устройства вы видите код ошибки 10 (Запуск это устройства прервано или остановлено).

Что пробовал делать:

- Переключение принтера в другие свободные USB порты на системном блоке проблему не решает

- Перезагрузка компьютера проблему не решает

- Выключение и включение принтера проблему не решает

Путем долгих часов поиска решения проблемы выяснилось, что для это принтера необходимо установить в Windows 10 Pro 64 bit программу (драйвер порта от HP) который называется Dot4x64.msi (Windows 10 Pro 64 bit) или Dot4x86.msi (Windows 10 Pro 32 bit).

На сайте HP на странице скачивания драйверов к принтеру HP LaserJet 1320 для Windows 10 можно скачать файл (Dot4x86.msi) (Windows 10 Pro 32 bit) и (Dot4x64.msi) (Windows 10 Pro 64 bit). Внимание! Обязательно проверяйте скаченные файлы антивирусом.

Данные принтеры (HP LaserJet P2014, HP LaserJet P2015) в Windows 10 Pro 64 bit после отключения системного блока или перезагрузке самопроизвольно создают порты DOT4USB и создают новый логический принтер с новым именем (добавляется в конце имени Копия 1,2,3..N). Так же наблюдается периодическое отвал этих моделей принтеров от USB разъёма компьютера, что требуется переключение их в другой свободный USB порт, после этого данные модели принтеров будут работать до следующего отвала от USB. Данная проблема наблюдается в Windows 10 Pro 64 bit, замечу что в Windows 7 Pro 32 bit такой проблемы нет, в Winndows 7 данные модели принтеров работают отлично.

пятница, 14 июня 2024 г.

Включение поддержки установки 64 битной гостевой операционной системы в программе Oracle VirtualBox 6.1.32

1. На вашем компьютере должен быть установлен 64-х битный процессор и установлена 64-х битная операционная система Windows 10

2. Необходимо убедится, что ваш процессор поддерживает технологию аппаратной виртуализации. Посмотрите на сайте Intel или AMD по характеристикам вашего процессора есть ли поддержка виртуализации.

3. Включить поддержку аппаратной виртуализации в BIOS вашего компьютера.

4. После включения поддержки аппаратной виртуализации в BIOS необходимо выключить компьютер и опять включить, если вы его просто перезагрузите, то аппаратная виртуализация не заработает.

5. Проверить работает ли поддержка 64 битной гостевой операционной системы в программе Oracle VirtualBox 6.1.32 (смотрите рисунок 1)

Рисунок 1. Окно создания виртуальной машины

воскресенье, 12 сентября 2021 г.

Печать выделенного фрагмента из PDF документа в Adobe Acrobat Reader DC

Если вам необходимо напечатать выделенный фрагмент PDF документа, то вам нужно открыть PDF документ в программе Adobe Acrobat Reader DC, выбрать пункт меню «Редактирование» (смотрите рисунок 1), выбрать подпункт «Сделать снимок», потом выделить на нужной странице фрагмент в PDF документе.

Рисунок 1. Создание снимка выделенного PDF фрагмента

Теперь можно заходить в окно печати, для этого выберите пункт меню «Файл», потом подпункт “Печать…” или нажмите сочетание клавиш Ctrl+P, и вы увидите подготовленный выделенный PDF фрагмент для печати. В разделе «Настройка размера и обработка страниц» установите опцию «Подогнать» для того чтобы выделенный PDF фрагмент занимал всю печатающуюся область.