Я предпочитаю создавать NSIS как консольную программу для этой цели, однако можно разрешить программе GUI писать в существующее окно консоли. Недостаток этого метода заключается в том, что курсор ввода не перемещается вместе с выводом, поэтому пользователь, вероятно, захочет ввести cls после завершения установки, и вам придется уведомить их об этом факте. Для дополнительной поддержки я также добавил функцию DetectConsole для автоматического определения, был ли NSIS вызван из командной строки, но вам нужно будет включить этот заголовок для GetProcessInfo: https://nsis.sourceforge.io/Get_process_info
Но в любом случае это возможно с чем-то вроде ниже. Вы можете обернуть ваши DetailPrint в макрос, который также выполняет StdOutPrint, и использовать nsExe c :: ExecToStack: https://nsis.sourceforge.io/NsExec_plug-in и StdOutPrint содержимое стека (хотя вы, вероятно, захотите использовать NSIS long строки строк для получения более подробного вывода).
Если вы хотите использовать параметр / S для открытия нового командного окна при необходимости, даже если оно не вызывается из командной строки (шумная пауза), раскомментируйте 4 строки с "; $ {OrIf} $ {Silent}" и "; SetSilent silent"
!include LogicLib.nsh
!include GetProcessInfo.nsh
Var /GLOBAL StdOutHandle
Var /GLOBAL CommandLine
Function ${UN}AttachConsole # Reuse or create a command prompt window if command line install
Push $0
Push $1
StrCpy $StdOutHandle ""
${If} $CommandLine == "yes"
;${OrIf} ${Silent}
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
System::Call 'kernel32::AttachConsole(i -1)i.r1'
${If} $0 = 0
${OrIf} $1 = 0
System::Call 'kernel32::AllocConsole()'
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
StrCpy $StdOutHandle $0
FileWrite $StdOutHandle "\r\n"
${EndIf}
${EndIf}
Pop $1
Pop $0
FunctionEnd
!macro StdOutPrint OutputText
${If} $CommandLine == "yes"
;${OrIf} ${Silent}
FileWrite $StdOutHandle `${OutputText} \r\n`
${EndIf}
!macroend
!define StdOutPrint '!insertmacro StdOutPrint'
Function ${UN}DetectConsole # Check if run from a command line (including some known cmd.exe replacements)
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
${GetProcessInfo} 0 $0 $1 $2 $3 $4 # $0=pid $1=parent_pid $2=priority $3=name $4=fullname
${GetProcessInfo} $1 $0 $1 $2 $3 $5
${If} $3 == "wsmprovhost.exe" # Remote PowerShell [stdout OK, but no stdin]
${OrIf} $3 == "powershell.exe" # Local PowerShell
${OrIf} $3 == "cmd.exe" # Command Prompt
${OrIf} $3 == "tcc.exe" # Take Command
${OrIf} $3 == "4nt.exe" # 4NT
${OrIf} $3 == "console2.exe" # Console2
${OrIf} $3 == "conemu.exe" # ConEmu
${OrIf} $3 == "conemu64.exe" # ConEmu x64
${OrIf} $3 == "clink_x86.exe" # clink
${OrIf} $3 == "clink_x64.exe" # clink x64
${OrIf} $3 == "FireCMD.exe" # FireCMD
${OrIf} $3 == "far.exe" # Far Manager
${OrIf} $3 == "mintty.exe" # Cygwin/Git
${OrIf} $3 == "Cmder.exe" # Cmder
${OrIf} $3 == "PowerCmd.exe" # PowerCmd
;SetSilent silent
StrCpy $CommandLine "yes"
${EndIf}
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
Function .onInit
Call DetectConsole
${If} $CommandLine == "yes"
;${OrIf} ${Silent}
Call AttachConsole
${StdOutPrint} "Hello, world!"
${EndIf}
FunctionEnd