Run two or more apps via powershell with one command - windows

this is my `user_profile.ps1' file with my alias list
# some data here
Set-alias idea 'C:\users\user\appdata\local\jetbrains\toolbox\apps\idea-c\ch-0\213.5744.223\bin\idea64.exe'
Set-Alias obsidian 'C:\Users\user\AppData\Local\Obsidian\Obsidian.exe'
Set-Alias brave 'C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe'
# and there
is possible to create "super alias" for this three (or more) apps to run it with one alias like when I type something like superalias and this run three (or more) apps. Maybe you know or other possibility instead of Set-Alias
P.S.
this doesn't work:
Set-Alias superalias 'C:\users\user\appdata\local\jetbrains\toolbox\apps\idea-c\ch-0\213.5744.223\bin\idea64.exe', 'C:\Users\user\AppData\Local\Obsidian\Obsidian.exe', 'C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe'

An alias in PowerShell can only refer to one other command name or path - it is simply an alternative (usually shorter) name for another command.
In order to invoke multiple commands you need a function (adjust the name as needed):
function superalias {
& 'C:\users\user\appdata\local\jetbrains\toolbox\apps\idea-c\ch-0\213.5744.223\bin\idea64.exe'
& 'C:\Users\user\AppData\Local\Obsidian\Obsidian.exe'
& 'C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe'
}
Note the need to use &, the call operator, to invoke the external programs, which is a syntactic necessity because their paths are quoted (the same would apply if the paths contained variable names or expressions).
These external programs will launch sequentially, and any among them that are console applications will run synchronously, i.e. block further execution until they exit.

Related

Why does a Perl script that is run from PowerShell run in a new console, but a Python script does not?

For both file associations, .py and .pl, I have a pair of ftype and assoc so that I can run Perl and Python scripts without explicitely specifying the path to their respective interpreter executable, like so:
C:\users\rene> .\abc.pl
C:\users\rene> .\xyz.py
When I do the "same" in a PowerShell console, executing the Perl Script opens another console in which it executes, yet the Python script executes in the same console.
Because the Perl Script runs in another console, I am faced with two problems: 1) I cannot redirect STDOUT of the script and 2) the console closes when the script is done, thus I cannot see its output.
I have no idea why the Python script behaves differently from the Perl script and I wonder what I need to change in order for the Perl script to run in the same console when executed in PowerShell.
Assuming that the .pl filename extension is associated with a file type that uses a console application to perform the Open verb on that file type (run ($fileTypeName = cmd /c assoc .pl) to learn the file-type name, then cmd /c ftype $fileTypeName to see its definition):
In order for PowerShell to run files with a given filename extension in the current console window, synchronously (assuming they're associated with a console application), that extension must be listed in the system-defined $env:PATHEXT environment variable, which is surprising.[1]
You can add .pl to $env:PATHEXT as follows:
For the current session only:
$env:PATHEXT += ';.pl'
Persistently:
Must be run from an elevated session (run as admin), and requires starting a new session to take effect:
[Environment]::SetEnvironmentVariable('PATHEXT',
([Environment]::GetEnvironmentVariable('PATHEXT', 'Machine') + ';.pl'),
'Machine'
)
Note: It is possible - though rare and not advisable - for a persistent user-level definition of this environment variable to shadow the machine-level (all-users) definition. If that is true for your user account, replace 'Machine' with 'User' above.
[1] As you state, the purpose of the $env:PATHEXT environment variable is to list filename extensions that are implicitly executable, so that, with .pl present in the variable, excecuting .\abc.pl can be shortened to .\abc. This aspect is conceptually separate from the file-type associations that allow defining what executable to pass non-executables with given filename extensions to on direct invocation, and it is arguably a bug that PowerShell couples these two aspects; it would make more sense for PowerShell to always run console-based executables in the current window, synchronously.

how to make a Powershell script avaiable from anywhere

I have a Powershell script I would like to make "public", meaning I want to be able to execute the script from any folder as you can do from the command prompt.
Is this possible?
You can also add an alias in your local powershell profile
Alias Example in profile
Set-Alias hello C:\scriptlocation\script.ps1
Now anytime you type hello, the script.ps1 will run.
More info on the various profiles that the alias can be saved to.
https://devblogs.microsoft.com/scripting/understanding-the-six-powershell-profiles/
You can explore the use of your powershell profile to achieve this. See: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles.
If the script is just a function or some variables, you can copy and paste the content into your profile.
Alternatively, if the script represents a standalone unit of code you want to keep separate, you could import it into your main profile as such:
get-content -path C:\blahblahblah\scriptName.ps1 -raw | invoke-expression
Finally, if you are writing an "advanced" powershell function, or are trying to do things officially, you could investigate the use of powershell modules as a way to export your function. See: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_modules
#Lee_Dailey's answer of adding the script to your path is also viable. If you want to add a lot of scripts, one way to do that is to add a folder like C:/PowershellScripts/, to your path, save your scripts there, and then you'll be able to invoke your .PS1 file from anywhere.
Name the script something meaningful ie: awesome.bat Save it in a dir and add the dir to windows env. Command awesome will be globally available.

Are there any fundamental incompatibilities when using a CMD script in a console using PowerShell?

I have an extensive set of CMD scripts for an automation suite.
In a console using CMD.exe, everything works fine. After installing the Windows Creator's update, where PowerShell becomes the new default Windows shell via Explorer's menu options, my scripts break at-random. I can't provide any meaningful code for repro for two main reasons:
No obvious error is occurring; my automated scripts just hang, eventually
The halt isn't even occurring in the same place each time
What I can tell you is that the suite heavily relies on exit codes, use of findstr.exe, and type.
I know things like Windows macros, e.g., %Var% are not compatible, but I was assuming that since the only call I did was to a .bat file, .bat behavior would be the only thing I would need to worry about.
If that's not the case, should my initial .bat be triggering the direct execution of a CMD.exe instance with my parameters? If so, what's the best way to do that, PowerShell-friendly?
eryksun's comments on the question are all worth heeding.
This section of the answer provides a generic answer to the generic question in the question's title. See the next section for considerations specific to the OP's scenario.
Generally speaking, there are only a few things to watch out for when invoking a batch file from PowerShell:
Always include the specific filename extension (.bat or .cmd) in the filename, e.g., script_name.bat
This ensures that no other forms of the same command (named script_name, in the example) with higher precedence are accidentally executed, which could be:
In case of a command name without a path component:
An alias, function, cmdlet, or an external executable / PowerShell script (*.ps1) that happens to be located in a directory listed earlier in the $env:PATH (%PATH%) variable; if multiple executables by the same name are in the same (earliest) directory, the next point applies too.
In case of a command name with a path component:
A PowerShell script (*.ps1) or executable with the same filename root whose extension comes before .bat or .cmd in the %PATHEXT% environment variable.
If the batch file is located in the current directory, you must prefix its filename with ./
By design, as a security measure, PowerShell - unlike cmd.exe - does NOT invoke executables located in the current directory by filename only, so invoking script_name.bat to invoke a batch file of that name in the current directory does not work.[1]
Instead, you must use a path to target such an executable so as to explicitly signal the intent to execute something located in the current directory, and the simplest approach is to use prefix ./ (.\, if running on Windows only); e.g., ./script_name.bat.
When passing parameters to the batch file:
Either: be aware of PowerShell's parsing rules, which are applied before the arguments are passed to the batch file - see this answer of mine.
Or: use --% (the PSv3+ stop-parsing symbol) to pass the remaining arguments as if they'd been passed from a batch file (no interpretation by PowerShell other than expansion of %<var>%-style environment-variable references).
[1] eryksun points out that on Vista+ you can make cmd behave like PowerShell by defining environment variable NoDefaultCurrentDirectoryInExePath (its specific value doesn't matter).
While ill-advised, you can still force both environments to always find executables in the current directory by explicitly adding . to the %PATH% / $env:PATH variable; if you prepend ., you get the default cmd behavior.
As for your specific scenario:
After installing the Windows Creator's update, where PowerShell becomes the new default Windows shell via Explorer's menu options
This applies to the following scenarios:
Pressing Win-X (system-wide keyboard shortcut) now offers PowerShell rather than cmd in the shortcut menu that pops up.
Using File Explore's File menu now shows Open Windows PowerShell in place of Open command prompt (cmd).
However, nothing has changed with respect to how batch files are invoked when they are opened / double-clicked from File Explorer: The subkeys of HKEY_CLASSES_ROOT\batchfile and HKEY_CLASSES_ROOT\cmdfile in the registry still define the shell\open verb as "%1" %*, which should invoke a batch file implicitly with cmd /c, as before.
However, per your comments, your batch file is never run directly from File Explorer, because it require parameter values, and it is invoked in two fundamental ways:
Explicitly via a cmd console, after entering cmd in the Run dialog that is presented after pressing Win-R (system-wide keyboard shortcut).
In this case, everything should work as before: you're invoking your batch file from cmd.
Explicitly via PowerShell, using File Explorer's File menu.
Per your comments, the PowerShell console may either be opened:
directly in the directory in which the target batch file resides.
in an ancestral directory, such as the root of a thumb drive on which the batch file resides.
In both cases, PowerShell's potential interpretation of arguments does come into play.
Additionally, in the 2nd case (ancestral directory), the invocation will only work the same if the batch file either does not depend on the current directory or explicitly sets the current directory (such as setting it to its own location with cd /d "%~dp0").
This is a non-answer solution if encountering the question's specific behavior. I've verified all my halting scripts stopped halting after implementing a shim-like workaround.
As erykson said, there doesn't appear to be a reason why using a shim would be required. The goal is then to explicitly launch the script in CMD when using PowerShell, which aligns with Jeff Zeitlin's original suggestion in the question's comments.
So, let's say you're in my shoes with your own script_name.bat.
script_name.bat was your old script that initializes and kicks off everything. We can make sure that whatever was in script_name.bat is correctly run via CMD instead of PowerShell by doing the following:
Rename script_name.bat to script_name_shim.bat
Create a new script_name.bat in the same directory
Set its contents to:
#echo off
CMD.exe /C "%~dp0script_name_shim.bat" %*
exit /b %errorlevel%
That will launch your script with CMD.exe regardless of the fact that you started in PowerShell, and it will also use all your command-line arguments too.
This looks like a chicken egg problem, wihtout knowing the code it's difficult to tell where the problem is.
There are a ton of ways to start batches with cmd.exe even in win10cu.
Aliases are only a problem when working interactively with the PowerShell console and expecting behavior as it used to be in cmd.exe.
The aliases depend also on the loaded/imported modules and profiles.
This small PowerShell script will get all items from Help.exe and
perform a Get-Command with the item.
internal commands without counterparts in PoSh are filtered out by the ErrorAction SilentlyContinue.
Applications (*.exe files) are assumed identical and removed by the where clause.
help.exe |
Select-String '^[A-Z][^ ]+'|
ForEach-Object {
Get-Command $_.Matches.Value -ErrorAction SilentlyContinue
}| Where-Object CommandType -ne 'Application'|Select *|
Format-Table -auto CommandType,Name,DisplayName,ResolvedCommand,Module
Sample output on my system, all these items will likely work differently in PowerShell:
CommandType Name DisplayName ResolvedCommand Module
----------- ---- ----------- --------------- ------
Alias call call -> Invoke-Method Invoke-Method pscx
Alias cd cd -> Set-LocationEx Set-LocationEx Pscx.CD
Alias chdir chdir -> Set-Location Set-Location
Alias cls cls -> Clear-Host Clear-Host
Alias copy copy -> Copy-Item Copy-Item
Alias del del -> Remove-Item Remove-Item
Alias dir dir -> Get-ChildItem Get-ChildItem
Alias echo echo -> Write-Output Write-Output
Alias erase erase -> Remove-Item Remove-Item
Alias fc fc -> Format-Custom Format-Custom
Function help pscx
Alias md md -> mkdir mkdir
Function mkdir
Function more
Alias move move -> Move-Item Move-Item
Function Pause
Alias popd popd -> Pop-Location Pop-Location
Function prompt
Alias pushd pushd -> Push-Location Push-Location
Alias rd rd -> Remove-Item Remove-Item
Alias ren ren -> Rename-Item Rename-Item
Alias rmdir rmdir -> Remove-Item Remove-Item
Alias set set -> Set-Variable Set-Variable
Alias sc sc -> Set-Content Set-Content
Alias sort sort -> Sort-Object Sort-Object
Alias start start -> Start-Process Start-Process
Alias type type -> Get-Content Get-Content

Location of Command Prompt Commands

Where are the commands located for Command Prompt? I know this is possible in Linux, but what about windows?
I want to rename certain commands so I can make my own using the original name.
Im doing this on a 32bit Windows XP if that helps.
More specifically, where can I find the tree command?
https://superuser.com/questions/312926/windows-equivalent-of-which-command-in-linux
in windows 7 there's the where command.
You can overwrite the standard commands, but this will break a lot of stuff.
You would also have to modify your path environment variable
in windows 7 tree is located in C:\Windows\System32\tree.com
This might be a useful site for you
http://ss64.com/nt/
Use a bat file of the same name to override an inbuilt external command. Some commands are internal so you have to specify .bat. Also if calling the overridden program specify the extension.
There are two types of commands in Windows command prompt. The internal commands are built-in inside the command processor program, that is called cmd.exe. You may inspect such commands if you open cmd.exe file with an Hex editor, or even directly with Notepad (although doing that requires a lot of patience!); to know the location of cmd.exe file, type: set comspec. Examples of internal commands are DIR, COPY, TYPE, MD, etc. (the simplest ones) and all Batch-file commands, like GOTO, IF, FOR, REM, etc. There is no way to change the name of an internal command, unless you modify the cmd.exe file (for example, using the same Hex editor) that, although possible, is NEVER recommended!!!
The external commands reside in disk files with .com or .exe extension that are grouped in certain subdirectories, usually in C:\Windows\System or C:\Windows\System32; these subdirectories must appear in %PATH% variable in order to execute the external commands directly in the command prompt. You may locate the folder where an executable file resides using the following command, that review folders included in PATH variable only (you can not use wild-cards in this case):
for %a in (tree.com tree.exe) do #echo/%~$PATH:a
You may directly change the name of any command-name.exe file; however, this practice is not recommended. A simpler option is create a Batch file with the same name of a standard command (and .bat extension) and place it in a folder that will be included in PATH variable before the standard commands folder (or in the current directory). For example, create a file named tree.bat and place it in C:\Users\MyName\MyCommands; then, modify PATH variable this way: path=C:\Users\MyName\MyCommands;C:\Windows;C:\Windows\System32. If you need to use the standard tree command inside your tree.bat file, just include the proper extension: tree.com.

How do I create a Powershell alias (or function, or cmdlet) that runs in the same process as my shell?

In Unix, I create a lot of aliases/functions. Here is my workflow:
* I have a file named 'aliases.txt' in my $HOME directory
* I have a quick command to edit that file
* I have an alias named 'sa' that sources that alias file. I.e.
alias sa='. $HOME/aliases.txt
So I can quickly and easily create, modify, and use new aliases.
I'm trying to re-create the same work flow in Powershell and it doesn't work. I've got the aliases.ps1 file in my $HOME directory. I tried creating an 'sa' alias, but of course a Powershell alias can't contain an argument. So I've tried
function sa {. $HOME\aliases.ps1 }
I can run it but changes in my aliases.pl1 file don't get reflected in my shell session. I'm assuming it's because Windows runs the 'sa' function in a new process, while Unix runs functions and aliases in the same process. How can I get my 'sa' back?
(BTW, "Type '. $HOME\aliases.ps1' at the command line each time" is not the answer I'm looking for.
Thanks in advance.
Would
. sa
be terse enough? You just need to dot-source the function call into the current scope. (Note there needs to be a space between the dot and the function name).
What are you trying to do? Some parts of your question doesn't make sense.
Ok, I understand better now.
Import-Alias is exactly for this purpose! Edit the file and do Import-Alias file and you get the new aliases that you have added.
Your flow:
Use the Set-Alias command to setup an alias and add that to your profile or just add that function to profile.
notepad $profile
(add the next in notepad)
function sa {. HOME\aliases.ps1 }
Now sa, should be available and the aliases.ps1 can be setup to use Set-Alias and add the aliases.
You are trying to map what you do in unix EXACTLY to Powershell. You should try and use what powershell has to offer:
Powershell flow:
notepad $profile
(in notepad)
Set-Alias <alias> <command>
Just add Set-Alias command to your profile.
Or use Export-Alias to export into a file and add Import-Alias to import from the file in your profile.
All these are excellently explained here: http://technet.microsoft.com/en-us/library/ee692685.aspx

Resources