Creating a folder without space is failing - cmd

I have a pure QML application where I'm trying to create a folder with a QProcess on Windows.
If the path I'd like to create contains a space it is working.
If the path I'd like to create DOES NOT contain a space it is NOT working.
QML function:
function mkdir(qproc, path) {
var cmd;
var res = false;
// Platform-based command
switch (Qt.platform.os) {
case "windows":
cmd = "cmd /s /c mkdir \"" + path + "\"";
break;
default:
cmd = "/bin/sh -c \"mkdir -p '"+path+"'\"";
}
qproc.start(cmd);
res = qproc.waitForFinished(5000);
}
Which ends up as DOS commands:
Path with space: cmd /s /c mkdir "D:/Misc/temp/A Folder/" ==> A Folder is created
Path without space: cmd /s /c mkdir "D:/Misc/temp/AFolder/" ==> AFolder is NOT created
Two remarks:
the \s flag seems having no effect, neither positive nor negative (I could remove it)
launched individually in a cmd-prompt, the 2 calls are working. The issue seems to be in the QML<->cmd interaction.

Related

Jenkins Pipeline does not store Windows env variables from a cmd file

In a Jenkins Pipeline (groovy) i try to run a windows script and use the variables set in this script afterwards.
I broke down the situation to this Pipeline attached.
Here I call "set" twice. Once before the script and once after the script.
My expectation is that i see the new variable in the second output. But the output does not change at all. I do see some (PATH, ...), so it is not just empty.
The goal is to have scripts working that set for example qt environment variables.
Does anybody know if I call the script in a "bad" manor? or sth else?! that I miss here.
timestamps {
parallel(
"build_windows": {
node('winddk-build') {
stage('create bat file') {
bat """
>mybat.cmd echo set MYVAR=1234
>>mybat.cmd echo cmd /k
"""
}
stage('run bat file') {
bat """
set
cmd /k mybat.cmd
set
"""
}
stage('clean up bat file') {
bat """
del /Q /S mybat.cmd
"""
}
}
}
)
}

How to stop Golang from replacing double-quotes with backslashes when executing a Windows command?

I am writing a program in Golang that will use Mozilla's Thunderbird email client to send email. The Windows command that should be executed is:
start "" "C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe" -compose "to='CloudCoin#Protonmail.com',subject='Subject1',body='Hello'" -offline
My Go code looks like this (command is the one listed above) :
var command string
command = `start "" "C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe"`
command += ` -compose "to='` + toAddress + `',`
command += `subject='Subject1',`
command += `body='Hello'"`
command += ` -offline`
cmd := exec.Command("cmd.exe", "/C", command)
But I get an error:
Windows cannot find '\\'. Make sure you typed the name correctly, and then try again.
If I change the code to this (moving the word start):
var command string
command = ` "" "C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe"`
command += ` -compose "to='` + toAddress + `',`
command += `subject='Subject1',`
command += `body='Hello'"`
command += ` -offline`
fmt.Println("Command: " + command)
cmd := exec.Command("cmd.exe", "/C", "start", command)
Then I get another error:
Windows cannot find 'Files'. Make sure you typed the name correctly, and then try again.
It seems that instead of trying to start "" it is trying to start \\. How can I keep my double-quotes?
Your problem likely is that every separate string passed to exec.Command is passed on (without parsing it) as a single argument to cmd.exe, which does probably not split given strings either, so you have to do it yourself.
See this example where the argument is being split up too. You should be able to leave " out since you split it up manually anyway, or write a program for it or run it with an interpreter which does the splitting.
func do() {
args := []string{
"/C",
"start",
"",
`C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe`,
"-compose",
"to=" + toAddress + ",subject=Subject1,body=Hello",
"-offline",
}
cmd := exec.Command("cmd.exe", args...)
}

Doing operation for each file of a folder using windows command line

I have some document in a folder. these document may have same name with different extention, e.g: xyz.doc, xyz.pdf and xyz.log. I want implement following logic in windows command line script:
foreach *.doc {
if EXIST *.pdf{
do something_1
}else {
do something_2
}
if EXIST *.log {
do something_3
}
Here's my Minimal, Complete, and Verifiable example (Copy&Paste from cmd window). Used another extensions but principle is the same:
==> dir /b "sta *.*"
sta tus.csv
sta tus.txt
sta tus2.txt
==> for %G in ("sta *.txt") do #if exist "%~nG.csv" (echo + %~nG ) else (echo - %~nG)
+ sta tus
- sta tus2
==>
A batch script for your extensions:
#echo off
for %%G in ("*.doc") do (
if exist "%%~nG.pdf" (
echo + %%~nG
) else (
echo - %%~nG
)
)
Resources (required reading, incomplete):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~G, %~nG etc. special page) Command Line arguments (Parameters)

qmake command to copy files and folders into output directory

I'm developing an app that should build on Windows, Linux and OS X using QtCreator and Qt 5.3. I want to copy all files and subfolders from a folder into output folder. I've got it working for Linux and OS X, but not for Windows. Here's the relevant section of my .pro file:
win32 {
PWD_WIN = $${PWD}
DESTDIR_WIN = $${OUT_PWD}
copyfiles.commands = $$quote(cmd /c xcopy /S /I $${PWD_WIN}\copy_to_output $${DESTDIR_WIN})
}
macx {
copyfiles.commands = cp -r $$PWD/copy_to_output/* $$OUT_PWD
}
linux {
copyfiles.commands = cp -r $$PWD/copy_to_output/* $$OUT_PWD
}
QMAKE_EXTRA_TARGETS += copyfiles
POST_TARGETDEPS += copyfiles
The error I'm getting on Windows is "Invalid number of parameters".
If you look at the $${PWD} variable with message($${PWD}), you will see / as directory seperator, even in Windows. You have to convert it to native directory seperator :
PWD_WIN = $${PWD}
DESTDIR_WIN = $${OUT_PWD}
PWD_WIN ~= s,/,\\,g
DESTDIR_WIN ~= s,/,\\,g
copyfiles.commands = $$quote(cmd /c xcopy /S /I $${PWD_WIN}\\copy_to_output $${DESTDIR_WIN})
QMAKE_EXTRA_TARGETS += copyfiles
POST_TARGETDEPS += copyfiles
Building off of #Murat's answer, Qt actually has built-in functions to convert the filepath to the local system's preference.
$$shell_path( <your path> ) //Converts to OS path divider preference.
$$clean_path( <your path> ) //Removes duplicate dividers.
Call it like: $$shell_path($$clean_path( <your path> )), or $$clean_path() will convert the dividers back to Linux-style dividers.
This works for me on Windows:
#For our copy command, we neeed to fix the filepaths to use Windows-style path dividers.
SHADER_SOURCE_PATH = $$shell_path($$clean_path("$${SOURCE_ROOT}\\Engine\\Shaders\\"))
SHADER_DESTINATION = $$shell_path($$clean_path("$${PROJECT_BIN}\\Shaders\\"))
#Create a command, using the 'cmd' command line and Window's 'xcopy', to copy our shaders folder
#into the Game/Bin/Shaders/ directory.
CopyShaders.commands = $$quote(cmd /c xcopy /Y /S /I $${SHADER_SOURCE_PATH} $${SHADER_DESTINATION})
#Add the command to Qt.
QMAKE_EXTRA_TARGETS += CopyShaders
POST_TARGETDEPS += CopyShaders

Capturing (failed) mklink command output

Does anybody know why the below happens and does anybody have a workaround?
I'm strugging to capture mklink command output (via cmd.exe mklink > out.txt)
Output is sent to out.txt fine if the mklink command is successful
E.G: %comspec% /c mklink /d C:\Test C:\Windows > out.txt && notepad out.txt
However if the command is invalid, or fails, then nothing will be written to out.txt
E.G: Run above command again (fails because C:\Test already exists) or
E.G: %comspec% /c mklink > out.txt && notepad out.txt
I'm using the command in VBScript, does anybody know how to capture the mklink output if the command isn't completed successfully?
Set o_shell = CreateObject("Wscript.Shell")
Set o_fso = CreateObject("Scripting.FileSystemObject")
mklinkCommandOutput = GetCommandOutput("mklink /D ""C:\Test"" ""C:\Windows""")
WScript.echo mklinkCommandOutput
Function GetCommandOutput(runCmd)
on error resume next
Dim o_file, tempFile: tempFile = o_shell.ExpandEnvironmentStrings("%TEMP%") & "\tmpcmd.txt"
' Run command and write output to temp file
o_shell.Run "%COMSPEC% /c " & runCmd & " > """ & tempFile & """", 0, 1
' Read command output from temp file
Set o_file = o_fso.OpenTextFile(tempFile, 1)
GetCommandOutput = o_file.ReadAll
o_file.Close
' Delete temp file
Set o_file = o_fso.GetFile(tempFile)
o_file.Delete
End Function
(1) According to Using multiple commands and conditional processing symbols, the symbol && runs the command on the right only if the command on the left succeeds. You must use &
to start notepad even when the mlink fails.
(2) While the mlink docs don't say so explicitly, I assume that mlink writes its error message to Stderr (see here) - just like dir.
Evidence:
dir 01.vbs
...
19.10.2012 11:29 2.588 01.vbs
...
(dir succeeded)
dir nix
...
File Not Found
(dir failed)
dir nix && echo nothing to see, because lefty failed
...
File Not Found
(dir failed, no output because of &&)
dir nix & echo much to see, although lefty failed
...
File Not Found
much to see, although lefty failed
(dir succeeded, echo done because of &)
(3) To capture the output of mlink (rsp. dir) whether it fails or not and to display the result (file) in notepad, you have to use
dir 01.vbs 1> out.txt 2>&1 & notepad out.txt
dir nix 1> out.txt 2>&1 & notepad out.txt
to redirect Stdout and Stderr to the output file.
Evidence:
Have you considered utilizing the "Exec" command rather than the run command and collecting the output results?
It doesn't require a file and it's just easier.
New Code
Function GetCommandOutput(runCmd)
Dim WshShell, oExec
Set WshShell = CreateObject("WScript.Shell")
Set oExec = WshShell.Exec("%COMSPEC% /c " & runCmd)
GetCommandOutput = oExec.StdOut.ReadAll
End Function
Old Code
Function GetCommandOutput(runCmd)
on error resume next
Dim o_file, tempFile: tempFile = o_shell.ExpandEnvironmentStrings("%TEMP%") & "\tmpcmd.txt"
' Run command and write output to temp file
o_shell.Run "%COMSPEC% /c " & runCmd & " > """ & tempFile & """", 0, 1
' Read command output from temp file
Set o_file = o_fso.OpenTextFile(tempFile, 1)
GetCommandOutput = o_file.ReadAll
o_file.Close
' Delete temp file
Set o_file = o_fso.GetFile(tempFile)
o_file.Delete
End Function

Resources