1

Тема: VBScript: вывод текста на консоль с помощью DynamicWrapper

Пример демонстрирует вывод текста на консоль с помощью DynamicWrapper. Вывод осуществляется независимо от того, запущен ли скрипт с помощью cscript, wscript или даже из-под текстового редактора с перенаправлением вывода (например, SciTE),  т.е. вывод направляется в stdout (если он есть) и нормально перехватывается и перенаправляется. Практическую ценность этого примера оценить трудно, однако пример демонстрирует интересную работу с некоторыми функциями Win32 API.

Text="Hello, world! Это я. Как дела?"

CharsWritten=CLng(0)
Const STD_OUTPUT_HANDLE = -11

Set Wrap=CreateObject("DynamicWrapper")

Wrap.Register "msvcrt.dll",   "strncpy",             "i=wwl",      "f=c", "r=l"
Wrap.Register "msvcrt.dll",   "memcpy",              "i=lll",      "f=c", "r=l"
Wrap.Register "kernel32.dll", "GetConsoleWindow",                  "f=s", "r=l"
Wrap.Register "kernel32.dll", "AllocConsole",                      "f=s", "r=l"
Wrap.Register "kernel32.dll", "FreeConsole",                       "f=s", "r=l"
Wrap.Register "kernel32.dll", "WriteFile",        "i=lllll",    "f=s", "r=l"
Wrap.Register "kernel32.dll", "GetStdHandle",        "i=l",        "f=s", "r=l"
Wrap.Register "kernel32.dll", "GetConsoleOutputCP",                "f=s", "r=l"
Wrap.Register "kernel32.dll", "WideCharToMultiByte", "i=llllllll", "f=s", "r=l"
Wrap.Register "user32.dll",   "SetForegroundWindow", "i=l",        "f=s", "r=l"

ConHwnd=Wrap.GetConsoleWindow()
If ConHwnd = 0 Then
  Wrap.AllocConsole()
  ConHwnd=Wrap.GetConsoleWindow()
End If
Wrap.SetForegroundWindow ConHwnd

OutCP=Wrap.GetConsoleOutputCP()
Text=Text & vbcrlf & "Кодовая страница вывода: " & OutCP & vbcrlf
StdOut=Wrap.GetStdHandle(STD_OUTPUT_HANDLE)
Wrap.WriteFile StdOut, UniToAnsi(Text, OutCP), Len(Text), CLngPtr(CharsWritten), 0
WScript.Sleep 3000
'Wrap.FreeConsole()

WScript.Echo "Записано символов: " & CharsWritten


'====================== Вспомогательные функции =====================

Function CLngPtr(v)                ' Возвращает указатель на число.
  CLngPtr=Wrap.strncpy(v, v, 1)+8
End Function

Function CStrPtr(v)                ' Возвращает указатель на строку.
  d=CLng(0)
  pv=Wrap.strncpy(v, v, 1)
  pd=Wrap.strncpy(d, d, 1)
  Wrap.memcpy pd+8, pv+8, 8
  CStrPtr=d
End Function

Function UniToAnsi(w, cp)          ' Конвертирует из Unicode в ANSI.
  s=Space(Len(w))                  ' Возвращает указатель на строку.
  ps=CStrPtr(s)
  pw=CStrPtr(w)
  Wrap.WideCharToMultiByte cp, 0, pw, Len(w), ps, Len(w), 0, 0
  UniToAnsi=ps
End Function

Автор примера - YMP.

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

2

Re: VBScript: вывод текста на консоль с помощью DynamicWrapper

Пример, аналогичный предыдущему, но работает немного по-другому. Открывает окно консоли и выводит текст в него, независимо от того, запущен ли скрипт с помощью cscript, wscript или даже из-под текстового редактора с неявным перенаправлением вывода (например, SciTE), или даже с помощью cscript с явным перенаправлением вывода в файл.

Text="Hello, world! Это я. Как дела?"

CharsWritten=CLng(0)
Const STD_OUTPUT_HANDLE = -11

Const GENERIC_READ          = &H80000000
Const GENERIC_WRITE         = &H40000000
Const FILE_SHARE_READ       = &H00000001
Const FILE_SHARE_WRITE      = &H00000002
Const OPEN_EXISTING         = &H00000003
Const FILE_ATTRIBUTE_NORMAL = &H00000080
Const SW_SHOWNOACTIVATE     = &H00000004
Const SW_SHOW               = &H00000005
Const SW_SHOWDEFAULT        = &H0000000A
Const SW_HIDE               = &H00000000
Const SW_SHOWNORMAL         = &H00000001

Set Wrap=CreateObject("DynamicWrapper")

Wrap.Register "msvcrt.dll",   "strncpy",             "i=wwl",      "f=c", "r=l"
Wrap.Register "msvcrt.dll",   "memcpy",              "i=lll",      "f=c", "r=l"
Wrap.Register "kernel32.dll", "GetConsoleWindow",                  "f=s", "r=l"
Wrap.Register "kernel32.dll", "AllocConsole",                      "f=s", "r=l"
Wrap.Register "kernel32.dll", "FreeConsole",                       "f=s", "r=l"
Wrap.Register "kernel32.dll", "WriteConsole",        "i=lllll",    "f=s", "r=l"
Wrap.Register "kernel32.dll", "WriteFile",           "i=lllll",    "f=s", "r=l"
Wrap.Register "kernel32.dll", "GetStdHandle",        "i=l",        "f=s", "r=l"
Wrap.Register "kernel32.dll", "GetConsoleOutputCP",                "f=s", "r=l"
Wrap.Register "kernel32.dll", "WideCharToMultiByte", "i=llllllll", "f=s", "r=l"
Wrap.Register "user32.dll",   "SetForegroundWindow", "i=l",        "f=s", "r=l"
Wrap.Register "kernel32.dll", "CreateFile",          "i=sllllll",  "f=s", "r=l"
Wrap.Register "kernel32.dll", "CloseHandle",         "i=l",        "f=s", "r=l"
Wrap.Register "user32.dll",   "ShowWindow",          "i=ll",       "f=s", "r=l"

ConHwnd=Wrap.GetConsoleWindow()
If ConHwnd = 0 Then
  'Wrap.FreeConsole()
  Wrap.AllocConsole()
  ConHwnd=Wrap.GetConsoleWindow()
End If

Wrap.ShowWindow ConHwnd, SW_SHOWNOACTIVATE
Wrap.SetForegroundWindow ConHwnd

OutCP=Wrap.GetConsoleOutputCP()
Text=Text & vbcrlf & "Кодовая страница вывода: " & OutCP & vbcrlf

'StdOut=Wrap.GetStdHandle(STD_OUTPUT_HANDLE)
StdOut = Wrap.CreateFile("CONOUT$", GENERIC_READ Or GENERIC_WRITE, _
    FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
    
Wrap.WriteFile StdOut, UniToAnsi(Text, OutCP), Len(Text), CLngPtr(CharsWritten), 0

Wrap.CloseHandle StdOut
'Wrap.FreeConsole()

WScript.Echo "Записано символов: " & CharsWritten
do
    WScript.Sleep 10000
loop


'====================== Вспомогательные функции =====================

Function CLngPtr(v)                ' Возвращает указатель на число.
  CLngPtr=Wrap.strncpy(v, v, 1)+8
End Function

Function CStrPtr(v)                ' Возвращает указатель на строку.
  d=CLng(0)
  pv=Wrap.strncpy(v, v, 1)
  pd=Wrap.strncpy(d, d, 1)
  Wrap.memcpy pd+8, pv+8, 8
  CStrPtr=d
End Function

Function UniToAnsi(w, cp)          ' Конвертирует из Unicode в ANSI.
  s=Space(Len(w))                  ' Возвращает указатель на строку.
  ps=CStrPtr(s)
  pw=CStrPtr(w)
  Wrap.WideCharToMultiByte cp, 0, pw, Len(w), ps, Len(w), 0, 0
  UniToAnsi=ps
End Function

Автор примера - alexii.

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

3

Re: VBScript: вывод текста на консоль с помощью DynamicWrapper

Командный процессор на VBS . Понимает 2 команды (Help и Exit), а также правильно реагирует на неизвестные.

Welcome="Command processor Валенок [Версия 0.0.0.1]" & vbcrlf &_
"(C) Корпорация Script-coding.com & Co, 2008-2100" & vbcrlf & vbcrlf &_
"Для вывода справки наберите ""Help"", для выхода наберите ""Exit""." &  vbcrlf &_
"Также можно набрать любую фигню. Регистр роли не играет." &  vbcrlf

Const STD_INPUT_HANDLE  = -10
Const STD_OUTPUT_HANDLE = -11
InBufSize=255
Prompt="Вводи!>"

Set Wrap=CreateObject("DynamicWrapper")
RegisterMethods                          ' Вынес всю портянку в Sub ниже.

ConHwnd=Wrap.GetConsoleWindow()
If ConHwnd = 0 Then
  Wrap.AllocConsole()
  ConHwnd=Wrap.GetConsoleWindow()
End If
Wrap.SetForegroundWindow ConHwnd

StdIn =Wrap.GetStdHandle(STD_INPUT_HANDLE)
StdOut=Wrap.GetStdHandle(STD_OUTPUT_HANDLE)

ConWrite Welcome

Do While True                ' Цикл обработки вводимых команд.
  ConWrite vbcrlf & Prompt
  Cmd=ConRead()
  If LCase(Cmd) = "help" Then
    ConWrite "Помоги себе сам!" & vbcrlf
  ElseIf LCase(Cmd) = "exit" Then
    WScript.Quit
  ElseIf Cmd = "" Then
    ConWrite "Ничего не введено." & vbcrlf
  Else
    ConWrite "Неопознанная фигня: " & Cmd & vbcrlf 
  End If
Loop


'====================== Вспомогательные функции =====================

Sub RegisterMethods()
  Wrap.Register "msvcrt.dll",   "strncpy",             "i=wwl",      "f=c", "r=l"
  Wrap.Register "msvcrt.dll",   "strlen",              "i=l",        "f=c", "r=l"
  Wrap.Register "msvcrt.dll",   "memcpy",              "i=lll",      "f=c", "r=l"
  Wrap.Register "kernel32.dll", "GetConsoleWindow",                  "f=s", "r=l"
  Wrap.Register "kernel32.dll", "AllocConsole",                      "f=s", "r=l"
  Wrap.Register "kernel32.dll", "FreeConsole",                       "f=s", "r=l"
  Wrap.Register "kernel32.dll", "WriteFile",           "i=lllll",    "f=s", "r=l"
  Wrap.Register "kernel32.dll", "ReadFile",            "i=lllll",    "f=s", "r=l"
  Wrap.Register "kernel32.dll", "GetStdHandle",        "i=l",        "f=s", "r=l"
  Wrap.Register "kernel32.dll", "GetConsoleCP",                      "f=s", "r=l"
  Wrap.Register "kernel32.dll", "GetConsoleOutputCP",                "f=s", "r=l"
  Wrap.Register "kernel32.dll", "WideCharToMultiByte", "i=llllllll", "f=s", "r=l"
  Wrap.Register "kernel32.dll", "MultiByteToWideChar", "i=llllll",   "f=s", "r=l"
  Wrap.Register "user32.dll",   "SetForegroundWindow", "i=l",        "f=s", "r=l"
  Wrap.Register "ntdll.dll",    "RtlZeroMemory",       "i=ll",       "f=s", "r=l"
End Sub

Function ConRead()                  ' Читает ввод.
  InBuf=Space(InBufSize/2)
  CharsRead=0
  InCP=Wrap.GetConsoleCP()
  Wrap.RtlZeroMemory CStrPtr(InBuf), InBufSize
  Wrap.ReadFile StdIn, CStrPtr(InBuf), InBufSize, CLngPtr(CharsRead), 0
  If CharsRead <= 2 Then
    ConRead = ""
  End If
  ConRead = Left(AnsiToUni(InBuf, InCP), CharsRead-2) ' Отрезаются CR и LF.
End Function

Function ConWrite(Text)            ' Пишет в вывод.
  CharsWritten=0
  OutCP=Wrap.GetConsoleOutputCP()
  Wrap.WriteFile StdOut, UniToAnsi(Text, OutCP), Len(Text), CLngPtr(CharsWritten), 0
  ConWrite=CharsWritten
End Function

Function CLngPtr(v)                ' Возвращает указатель на число.
  CLngPtr=Wrap.strncpy(v, v, 1)+8
End Function

Function CStrPtr(v)                ' Возвращает указатель на строку.
  d=CLng(0)
  pv=Wrap.strncpy(v, v, 1)
  pd=Wrap.strncpy(d, d, 1)
  Wrap.memcpy pd+8, pv+8, 8
  CStrPtr=d
End Function

Function UniToAnsi(w, cp)          ' Конвертирует из Unicode в ANSI.
  s=Space(Len(w))                  ' Возвращает указатель на строку.
  ps=CStrPtr(s)
  pw=CStrPtr(w)
  Wrap.WideCharToMultiByte cp, 0, pw, Len(w), ps, Len(w), 0, 0
  UniToAnsi=ps
End Function

Function AnsiToUni(s, cp)          ' Конвертирует из ANSI в Unicode.
  ps=CStrPtr(s)                    ' Возвращает строковую переменную VBS.
  slen=Wrap.strlen(ps)
  w=Space(slen)
  pw=CStrPtr(w)
  Wrap.MultiByteToWideChar cp, 0, ps, slen, pw, slen
  AnsiToUni=w
End Function

Автор примера - YMP.

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