How to continue executing a Powershell script after starting a web server? - powershell

I have a script which calls two other scripts.
script0.ps1
Invoke-Expression C:\script1.ps1
Invoke-Expression C:\script2.ps1
The first script starts a web server:
script1.ps1
./activate anaconda_env
cd C:\webserver
python api_server.py
The second script starts a ngrok service:
script2.ps1
./activate anaconda_env
cd c:\ngrok
./ngrok -subdomain=mysd 8000
The problem is that the script0.ps1 only executes script1.ps1. At this point the web server starts running in the console and so the second command of script0.ps1 is not executed.
How to make write the scripts so both commands are executed? Or, how to write just one script to execute all commands but in two separate consoles?
The final result should be:
1) a web server running in a console with activated anaconda environment
2) a ngrok service running in a console with with activated anaconda environment

Change Script1.ps1 to launch python as a job:
./activate anaconda_env
cd C:\webserver
Invoke-Command -ScriptBlock {.\python.exe api_server.py} -AsJob -ComputerName .
I don't have the specific script you're using, so I tested this with turtle.py which ships with 3.43 and it seems to work.

You don't need to use Invoke-Expression to run a Powershell script from another script. Just run it as if you're on the command line
c:\script1.ps1
c:\script2.ps1
Now if script1.ps1 starts a process that doesn't exit, it will halt execution for the next statements in the script, and thus also prevent the second script from running.
In most cases this sequential execution is exactly what you want.
In your case you can start the scripts asynchronously by using Start-Process.
So your main script becomes something like:
start-process c:\script1.ps1
start-process c:\script2.ps1
Start-Process basically starts a new command shell to run the statement in. Check out the docs for more info. There's a bunch of parameters you can use to tweak how this happens.

To not have invoke-expression close your script you can pipe the output to Out-Null. Your code above would look like:
Invoke-Expression C:\script1.ps1 | Out-Null
Invoke-Expression C:\script2.ps1 | Out-Null

Related

Powershell execute commands on newly started Command Prompt process

Trying to start a new process in a separate command prompt on Windows 10, but can't find how to execute commands in opened prompt. With Powershell, I could use -Command:
Start-Process PowerShell "-Command tasklist"
But how to do that in Command Prompt window? This, obviously, doesnt work:
Start-Process cmd '-Command tasklist'
You're using the PowerShell arguments for cmd.exe. cmd /? will give you the usage, but what you want is cmd /c COMMAND [ARGUMENTS]:
Start-Process cmd "/c ping -n 4 google.com"
#Jeff Zeitlin was kind enough to provide a link to the SS64 CMD usage.
Worth mentioning, you don't need to use Start-Process when running external commands unless:
You are running a GUI application and wait to use the -Wait parameter to wait until the program exits
You want to run something in a different process asynchronously and check the result later
In this case don't forget to use -PassThru and assign the process to a variable, so you can check the result when ready

Run executable in powershell without waiting for return

This is really basic, but I can't find the answer. The installer sets up my path so that I can just type the command:
ng serve
at the command prompt and the script runs. I don't want to wait for this program to finish (it's a server, after all). How do I launch the same script (it's a CMD script as far as I can tell) from Powershell without waiting for it to finish (and without having to find the source directory for the script)?
If it's acceptable to terminate the server when the PowerShell session exits, use a background job:
In PowerShell (Core) 7+
ng server &
In Windows PowerShell, explicit use of Start-Job is required:
Start-Job { ng server }
Both commands return a job-information object, which you can either save in a variable ($jb = ...) or discard ($null = ...)
If the server process produces output you'd like to monitor, you can use the Receive-Job cmdlet.
See the conceptual about_Jobs topic for more information.
If the server must continue to run even after the launching PowerShell session exits, use the Start-Process cmdlet, which on Windows launches an independent process in a new console window (by default); use the -WindowStyle parameter to control the visibility / state of that window:
Start-Process ng server # short for: Start-Process -FilePath ng -ArgumentList server
Note: On Unix-like platforms, where Start-Process doesn't support creating independent new terminal windows, you must additionally use nohup - see this answer.

Run a PowerShell method from cmd and don't wait for its return

In cmd I'm trying to run Method1 which is in a PowerShell script, script1.
Method1 is a method that takes a few hours, and I simply want to fire and forget.
The following is working for me:
c:\temp> powershell
PS c:\temp> . .\script1.ps1;Method1
When I do the lines above, everything is working fine as long as I keep the CMD of PS opened. once I close the PS window, it kills Method1.
So actually I want that from cmd, in one line, to somehow make Method1 work without the dependency of the PowerShell window, maybe create a new process.. I am not really sure.
I've tried:
c:\temp> cmd /c powershell . .\script1.ps1;Method1
It is running for a few seconds, but when the cmd gets closed, then Method1 also terminates.
I also tried
c:\temp>cmd /c powershell -noexit "& { . .\script.ps1;Method1 }"
Again, once I do this, it is working. However, a PowerShell window is opened and if I close it then it terminates Method1.
From you help, I've tried:
c:\temp> cmd /c powershell start-process cmd /c powershell . .\script1.ps1;Method1
But I get an exception:
Start-Process : A positional parameter cannot be found that accepts
argument 'powershell'.
But still, I am not able to make it work.
Alternatively if you want a pure PowerShell solution (note this needs to be running as Admin):
Invoke-Command LocalHost -Scriptblock $script -InDisconnectedSession
The InDisconnectedSession switch runs it in a separate PowerShell session that will not be terminated when you close the PowerShell window. You can also use Get-PSSession and pass the session to Enter-PSSession to interact with it during or after execution. Remember in this state if you close the window it -will- kill it, so you'll want to use Exit-PSSession to keep it alive.
There is however a problem - you can't do any remoting tasks, at least not easily. This incurs the wrath of the "double hop" where you remote to one computer (your own in this case), then to another, and for security PowerShell refuses to pass any credentials to the second remoting session so it can't connect, even if you put the credentials in manually. If you do need to do remoting I recommend sticking with launching a hidden PowerShell process.
You can use PowerShell jobs for that, so just:
Start-Job -FilePath somepath
And add a method call at the end of the script, or pass in a Scriptblock like:
Start-Job -ScriptBlock {. .\path_to_ps1; Method1}
Or perhaps use the hackish:
start-process cmd -WindowStyle Hidden -ArgumentList "'/c powershell . .\script1.ps1;Method1'"
Actually, you can just launch PowerShell, without CMD, and I am not sure why I was using a cmd approach:
start-process powershell -WindowStyle Hidden -ArgumentList ". .\script1.ps1;Method1"
Easy answer ya'll; Just paste "start" command into your PS window (whether in a remote session or not) and it works fine:
Start C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file 'driverletter:\path\yourpowershellscript.ps1'

Need to unblock remote ps script run using psexec

As part of our automatic build and deploy using TFS, I need to execute a powershell script on a target server. The following is the (simplified for clarity) command run on the build server by the TFS Build Agent PreBuild step, in the (pre-build.ps1) script...
C:\Builds\<snip>\psexec.exe -accepteula -s -i \\WSRMO632WEB powershell.exe \\TFS-BAGENT-POC\<snip>\PreBuild-AppPool.ps1 -name AppPool-DEV -usr User -pw pass
If I run the powershell part of the command on the WSRMO632WEB box in a command window, I get the warning...
Security warning
Run only scripts that you trust. While scripts from the internet can be useful,
this script can potentially harm your computer. If you trust this script,
use the Unblock-File cmdlet to allow the script to run without this warning message.
Do you want to run \\TFS-BAGENT-POC\<snip>\PreBuild-AppPool.ps1?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
If I choose R, the script runs and performs correctly.
My problem is that I cannot get the syntax correct to incorporate the Unblock-File cmdlet.
I'm currently thinking that I'm going to have to use multiple psexec commands, one to copy the file from the build server, one to unblock it and a third to finally run it.
Surely it should be easier than that, but I can't find a suitable example and can't get the syntax right.
Any suggestions, please?
You can use Powershell's -command to first do an Unblock-File, then run it as a script.
C:\Builds\<snip>\psexec.exe -accepteula -s -i \\WSRMO632WEB powershell.exe "-command \"$file='\\TFS-BAGENT-POC\<snip>\PreBuild-AppPool.ps1'; $file; Unblock-File $file; & $file\"" -name AppPool-DEV -usr User -pw pass
Quotes are necessary so that the full command string will be passed to Powershell. Add backslashes to escape themselves as necessary.
UPDATE: You can also try feeding the required command into standard input.
echo r | C:\Builds\<snip>\psexec.exe -accepteula -s -i \\WSRMO632WEB powershell.exe \\TFS-BAGENT-POC\<snip>\PreBuild-AppPool.ps1 -name AppPool-DEV -usr User -pw pass
This way Powershell will run, get the "R" for "Run once" and run the script, without any changes to the script or calling command.

PowerShell: Starting the CLR Failed with HRESULT 8007000e

I'm getting the following error when running PowerShell scripts on a remote server:
Starting the CLR Failed with HRESULT 8007000e
This is basically how I'm running/calling the scripts:
On the local server I'm running a CMD script that calls a PowerShell script to create a remote session to a remote server. In the PowerShell script I also call a CMD script to run on the remote server like so:
$Script = [scriptblock]::create("cd $BuildPath | cmd.exe /c install.cmd $apptype")
The install.cmd script runs on the remote server and calls a PowerShell script that executes a series of tasks.
powershell ./Install.ps1 -BuildNum %BUILDNUM%
After the tasks are complete, the PowerShell script then calls another PowerShell script to run a separate series of tasks. This is when I hit the above error, when the second PowerShell script is called.
This is how the second PS1 script is called from the first PowerShell script:
powershell "& {. $BinToolsSrc\PostInstallValidation.ps1 -BuildNum $BuildNum -Test 'True'; Run-Validation -App $App -AppLoc $AppLoc -Env $Env:ENV -Site $Site -AppPool $AppPool -Config $Config -EnvConfig $EnvConfig -DllPath $DllPath}"
What usually causes the type of CLR error that I'm getting and how do I resolve it?
NOTE: I do not get this error when I run the install script locally on the remote server.
Thanks in advance!
UPDATE: Installing PowerShell 3 on the remote server seems to have solved the problem as it targets the .NET 4.0 runtime.
I too had the same problem because I have changed some path settings in my VScode unknowingly.
I have changed the settings to command prompt which works fine for me now...(This might not be the best solution though).screenshot