docker RUN on windows what happens? - windows

I struggle to understand what happens when docker build runs on windows.
Especially the RUN instruction.
I have seen scripts where after RUN instruction follows powershell code. But in my case I have to use cmd code. Is there a switch? How can I make the RUN run powershell?
RUN ["powershell", ... causes:
'["powershell"' is not recognized as an internal or external command,
Is there a switch? Configuration? Flag?
Unfortunatelly the code words are kind of difficult to google due to "run" "command" and similar being kind of really general.
EDIT: (code in question)
ARG MINGW32_SCRIPT=install_mingw32.ps1
ARG MINGW32_INSTALLER=mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip
ADD ${MINGW32_SCRIPT} ${BASE_PATH}\\${MINGW32_SCRIPT}
COPY ${MINGW32_INSTALLER} ${BASE_PATH}\\${MINGW32_INSTALLER}
RUN powershell -command "%BASE_PATH%\%MINGW32_SCRIPT%"
This is what I have now, this works. But the return value of the script is ignored. (As powershell returns sucessfully.)
I want the last line to be something like:
RUN ${BASE_PATH}\\${MINGW32_INSTALLER}
I want the build to fail when the script fails. But this fails. (As for some reason after RUN I have to post CMD code. It calls cmd, that calls powershell.
If it matters, the win is server 2016.
Thanks for help
operable program or batch file.

Related

Rust std::process with special characters

I've got a very simple rust program but its not doing quite what I'd expect. Running on Windows, using a powershell prompt, I can do the following to display the path:
echo "%PATH%"
and I have a simple Rust program with:
Command::new("echo")
.arg("%PATH%")
.spawn()
.expect("ls command failed to start");
The command will launch and run, but it outputs:
%PATH%
instead of the path contents, like I'd expect. Other commands which don't use special characters seem to work as expected, so I suspect its related to handling them but I don't see a way in Rust to make the command any more primitive than it already is.
I've tried various formatting but it either fails to run the command or does the same.
I also tried using $env:path, but this always fails to run from Rust with a cannot find the path specified error.
Are there any suggestions for handling this? I could write the contents to a file and run the file instead, but running these types of commands from other languages directly works fine so I think it should work from Rust as well.
Thanks!
Update:
Managed to get the expected results from by using:
let out = Command::new("cmd")
.arg("/C")
.arg("echo %PATH%")
.spawn()
.expect("ls command failed to start");
}
I think the question got interpreted a bit differently, as getting the path was just an example of a larger issue I was seeing. Updating with the above solved my larger issue as well.
As the comment by French says: Spawning the process does not include the Powershell-environment, which would expand %PATH% to it's actual content before launching the process.
You need to get the content of PATH via std::env yourself or lookup the Powershell documentation on how to launch a subprocess inside a powershell-session.
As others have mentioned, it's not the special characters, it's the fact that those special characters are interpreted by powershell before the "echo" program runs at all.
Using https://doc.rust-lang.org/cargo/reference/environment-variables.html as a reference for how to look up environment variables, try something like this:
use std::env;
fn main() {
let cur_path = env::var("PATH").unwrap();
println!("Environment is: {}", cur_path);
}
You can try this here: https://play.rust-lang.org/
You can then feed cur_path into your "Command::new" if you wish. The trick is that powershell substitutes that argument BEFORE launching echo, which you may not have known, whereas when you execute the echo program directly, you have to do that substitution yourself.

execute powershell commands with Lua

I have a program that I work with, that has an onboard lua compiler to allow for custom written actions.
Since the tool itself is very limited, especially if it goes for complex reactions over networks, I want to use Powershell over lua.
Methods like os.execute() or io.popen() use the standard command line from windows and not Powershell.
Is there a way to use Powershell with lua?
I tried to write a command line script with the Powershell editor and run this script with os.execute, but it opens it as a textfile, it would be better to write the commands directly in lua but if there is no other way, executing a Powershell script directly would also be fine. (In Windows itself you can execute the script with right mouse "click/Execute with Powershell")
-- You can generate PowerShell script at run-time
local script = [[
Write-Host "Hello, World!"
]]
-- Now create powershell process and feed your script to its stdin
local pipe = io.popen("powershell -command -", "w")
pipe:write(script)
pipe:close()
Your description of the problem makes it sound like you're using a command such as os.execute("powershellscript.ps1"), and that call invokes cmd.exe with your string as the proposed command line. Normally, Windows will open a .PS1 file for editing; this was a deliberate decision for safety. Instead, try altering the os.execute() command to explicitly call PS: os.execute("powershell.exe -file powershellscript.ps1"). If you need to pass parameters to your script, enclose them in {}. See https://msdn.microsoft.com/en-us/powershell/scripting/core-powershell/console/powershell.exe-command-line-help for more info on invoking PowerShell from the command line.

How can I make a local Git hook run a Windows executable and wait for it to return?

I'm working in a Windows environment. I have a Git repository and am writing a custom pre-commit hook. I am much more comfortable writing a quick and dirty console application in C# than trying to figure out Perl syntax so that's the route I'm going.
My .git/hooks/precommit file looks like this:
#!/bin/sh
start MyHelperApp.exe
And this works somewhat. As you can see I have a compiled helper application in the root of the repo directory (and it is .gitignore'd), and this does indeed launch my application successfully when I call git commit. However, it doesn't wait for the process to finish nor does it seem to care what the return code of the process is. I assume this is because start is asynchronous and it returns a 0 exit code every time.
I have reason to suspect that the start process which is getting called here is not the native Windows start command, because I tried changing it to start /wait MyHelperApp.exe but this had no effect. Also trying to call MyHelperApp.exe directly gives a "command not found" error, and so does changing start to call. I suspect that start is an emulated bash command and it's running the bash version instead of the Windows version?
Anyways, my helper app does return different exit codes depending on different conditions, so it'd be great if those could be used. (Pre-commit hooks fail if a program in the script returns any exit code besides zero.) How might I go about utilizing this?
Call the executable directly, don't use start.
Also trying to call MyHelperApp.exe directly gives a "command not found" error
If the PATH variable doesn't contain a . entry, bash won't look in the current directory to find executables. Call ./MyHelperApp.exe to make it explicit that it should be run from the current directory.

Windows Program: How to snoop on command line arguments?

I am trying to reverse engineer the build system of a commercial Windows based IDE, so I can use make to build my project.
A program is launched to perform a task, and I need to know what command line arguments are passed to this program when it is run. However the windows process viewer does not show the command line arguments.
Is there any way to see what command line arguments are being passed when the program is launched?
(Actually it just occurred to me that I should substitute a stub program to read the command line args. Still, I'd like to know if there's an easy way).
Sysinternals Process Explorer lets you do that.

Powershell script gets stuck, doesn't exit when called from batch file

I have a PowerShell script that connects to a web site, and parses its returned data (It's about importing a previously uploaded SQL file into the web site's data base). The PowerShell script uses wget, something I may replace by a native function later.
The import process is embedded in a script that is executed by a 3rd party program called scriptFTP.
The script runs fine when I call it from a single .bat file like so:
powershell "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%
However, when I call this .bat file from within the greater ScriptFTP context, the following happens:
The PowerShell script is executed. I confirmed this my sending myself an E-Mail each time the remote import script got called.
PowerShell doesn't seem to exit, and script execution gets stuck. I can still cancel the whole thing using Ctrl+C but the following commands never get executed.
When I change the batch file to the following:
start powershell "& "C:\data\etc\run_import_script.ps1"
exit %ERRORLEVEL%
it works, running the PowerShell script in a new console, but I can't grab the error level that PowerShell returns.
I have tried calling PowerShell from ScriptFTP directly, bypassing the batch file, but with the same result: It just gets stuck.
Any output I have the PowerShell script do using Write-Output or Write-Host is not displayed.
All programs run under the same user, me.
Does anybody have any ideas what to do?
This variant might work for you.
powershell -NoProfile -Command "C:\data\etc\run_import_script.ps1; exit $LASTEXITCODE" < NUL
Taken from http://thepowershellguy.com/blogs/posh/archive/2008/05/20/hey-powershell-guy-how-can-i-run-a-powershell-script-from-cmd-exe-and-return-an-errorlevel.aspx
From my experience, PowerShell.exe can easily run scripts from within a batch file or shell script in a predictable way using the -File switch. One does not need to use the Start command.
The important thing to do is to append
< nul
to the command line from within a batch file. My research has shown that PowerShell runs the commands in the script indicated through the -File switch and then waits for additional PowerShell commands from the standard input (my brief experimentation with the -Command switch demonstrated similar behavior). By redirecting the standard input to nul, once PowerShell finishes executing the script and "reads end-of-file" from the standard input, PowerShell exits.
When invoking PowerShell from Cygwin, use
< /dev/null
For example, I've run PowerShell scripts from Cygwin using shell variables, like this:
PowerShell.exe -ExecutionPolicy RemoteSigned -File $_powershellscriptpath $_firstscriptparameter < /dev/null
Please post a comment if your experience varied from mine.
- Gordon
Try adding the /WAIT parameter. It will keep the .bat waiting until the PowerShell script completes.
START /WAIT powershell "& "C:\data\etc\run_import_script.ps1"
We had a similar issue. We wanted to call a powershell app from a piece of software that just had a box to enter "Command" and "Parameters" but although the powershell ran successfully (I could see the affected file updated.)
Finally my coworker helped me figure it out
Command needs to be:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
And Parameters:
-ExecutionPolicy unrestricted -Command "& {C:\scripts\apps\EDI\Test.ps1; [Environment]::Exit(1)}"
In our case it was important to use [Environment]::Exit(1) rather than Exit 1. I believe Exit was simply terminating the script, not closing Powershell itself.
If you want to capture the output of the powershell.exe commands then you can also use the /B parameter to force the process to run in the same command shell.
We've just seen a very odd instance of this problem. A batch file containing the call powershell.exe -command ... ran fine locally but stalled as described above when the batch file was run in the context of an msdeploy -postSync command. After experimenting with process.Kill() to force PowerShell to quit, we lit on the use of START /WAIT /B PowerShell.exe ..
No idea why this should work, but it does ...
IF that is exactly what's in your file it's because you have mismatched quotes. Powershell is waiting for the last quote.
PowerShell has, at least what I consider, strange behavior when being invoked in this manner. In short, it doesn't treat the command line arguments being passed to powershell.exe as scripts to run. Instead, it treats them as command to run. This is because the default for powershell.exe is -command - see powershell.exe /? for additional info.
C:\>powershell "'Hello'"
Hello
What you will need to do, is construct a clever input string to "source" the script you wish to run:
C:\>powershell ". .\test.ps1"
Hello, World!
As for the output, once you get the script running correctly, it should just be a matter of capturing STDOUT or whatever ends up fitting with your script.
Full Example
test.bat
#echo off
powershell.exe ". .\test.ps1"
test.ps1
"Hello, World!"
Invoke the command:
test.bat > test.txt
And verify the output was captured:
C:\>type test.txt
Hello, World!
The problem I bet is that the Powershell process continutes to run after executing the script. This means it has not exited and therefore there is no exit code. I'm having a similar problem when trying to run a Powershell script from C# that does stuff when finished, except it never finishes...
Hacky, but the only solution I've found is to put Stop-Process -processname powershell at the end of the .ps1 script. This kills off the PowerShell process (and all PowerShell windows you have open unfortunately) but seems to work. Might work for your script as well.
I had the exact issue, we were trying to integrate power shell scripts into another system and it kept giving a timeout error. Probably because of the issue mentioned by Gordon Smith, his solution might work. But to me I prefer to have complete control of my script from within the script itself and not depend on the way in which it is called.
$pid is built in variable with the PID. The below will end the current powershell process and leave the others intact. This way anyone can call your script as normal and it will work as expected.
Stop-Process $pid
you can simply add an 'exit' command to the end of the .ps1 script (or any variant of process termination that you wish). Powershell will continue to run at the end of the script as it has not been told to terminate (when run in PS or ISE it will auto-terminate at the end of the script but not when run through the DOS shell).

Resources