I have a start.bat similar to the following:
start npx tailwindcss -i ./www/src/styles/main.css -o ./www/dist/styles/main.css --watch
start caddy run
It launches 2 new cmd prompts and starts processes within them (which both run indefinitely). Is there a way for this bat file to send a kill command to the cmds it spawned? Ideally I'd have a single command to kill all "child" processes which were created.
A PowerShell solution - which is acceptable as both implied by this question's tagging and as explicitly stated by icanfathom (the OP) in a comment ("No, PS would be fine") - using the Start-Process and Stop-Process cmdlets:
$processes = & {
Start-Process -PassThru npx 'tailwindcss -i ./www/src/styles/main.css -o ./www/dist/styles/main.css --watch'
Start-Process -PassThru caddy run
}
# ...
# Stop (kill) all launched processes.
$processes | Stop-Process
set "wintitle=my process %time%"
start "%wintitle%" npx tailwindcss -i ./www/src/styles/main.css -o ./www/dist/styles/main.css --watch
start "%wintitle%" caddy run
....
taskkill /FI "WINDOWTITLE eq %wintitle%"
[untested] - should work in theory...
Always best to start with a quoted-title as the first quoted string seen by the start command may be eaten and used as a title otherwise.
Related
I have a powershell script which launches a ffmpeg command
$process = Start-Process -FilePath "cmd" -ArgumentList "/c c:\bin\ffmpeg\bin\ffmpeg.exe -rtsp_transport tcp -i........
This spawns a command prompt window.
I would like to rename the title of the command prompt window and be able to do that for every iteration I run of the ffmpeg command.
I have seen how to rename the title of the window directly via the command prompt and how to rename the powershell window title.
I cannot find any information pertaining to powershell being able to dynamically assign a new title to the command prompt window when created.
Any assistance/pointers would be greatly appreciated.
Once you pass your code off to the cmd instance you started it would be up to the running process to update it's title window (without getting into pinvoke/Windows API calls.) If ffmpeg.exe provides you with the current file as it's running then simply use that to set the title. If not, then it's most likely you'd need to adjust your commands to first get the list of files then iterate over those files setting the title and running the ffmpeg command. Here's a small example of letting the commands set the title.
Start-Process -FilePath "cmd" -ArgumentList "/c for /l %a in (1,1,10) do (title %a & cls & timeout 3)"
If you are instead referring to each time you do Start-Process then simply set the title before the other commands.
Start-Process -FilePath "cmd" -ArgumentList "/c title ffmpeg command running & c:\bin\ffmpeg\bin\ffmpeg.exe -rtsp_transport tcp -i........"
The & character instructs CMD to run the first command AND the next command. && says run the first command and only run the second if the first succeeds. || says run first command and if it fails run second.
By the way, unless you use the -Passthru on Start-Process then it is not collecting anything. With the passthru parameter it would collect a System.Diagnostics.Process object. That could be used for tracking, closing, etc.
$host.ui.RawUI.WindowTitle = "Changed Title"
Something like this?
I am trying to achieve the following using a command line script in windows:
Start an instance of a program (.exe) that launches a GUI (passing also some parameters to the command)
Wait a specific amount of time for the program to be executed (e.g. X second)
Terminate its execution
It can be the case that several instances of the program can run in parallel so what i am searching is a way to be able and terminate the specific instance of the program that was previously launched by the "start" command. A possible way i assume is to be able and get its PID but i am not sure if i can do that when using a simple command line script.
What i have tried is the following:
A) command line script for program's instance "A":
Start "" "C:\Program Files (x86)\XXXX\YYYY.exe" /USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_A
timeout 180
taskkill /F /T /IM YYYY.exe /FI "USERNAME eq domain\username"
timeout 30
exit
B) command line script for program's instance "B":
Start "" "C:\Program Files (x86)\XXXX\YYYY.exe" /USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_B
timeout 180
taskkill /F /T /IM YYYY.exe /FI "USERNAME eq domain\username"
timeout 30
exit
But obviously if i run the two scripts in parallel the taskkill command that is executed first, terminates both instances (i run them as windows scheduled tasks under a specific user account). The parameter that identifies uniquely each instance is the /CMDLINEID but i doubt i can filter the running tasks based on that parameter.
After #filimonic suggestion i am using the following powershell scripts to achieve the objective:
A) Powershell script for instance "A":
$process = [System.Diagnostics.Process]::Start(
'C:\Program Files (x86)\XXXX\YYYY.exe',
'/USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_A')
Write-Host $process.Id
Start-Sleep -Seconds 10
if (-not $process.HasExited) {
$process.Kill()
}
A) Powershell script for instance "B":
$process = [System.Diagnostics.Process]::Start(
'C:\Program Files (x86)\XXXX\YYYY.exe',
'/USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_B')
Write-Host $process.Id
Start-Sleep -Seconds 120
if (-not $process.HasExited) {
//Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $ppid } | ForEach-Object { Kill-Tree $_.ProcessId }
//Stop-Process -Id $ppid
$process.Kill()
}
This is working however i have the following issue:
YYYY.exe is a GUI application that has a "loading" time ~ 60 seconds
The first script which has "10 seconds" wait period is executed normally and i can see in the task manager that the corresponding "task" is also terminated
The second script which has "120 seconds" wait period is executed normally but after its execution the "task" in task manager (same PID) remains running
Any ideas on how to more effectively terminate YYYY.exe running instance?
From one script:
$process = [System.Diagnostics.Process]::Start('cmd.exe')
$process.Id #PID here
# ... Wait something #
$process.Kill()
From second script: ($storedProcessId is somehow stored between scripts). You may requre admin permissions
$process = [System.Diagnostics.Process]::GetProcessById($storedProcessId)
$process.Kill()
Of course you may use alternaltively more powershell-native way:
$process = Start-Process -PassThrough -FileName 'cmd.exe'
Of course, there are variants with command line arguments for both ways. See docs for Process.Start and Start-Process
So your script will be like that
$process = [System.Diagnostics.Process]::Start(
'C:\Program Files (x86)\XXXX\YYYY.exe',
'/USER=myUser /PASSWORDD=myPass /CMDLINEID=winTsk_IntSO_A')
Start-Sleep -Seconds 180
if (-not $process.HasExited) {
$process.Kill()
}
I'm using Azure-Pipelines for my CI. In my pipeline, I need to use multiple instances of a CMD (Windows). For example, one CMD needs to start and continuously run a server, while the other needs to then deploy an app while the server is still running.
When using the CMD task, it only uses one instance of the CMD, so when I run the server, it never finishes and never gets to running the app.
Is there a way to run multiple instances of a CMD with Azure-Pipelines?
You can start cmd.exe on the agent machine from a powershell task using Start-Process command.
So you can add multiple powershell tasks to start multiple CMD instances on the agent machine. Or you can start multiple CMD instances in one powershell task. Se below example:
steps:
- powershell: |
'Start-Process -FilePath "C:\Windows\System32\cmd.exe" -verb runas -ArgumentList {/k echo "hello"}'
- powershell: |
'Start-Process -FilePath "C:\Windows\System32\cmd.exe" -verb runas -ArgumentList {/k echo "world"}'
I am new to windows and PowerShell on the admin level. I have experience in Linux and prefer using Python but I have a difficult time understanding windows environments. In bash and Linux I am used to running shell scripting with cronjobs but in Windows, I'm having an issue running this command in the Task Scheduler. I need to be able to run Google Cloud Directory Sync so that our AD is in sync with Gsuite. I wrote a batch file that works but I feel its a bit dated to use a bat file
cd C:\Program Files\Google Apps Directory Sync\
sync-cmd.exe -a -o -c config.xml
my best guess is this needs to run as a PowerShell script through task scheduler, but I don't know where to start. I found this so far but I get an error that I don't know how to interpret.
Start-Process sync-cmd.exe -ArguementList "-a -o -c C:\Somepath\config.xml"
sorry for being a noob thanks in advance!
Also for an additional resource here's the GCDS command page.
https://support.google.com/a/answer/6152425?hl=en
Your error indicates that Start-Process does not have a parameter called ArguementList. You can use Get-Help to get a list of available parameters.
Get-Help Start-Process -Parameter * | Select-Object Name
Indeed ArguementList is not available, but ArgumentList is available. There simply is a typo in your command.
The following should work just fine:
Start-Process sync-cmd.exe -ArgumentList "-a -o -c C:\Somepath\config.xml"
Option 1 - Schedule your EXE directly through Task Scheduler
No need for powershell. You can just provide the full path to the EXE and the arguments using the Windows Task Scheduler User Interface. You can specify a working folder using the Start in option.
Option 2 - Schedule a PowerShell script using Task Scheduler
I find using the -File option of PowerShell.exe very useful when scheduling a PowerShell script using Task Scheduler. In this case, I would use the cmdlet Start-Process and I would encapsulate the arguments inside the PowerShell script.
Example
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -File "c:\MyScript.ps1"
MSDN
https://learn.microsoft.com/en-us/powershell/scripting/components/console/powershell.exe-command-line-help?view=powershell-6
Syntax
PowerShell[.exe]
[-Command { - | <script-block> [-args <arg-array>]
| <string> [<CommandParameters>] } ]
[-EncodedCommand <Base64EncodedCommand>]
[-ExecutionPolicy <ExecutionPolicy>]
[-File <FilePath> [<Args>]]
[-InputFormat {Text | XML}]
[-Mta]
[-NoExit]
[-NoLogo]
[-NonInteractive]
[-NoProfile]
[-OutputFormat {Text | XML}]
[-PSConsoleFile <FilePath> | -Version <PowerShell version>]
[-Sta]
[-WindowStyle <style>]
PowerShell[.exe] -Help | -? | /?
Example from my laptop
Passing arguments through Start-Process
If you are using Start-Process then you can pass an array of arguments through a comma delimited string.
PS C:\> Start-Process -FilePath "$env:comspec" -ArgumentList "/c dir `"%systemdrive%\program files`""
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6
I discovered that PowerShell is pretty similar to python and bash with variables. This runs as a script that I then attach to Task Scheduler.
$msbuild = "C:\Program Files\Google Apps Directory Sync\sync-cmd.exe"
$arguments = "-a -o -c config.xml"
start-Process -FilePath $msbuild $arguments
I want to write a powershell script that sets up a development environment. Firstly, I want to launch two command prompts which are running yarn run dev:client and yarn run dev:server respectively.
I have tried start cmd and Start-Process cmd -Argument yarn,run,dev:server, but am unable to get the newly launched command prompt to run the command.
How do I do this?
The generic way is:
cmd /c "insert_your_command_here"
This means in your case you would execute:
cmd /c "yarn run dev:client"
cmd /c "yarn run dev:server"
What about:
$arg="run dev:server"
Start-Process -FilePath path_to_yarn -Args $arg -passthru -RedirectStandardError err.log