I need to run a powershell script in cmd using qt qprocess.
my final command should be powershell -ExecutionPolicy Unrestricted -File D:/
here D:/ is argument to script.
I am trying to execute this by Qprocess:startDetached but its not working.
enter code here
bool ConfigScriptExecutor::StartScriptFile(const std::string& script, const std::string& scriptArgs)
{
qint64 pid = 0;
QString processName = "cmd.exe";
QStringList arguments;
std::string Powershell_unrestriced_command = "powershell -ExecutionPolicy Unrestricted -File ";
arguments << Powershell_unrestriced_command.c_str();
arguments << fs::system_complete(script).string().c_str();
if (!scriptArgs.empty())
{
arguments << scriptArgs.c_str();
}
QString workingDir(FileSystemHelper::ApplicationPath().c_str());
Debug::Output(make_string() << "Executing process: " << processName.toStdString()
<< " " << arguments[0].toStdString()
<< " workingDir: " << workingDir.toStdString());
bool success = QProcess::startDetached(processName, arguments, workingDir, &pid);
return (success && pid != 0);
}
Related
Using jScript to run a command line remotely. The first three commands work fine. It is not until i get to the dot command after I have opened the sqlite3 data base that it just stops executing. When I run .quit I either get
sqlite> .quit
The filename, directory name, or volume label syntax is incorrect.
or ".import" is not recognized as an internal or external command.
try {
// var ret = oShell.Run('cmd.exe cd c:\\sqlite', 1 /* SW_SHOWNORMAL */, true /* bWaitOnReturn */);
var oShell = WScript.CreateObject("WScript.Shell");
// var ret = oShell.Run("cmd.exe /k #echo Hello", 1 /* SW_SHOWNORMAL */, true/* bWaitOnReturn */);
var ret = oShell.Run('cmd.exe /k cd c:\\sqlite && #echo ".import H:\\\\2019\\\\00028-000-19\\\\QPPData\\\\Directory_Proofs\\\\Index_007.txt test" && sqlite3 F:\\qpp.db; && ".import H:\\\\2019\\\\00028-000-19\\\\QPPData\\\\Directory_Proofs\\\\Index_007.txt test"', 1 /* SW_SHOWNORMAL */, true/* bWaitOnReturn */);
WScript.Echo("ret " + ret);
//var ret = oShell.Run('cmd cd', 1 /* SW_SHOWNORMAL */, true /* bWaitOnReturn */);
}
catch (err) {
WScript.Echo(err);
}
I am trying to change the Windows Console Mode for output (CONOUT$) using the Windows API and SetConsoleMode calls. So I modified a PowerShell script, based on ConinMode.ps1 (and which works for input), to do this. Reading works fine with both the ConoutMode.exe and my script, and returns:
# .\ConoutMode.exe
mode: 0x3
ENABLE_PROCESSED_OUTPUT 0x0001 ON
ENABLE_WRAP_AT_EOL_OUTPUT 0x0002 ON
ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 off <====
DISABLE_NEWLINE_AUTO_RETURN 0x0008 off
ENABLE_LVB_GRID_WORLDWIDE 0x0010 off
# .\ConoutMode.ps1
OK! GetConsoleWindow handle : 0x1F06D6
Console Input Mode (CONIN) : 0x21f
Console Output Mode (CONOUT) : 0x3
However, both my script and the exe fails in writing the mode. (Possibly because it thinks that my output handle is not pointing to a console?)
In PowerShell:
# .\ConoutMode.exe set 0x000f
error: SetConsoleMode failed (is stdout a console?)
# .\ConoutMode.ps1 -Mode 7
OK! GetConsoleWindow handle : 0x1F06D6
old (out) mode: 0x3
SetConsoleMode (out) failed (is stdout a console?)
At C:\cygwin64\home\emix\win_esc_test\ConoutMode.ps1:112 char:9
+ throw "SetConsoleMode (out) failed (is stdout a console?)"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (SetConsoleMode ...out a console?):String) [], RuntimeException
+ FullyQualifiedErrorId : SetConsoleMode (out) failed (is stdout a console?)
Here is my ConoutMode.ps1 script in it's entirety:
param (
[int] $Mode
)
$signature = #'
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
public const int STD_INPUT_HANDLE = -10;
public const int STD_OUTPUT_HANDLE = -11;
public const int ENABLE_PROCESSED_OUTPUT = 0x0001;
public const int ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002;
public const int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
public const int DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
public const int ENABLE_LVB_GRID_WORLDWIDE = 0x0010;
'#
#----------------------------------------------------------
$WinAPI = Add-Type -MemberDefinition $signature -Name WinAPI -Namespace ConoutMode -PassThru
#$WinAPI = Add-Type -MemberDefinition $signature -Name WinAPI -Namespace IdentifyConsoleWindow -PassThru
$hwnd = $WinAPI::GetConsoleWindow()
if ($hwnd -eq 0) {
throw "Error: GetConsoleWindow returned NULL."
}
echo "OK! GetConsoleWindow handle : 0x$($hwnd.ToString("X"))"
function GetConIn {
$ret = $WinAPI::GetStdHandle($WinAPI::STD_INPUT_HANDLE)
if ($ret -eq -1) {
throw "Error: cannot get stdin handle"
}
return $ret
}
function GetConOut {
$ret = $WinAPI::GetStdHandle($WinAPI::STD_OUTPUT_HANDLE)
if ($ret -eq -1) {
throw "Error: cannot get stdout handle"
}
return $ret
}
function GetConInMode { #GetCOnsoleMode
$conin = GetConIn
$mode = 0
$ret = $WinAPI::GetConsoleMode($conin, [ref]$mode)
if ($ret -eq 0) {
throw "GetConsoleMode (in) failed (is stdin a console?)"
}
return $mode
}
function GetConOutMode {
$conout = GetConOut
$mode = 0
$ret = $WinAPI::GetConsoleMode($conout, [ref]$mode)
if ($ret -eq 0) {
throw "GetConsoleMode (out) failed (is stdout a console?)"
}
return $mode
}
function SetConInMode($mode) {
$conin = GetConIn
$ret = $WinAPI::SetConsoleMode($conin, $mode)
if ($ret -eq 0) {
throw "SetConsoleMode (in) failed (is stdin a console?)"
}
}
function SetConOutMode($mode) {
#$conout = GetConOut
# Different tack:
$conout = $hwnd
$ret = $WinAPI::SetConsoleMode($conout, $mode)
if ($ret -eq 0) {
throw "SetConsoleMode (out) failed (is stdout a console?)"
}
}
#----------------------------------------------------------
# MAIN
#----------------------------------------------------------
$oldInMode = GetConInMode
$oldOutMode = GetConOutMode
$newMode = $oldOutMode
$doit = $false
if ($PSBoundParameters.ContainsKey("Mode")) {
$newMode = $Mode
$doit = $true
}
if ($doit) {
echo "old (out) mode: 0x$($oldOutMode.ToString("x"))"
SetConOutMode $newMode
$newMode = GetConOutMode
echo "new (out) mode: 0x$($newMode.ToString("x"))"
} else {
echo "Console Input Mode (CONIN) : 0x$($oldInMode.ToString("x"))"
echo "Console Output Mode (CONOUT) : 0x$($oldOutMode.ToString("x"))"
}
So at the end of the day, I want to enable ENABLE_VIRTUAL_TERMINAL_PROCESSING for the Console.
The system I am using for this is:
---------------------------------------------------------
PowerShell Version : 6.1.1
OS Name : Microsoft Windows 8.1 (64-bit)
OS Version : 6.3.9600 [2018-11-16 00:50:01]
OS BuildLabEx : 9600.19179
OS HAL : 6.3.9600.18969
OS Kernel : 6.3.9600.18217
OS UBR : 19182
-------------------------------------------------------
with Privilege : Administrator
-------------------------------------------------------
ExecutionPolicy :
MachinePolicy : Undefined
UserPolicy : Undefined
Process : Undefined
CurrentUser : Undefined
LocalMachine : Bypass
Console Settings:
Type : ConsoleHost
OutputEncoding : Unicode (UTF-8)
Color Capability : 23
Registry VT Level : 1
CodePage (input) : 437
CodePage (output) : 437
I have also enabled the registry item: HKCU:\Console\VirtualTerminalLevel, as instructed elsewhere.
Q: How can I enable this bit/flag using PowerShell?
Some things I can think of that may be wrong:
I surely have the wrong understanding of how this works...
I might have the wrong permissions to write to console? (How to set?)
I might not write to the correct output buffer? (How to find?)
Note that setting the output mode of one screen buffer does not affect the output mode of other screen buffers.
When executing a script, perhaps a new output buffer is created? (What to do?)
I might have to create a new buffer?
I might have to create a new Console?
Related Questions and Links:
ENABLE_VIRTUAL_TERMINAL_PROCESSING and DISABLE_NEWLINE_AUTO_RETURN failing
MSDN: Inside the Windows Console
MSDN: Introducing the Windows Pseudo Console - ConPty
The code is using "GetStdHandle" to get stdin or stdout. And those might be console handles - but it's dependent on how the process is created. If you're launched from a console, and the stdin/stdout aren't redirected, then you'd probably get a console handle. But it's not guaranteed.
Rather than asking for stdin/stdout, just open the console handles directly - you can "CreateFile" for CONIN$ and CONOUT$. The documentation for CreateFile has a whole section on Consoles.
Update: I made a Gist to demonstrate how to use CreateFile to open CONIN$ and CONOUT$ from PowerShell.
I have been experimenting with this myself for a few days and have come to realize a few things. Apparently PowerShell enables Virtual Terminal Processing when it starts up. It disables it again, however, when it launches an executable and then reenables it when the executable exits. This means that whatever executable needs Virtual Terminal Processing must enable it itself or be called through a wrapper program that enables it and then pipes stdin/stdout/stderr through to the terminal. As for how would even go about writing such a program, I don't know.
I'm running a .NET Core Console Application on CentOS box. The below code is executing for normal command like uptime, but not executing for lz4 -dc --no-sparse vnp.tar.lz4 | tar xf - Logs.pdf:
try
{
var connectionInfo = new ConnectionInfo("server", "username", new PasswordAuthenticationMethod("username", "pwd"));
using (var client = new SshClient(connectionInfo))
{
client.Connect();
Console.WriteLine("Hello World!");
var command = client.CreateCommand("lz4 -dc --no-sparse vnp.tar | tar xf - Logs.pdf");
var result = command.Execute();
Console.WriteLine("yup ! UNIX Commands Executed from C#.net Application");
Console.WriteLine("Response came form UNIX Shell" + result);
client.Disconnect();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Expected output is Logs.pdf file needs to be extracted and saved in the current location. Can someone correct me where im
If application is running on Linux machine then you can try this also:
string command = "write your command here";
string result = "";
using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
proc.StartInfo.FileName = "/bin/bash";
proc.StartInfo.Arguments = "-c \" " + command + " \"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.Start();
result += proc.StandardOutput.ReadToEnd();
result += proc.StandardError.ReadToEnd();
proc.WaitForExit();
}
return result;
I am developing a Qt application that, among other things, converts an Excel spreadsheet in a text delimited with tab file. This is done by running a Windows Powershell script.
My problem is that the finished() signal from the QProcess is never emitted, although the conversion is done successfully. And yes, I receive stateChanged() signal.
Powershell script (ps_excel.ps1)
(adapted from this question)
param ([string]$ent = $null, [string]$sal = $null)
$xlCSV = -4158 #value for tab delimited file
$Excel = New-Object -Com Excel.Application
$Excel.visible = $False
$Excel.displayalerts=$False
$b = $Excel.Workbooks.Open($ent)
$b.SaveAs($sal,$xlCSV)
$Excel.quit()
exit 0 #tested without exit, with exit and with exit 0
Qt app header
(For testing, the minimal case is a QDialog without other widgets.)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QProcess>
#include <QDebug>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
QProcess *proces;
private:
Ui::Dialog *ui;
private slots:
void procFinish(int estat);
void procState(QProcess::ProcessState estat);
};
#endif // DIALOG_H
Qt app C++
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
QString program = "C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe";
QStringList params;
params << "-File" << "C:/Garsineu/ps_excel.ps1" << "-ent" << "C:/Garsineu/PROVAGALATEA.xls" << "-sal" << "C:/Garsineu/PROVAGALATEA.tab";
proces = new QProcess();
connect(proces, SIGNAL(finished(int)), this, SLOT(procFinish(int)));
connect(proces, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(procState(QProcess::ProcessState)));
proces->start(program, params);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::procFinish(int estat)
{
qDebug() << "Finished";
}
void Dialog::procState(QProcess::ProcessState estat)
{
qDebug() << estat;
}
Although the conversion is successful and the states 1 (Started) and 2 (Running) are shown, the message "Finished" is never displayed.
I also tried to do it synchronously, by waitForFinished () method, which is always timed out.
Environment
Windows 7 Professional 64 bit
Powershell v1.0 x86
Qt 5.4.0 with minGW491_32
I appreciate your help. Thank you.
I found the solution. Apparently Powershell does not run in the same way from the console or when is called from another program (noninteractive). If I add at end of ps_excel.ps1 script:
Get-Process Powershell | Stop-Process
instead of
exit 0
I Stop really Powershell and get finished signal, with QProcess::ExitStatus = 0.
I am starting my ps-script by Windows' ShellExecuteW(..):
#import "shell32.dll"
int ShellExecuteW(int hWnd,int lpVerb,string lpFile,string lpParameters,string lpDirectory,int nCmdShow);
#import
....
string psDir = "C:\\Users...\\WindowsPowerShell";
string param = "-file loadPOP2emails.ps1";
int ret = ShellExecuteW(0,0, "powershell.exe", param, psDir, SW_SHOW);
What do I have to enter in the param-string that the console remains open after the script has finished?
Any hint that I can try?
Thanks in advance
The parameter needed to keep powershell open is NoExit
string param = "-NoExit -file loadPOP2emails.ps1";