<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Библиотека для консольных приложений]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=16646</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=16646&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Библиотека для консольных приложений».]]></description>
		<lastBuildDate>Fri, 08 Oct 2021 20:56:23 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK: Библиотека для консольных приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=149971#p149971</link>
			<description><![CDATA[<p><strong>teadrinker</strong>, запомню :-)</p>]]></description>
			<author><![CDATA[null@example.com (streleck1y)]]></author>
			<pubDate>Fri, 08 Oct 2021 20:56:23 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=149971#p149971</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Библиотека для консольных приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=149961#p149961</link>
			<description><![CDATA[<p>Спасибо! Но уже вижу явные ошибки:<br /></p><div class="codebox"><pre><code>    DllCall(&quot;ntdll.dll\RtlFillMemoryUlong&quot;, &quot;UInt&quot;, &amp;PE32, &quot;UInt&quot;, 4, &quot;UInt&quot;, 304)  ; Set dwSize
    VarSetCapacity(th32ProcessID, 4, 0)
    if (DllCall(&quot;Process32First&quot;, &quot;UInt&quot;, hSnapshot, &quot;UInt&quot;, &amp;PE32))</code></pre></div><p>Хэндлы и адреса имеют тип Ptr, а не UInt.</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Fri, 08 Oct 2021 15:03:35 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=149961#p149961</guid>
		</item>
		<item>
			<title><![CDATA[AHK: Библиотека для консольных приложений]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=149960#p149960</link>
			<description><![CDATA[<p>Здравствуйте форумчане, решил поделиться с Вами своей библиотекой для консольных приложений на <strong>AutoHotKey</strong>, которую я использую в своих программах. Думаю, будет полезным для всех. Знаю, что когда-то была такая же библиотека на иностранных форумах, но она не работает в Windows 10 и выше.</p><p><strong>Возможности</strong>, которые откроются с этой библиотекой:<br /></p><ul><li><p>автоматическое подключение к хосту окна консоли, откуда был вызван скрипт;</p></li></ul><ul><li><p>принятие ввода текста от пользователя;</p></li></ul><ul><li><p>вывод текста в консоль;</p></li></ul><ul><li><p>автоматическое изменение кодовой страницы для ввода/вывода на 1251 (во-избежание &quot;крякозябр&quot;);</p></li></ul><p>Имеется большой <strong>минус</strong>, связанный с подключением скрипта к консоли. Заключается он в том, что скрипты AutoHotKey подразумеваются системой как не консольные, следовательно если просто подключиться к консоли, то вводы/выводы будут путаться, и решением этой проблемы в этой библиотеке является <strong>замораживание</strong> процесса. Это стабильно работает, но если скрипт вызван из стандартной командной строки. Но в случае PowerShell было замечено, что ввод новых команд не является возможным, однако вывод работает отлично. Если Вы знаете метод, с помощью которого можно обойтись без замораживания, то буду рад, посмотреть Ваше решение в этом обсуждении.</p><p>Сама библиотека, с примером в конце:<br /></p><div class="codebox"><pre><code>global attached, hStdIn, hStdOut
OnExit(&quot;ExitConsole&quot;) ; нужно разморозить предыдущий процесс

; Переменная &quot;attached&quot; содержит либо &quot;0&quot; (ноль), либо &quot;1&quot; (единицу). Если равно 0, то консоль создана в новом окне; если равно, то консоль подключилась к другой.

class console {
	init() {
		console.create()
		DllCall(&quot;SetConsoleOutputCP&quot;, &quot;int&quot;, 1251)
		DllCall(&quot;SetConsoleCP&quot;, &quot;int&quot;, 1251)
	}
	
	flushBuffer() {
		hStdout.Read(0)
	}
	
	create() {
		attached = 1
		
		if (DllCall(&quot;AttachConsole&quot;, &quot;uInt&quot;, Process_GetCurrentParentProcessID(), &quot;Cdecl int&quot;) != 1) {
			DllCall(&quot;AllocConsole&quot;)
			attached = 0
		}
		
		hStdIn := FileOpen(DllCall(&quot;GetStdHandle&quot;, &quot;int&quot;, -10, &quot;ptr&quot;), &quot;h `n&quot;)
		hStdOut := FileOpen(DllCall(&quot;GetStdHandle&quot;, &quot;int&quot;, -11, &quot;ptr&quot;), &quot;h `n&quot;)
		
		if (attached) {
			console.writeln(&quot;&quot;) ; отступ одной строки от вывода прошлого процесса
			Process_Suspend(Process_GetCurrentParentProcessID()) ; замораживание процесса, из которого был вызван скрипт
			ControlSend,, {enter}, % &quot;ahk_pid &quot; Process_GetCurrentParentProcessID() ; пропускаем ввод прошлого процесса
		}
	}
	
	read() {
		result := RTrim(hStdIn.ReadLine(), &quot;`n&quot;)
		console.flushBuffer()
		return result
	}
	
	write(text) {
		result := hStdOut.write(text)
		console.flushBuffer()
		return result
	}
	
	writeln(text) {
		result := hStdOut.WriteLine(text)
		console.flushBuffer()
		return result
	}
}

Process_GetCurrentProcessID(){
  Return DllCall(&quot;GetCurrentProcessId&quot;) 
}

Process_GetCurrentParentProcessID(){
  Return Process_GetParentProcessID(Process_GetCurrentProcessID())
}

Process_GetProcessName(ProcessID){
  Return Process_GetProcessInformation(ProcessID, &quot;Str&quot;, 260, 36)  ; TCHAR szExeFile[MAX_PATH]
}

Process_GetParentProcessID(ProcessID){
  Return Process_GetProcessInformation(ProcessID, &quot;UInt *&quot;, 4, 24)  ; DWORD th32ParentProcessID
}

Process_GetProcessThreadCount(ProcessID){
  Return Process_GetProcessInformation(ProcessID, &quot;UInt *&quot;, 4, 20)  ; DWORD cntThreads
}

Process_GetProcessInformation(ProcessID, CallVariableType, VariableCapacity, DataOffset){
  hSnapshot := DLLCall(&quot;CreateToolhelp32Snapshot&quot;, &quot;UInt&quot;, 2, &quot;UInt&quot;, 0)  ; TH32CS_SNAPPROCESS = 2
  if (hSnapshot &gt;= 0)
  {
    VarSetCapacity(PE32, 304, 0)  ; PROCESSENTRY32 structure
    DllCall(&quot;ntdll.dll\RtlFillMemoryUlong&quot;, &quot;UInt&quot;, &amp;PE32, &quot;UInt&quot;, 4, &quot;UInt&quot;, 304)  ; Set dwSize
    VarSetCapacity(th32ProcessID, 4, 0)
    if (DllCall(&quot;Process32First&quot;, &quot;UInt&quot;, hSnapshot, &quot;UInt&quot;, &amp;PE32)) 
      Loop
      {
        DllCall(&quot;RtlMoveMemory&quot;, &quot;UInt *&quot;, th32ProcessID, &quot;UInt&quot;, &amp;PE32 + 8, &quot;UInt&quot;, 4)
        if (ProcessID = th32ProcessID)
        {
          VarSetCapacity(th32DataEntry, VariableCapacity, 0)
          DllCall(&quot;RtlMoveMemory&quot;, CallVariableType, th32DataEntry, &quot;UInt&quot;, &amp;PE32 + DataOffset, &quot;UInt&quot;, VariableCapacity)
          DllCall(&quot;CloseHandle&quot;, &quot;UInt&quot;, hSnapshot)
          Return th32DataEntry  ; Process data found
        }
        if not DllCall(&quot;Process32Next&quot;, &quot;UInt&quot;, hSnapshot, &quot;UInt&quot;, &amp;PE32)
          Break
      }
    DllCall(&quot;CloseHandle&quot;, &quot;UInt&quot;, hSnapshot)
  }
  Return  ; Cannot find process
}

Process_GetModuleFileNameEx(ProcessID)  ; modified version of shimanov&#039;s function
{
  if A_OSVersion in WIN_95, WIN_98, WIN_ME
    Return Process_GetProcessName(ProcessID)
  
  ; #define PROCESS_VM_READ           (0x0010)
  ; #define PROCESS_QUERY_INFORMATION (0x0400)
  hProcess := DllCall( &quot;OpenProcess&quot;, &quot;UInt&quot;, 0x10|0x400, &quot;Int&quot;, False, &quot;UInt&quot;, ProcessID)
  if (ErrorLevel or hProcess = 0)
    Return
  FileNameSize := 260
  VarSetCapacity(ModuleFileName, FileNameSize, 0)
  CallResult := DllCall(&quot;Psapi.dll\GetModuleFileNameExA&quot;, &quot;UInt&quot;, hProcess, &quot;UInt&quot;, 0, &quot;Str&quot;, ModuleFileName, &quot;UInt&quot;, FileNameSize)
  DllCall(&quot;CloseHandle&quot;, hProcess)
  Return ModuleFileName
}

Process_Suspend(PID_or_Name){
    PID := (InStr(PID_or_Name,&quot;.&quot;)) ? ProcExist(PID_or_Name) : PID_or_Name
    h:=DllCall(&quot;OpenProcess&quot;, &quot;uInt&quot;, 0x1F0FFF, &quot;Int&quot;, 0, &quot;Int&quot;, pid)

    If !h   
        Return -1

    DllCall(&quot;ntdll.dll\NtSuspendProcess&quot;, &quot;Int&quot;, h)
    DllCall(&quot;CloseHandle&quot;, &quot;Int&quot;, h)
}

Process_Resume(PID_or_Name){
    PID := (InStr(PID_or_Name,&quot;.&quot;)) ? ProcExist(PID_or_Name) : PID_or_Name
    h:=DllCall(&quot;OpenProcess&quot;, &quot;uInt&quot;, 0x1F0FFF, &quot;Int&quot;, 0, &quot;Int&quot;, pid)

    If !h
        Return -1
	
    DllCall(&quot;ntdll.dll\NtResumeProcess&quot;, &quot;Int&quot;, h)
    DllCall(&quot;CloseHandle&quot;, &quot;Int&quot;, h)
}

ProcExist(PID_or_Name=&quot;&quot;){
    Process, Exist, % (PID_or_Name=&quot;&quot;) ? DllCall(&quot;GetCurrentProcessID&quot;) : PID_or_Name
    Return Errorlevel
}

ExitConsole() {
	console.writeln(&quot;&quot;) ; отступ в одну строку после вывода программы
	Process_Resume(Process_GetCurrentParentProcessID()) ; размораживание процесса, из которого был вызван скрипт
}

; Инициализация консоли
console.init()

; Пробуем написать в нее что-либо:
console.writeln(&quot;Привет, Мир!&quot;)
console.write(&quot;Введите Ваше имя: &quot;)
name := console.read() ; получаем текст, который ввел пользователь и записываем его в переменную name.
console.writeln(&quot;Рад познакомиться, &quot; name &quot;!&quot;)
runwait, %ComSpec% /c pause ; замена getch</code></pre></div><p>Если нужно изменить заголовок окна консоли, то можно воспользоваться DllCall (пример ниже работает, если Ваша версия AHK является 32-разрядной).<br /></p><div class="codebox"><pre><code>DllCall(&quot;SetConsoleTitleW&quot;, &quot;str&quot;, &quot;заголовок&quot;)</code></pre></div><p>Также стоит учесть, что вывод всех консольных приложений также будет в этой консоли. Рекомендуется их вызывать через <strong>RunWait</strong>, так как потоки вывода/ввода будут путаться. Пример ниже.<br /></p><div class="codebox"><pre><code>RunWait, cmd.exe</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (streleck1y)]]></author>
			<pubDate>Fri, 08 Oct 2021 14:56:41 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=149960#p149960</guid>
		</item>
	</channel>
</rss>
