Resolve conflict between two commands with the same name - powershell

I run PowerShell on Windows 10 and uses mingw and WinAVR side by side.
I want to use both make provided by mingw and WinAVR. (For some reason using mingw's make causes problems when working with Arduino code.)
But I can't add both C:\WinAVR-20100110\utils (contains WinAVR make) and C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin to paths because they have executables with the same name.
Can I do something like, prepending every command provided by WinAVR by avr (make to avr-make)? Or is there another walk around?

You can:
add the directory of the one executable that you do want to invoke as make to your $env:Path (first) - C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
define the other as an alias, by adding the following to your $PROFILE file:
Set-Alias avr-make C:\WinAVR-20100110\utils\make.exe
Note that alias have higher precedence than executables.
See about_Aliases and about_Command_Precedence.
If you want to define such aliases for all executables in a given directory, use the following approach:
Get-Item C:\WinAVR-20100110\utils\*.exe | ForEach-Object {
Set-Alias ('avr-' + $_.BaseName) $_.FullName
}

Related

Command "docker" not recognized in windows powershell

I am using Windows Powershell (on windows 10). I am also using the latest version 2.3.0.5 of docker desktop. When I type "docker version" in powershell the command is not recognized. The error message reads "Der angegebenen Datei ist keine Anwendung zugeordnet." (English: No application is assigned to the specified file). When I instead include the file extension and type "docker.exe version" the command can be executed. The interesting thing is that "docker version" works in a cmd window, but for some reason not in powershell. The extension ".exe" is contained in the windows environment variable PATHEXT.
What could be the reason that it doesn't work in powershell?
PS: I had an old version of docker installed before. There everything worked fine. Then I updated to the newest version. After that I couldn't use my existing docker containers anymore. So I uninstalled the old version and installed version 2.3.0.5. Since then I have this issue.
tl;dr:
Run Get-Command -All docker | ForEach-Object Path
Among the file paths returned, remove those that do not end in *.exe (use Remove-Item).
The likeliest explanation is that, in one of the directories in your system's path ($env:PATH) that comes before the one in which docker.exe is located, contains another file whose base name is docker:
Either: It is an extension-less file literally and fully named docker [This is what it the problem turned out to be] .
PowerShell unexpectedly tries to execute this extension-less file, because it considers it executable, despite - by definition - not having an extension designated as executable via the PATHEXT environment variable ($env:PATHEXT).[1]
This would explain cmd.exe's different behavior, because it sensibly never considers an extension-less file executable.
Presumably, the uninstallation of the old Docker version removed the original docker.exe, but left an extension-less docker file in the same directory behind (possibly a Unix shell script).
Or: It does have an extension (other than *.exe), which:
refers to a file that isn't directly executable and needs an interpreter - a separate executable - in order to be executed
and that extension is listed in the PATHEXT environment variable
and the association between the filename extension (e.g., .py) and the (information about the) associated interpreter is (now) missing, possibly as a result of having uninstalled the older Docker version.
[1] In fact, PowerShell unexpectedly considers any filename extension executable - see GitHub issue #12632.
However, for those extensions not listed in PATHEXT, execution via the path only works if you include the filename extension in a file-name-only call (e.g., executing file.txt opens a file by that name located in the first folder in the path that has such a file in the associated editor). With an extension-less file, there is obviously no extension to include, which is why confusion with an *.exe file of the same base name is possible (unless you invoke with .exe); if both such files reside in the same directory in the path, the *.exe file takes precedence, but if the extension-less file is in a different directory listed earlier in the path, it takes precedence.

Windows Powershell Basic Questions - new user

When trying to open a file with text editor VIM, I am unable to open the file unless VIM (shortcut) is in my current working directory. As an example, I am able to write start firefox to open a firefox window. However, start vim C:\filepath\filename.txt does not work unless a vim shortcut is in my current directory. How do I get around this?
Also, is there a way to have a program execute a file in the current working directory without having to reference the entire file path? For example instead of Start-Process vim C:\Users\User\Desktop\File\file.txt is there an available path shortcut like Start-Process vim ~\file.txt with ~ representing the current working directory?
The OS need to determine the full path of the exe, no matter what.
There's 2 ways that it will happen.
You're calling the executable from it's working directory
The executable location is in the Windows environment variable.
You can view the PATH variable content through this simple statement
$env:Path -split ';' | sort
You sill see that the Firefox path is listed there, but not the one from VIM.
That's why the former can be started by it's executable name and the latter require the full path.
You need to add VIM directory to your PATH variable if you want to be able to call it just by typing vim
Otherwise, if you have restricted access or don't want to edit that variable, you can also set a $vim variable, then invoke it whenever you want to call the executable.
Regarding the second part of your question
Powershell use the dot as a reference to the current directory .\file.txt.
You can also just specify the filename without anything else file.txt.
Both backslash \ & slash / work for filepath so .\file.txt and ./file.txt are both valid ways to reference the file.
Use ..\ to reference the parent directory (e.g. ..\file.txt)
$Vim = "c:\Path\To\Vim.exe"
& $vim "file.txt"
& $vim ".\file.txt"
#Forward slash also work for paths
& $vim "./file.txt"

Powershell file path with space, multiple drives

I'm trying to use the call operator (&) to run an R script, and for some reason I am unable to direct to the right path on the D:\ drive, but it works fine on the C:\ drive (copied the R folder from D:\ to C:\ for testing).
The D:\ drive error appears like a space error, even though there are quotes around the string/variable.
Double spacing between "Program" and "Files", the call command reads correctly.
Ideally I would like to call to Rscript.exe on the D:\ drive, but I don't know why it's giving me an error - especially when the C:\ drive works fine and double spacing reads correctly.
Also worth noting "D:\Program Files (x86)" doesn't read correctly either, with similar symptoms.
Update: running
gci -r d:\ -include rscript.exe | % fullname
returns:
D:\Program Files\R\R-3.2.3\bin\i386\Rscript.exe
D:\Program Files\R\R-3.2.3\bin\x64\Rscript.exe
D:\Program Files\R\R-3.2.3\bin\Rscript.exe
The last of which is what my variable $RscriptD is set to.
The first error message in your image is:
Rscript.exe : The term 'D:\Program' is not recognized as an internal or external command
This message means that the call operator (&) called Rscript.exe but Rscript.exe failed to do something by using 'D:\Program'.
I don't know exactly the details of internal process of Rscript.exe, however, I think Rscript.exe tried to run D:\Program Files\R\R-3.2.3\bin\i386\Rscript.exe or D:\Program Files\R\R-3.2.3\bin\x64\Rscript.exe but could not handle the whitespace of Program Files. Because the manual says:
Sub-architectures are also used on Windows, but by selecting executables within the appropriate bin directory, R_HOME/bin/i386 or R_HOME/bin/x64. For backwards compatibility there are executables R_HOME/bin/R.exe and R_HOME/bin/Rscript.exe: these will run an executable from one of the subdirectories, which one being taken first from the R_ARCH environment variable, then from the --arch command-line option and finally from the installation default (which is 32-bit for a combined 32/64 bit R installation).
According to this, I think it is better to call directly i386/Rscript.exe or x64/Rscript.exe rather than bin/Rscript.exe which is just for backwards compatibility.

Creating files at PSModulePath in batch

I am currently trying to write a batch program that installs a module named SetConsolePath.psm1 at the correct location. I am a beginner with Batch and I have absolutely no powershell experience.
Through the internet, I have learned how to display PSModulePath with powershell -command "echo $env:PSModulePath.
How can I, via .bat file, move SetConsolePath.psm1 from the desktop to the location displayed by powershell -command "echo $env:PSModulePath?
Thank you in advance, and I apologize for my lack of experience.
Before I answer, I must out that you do not want to copy PowerShell module files directly to the path pointed by PsModulePath. You really want to create a folder inside PSModulePath and copy the files there instead.
The prefix env in a Powershell variable indicates an environment variable. $env:PSModulePath is actually referring to the PSMODULEPATH environment variable. On the command line, and in batch files, environment variables can be displayed by placing the name between percent symbols. (In fact, you could have displayed this value by typing echo %PSMODULEPATH% instead.)
To reference the desktop folder, have a look at this answer, which shows you how to use another environment variable, USERPROFILE.
Therefore, to copy the file from the desktop directory to the path specified in PSModulePath, you would do this:
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%"
And, as I warned earlier, you really should copy the file to a folder underneath PsModulePath. So what you really want is:
IF NOT EXIST "%PSMODULEPATH%\MyNewFolder" MKDIR "%PSMODULEPATH%\MyNewFolder"
COPY "%USERPROFILE%\Desktop\SetConsolePath.psm1" "%PSMODULEPATH%\MyNewFolder"

ssh-keygen: The System Cannot Find the Path Specified

ssh-agent, ssh-add all works on Cmder running PowerShell/Posh-Git
I have added C:\Program Files\Git\usr\bin Environment Variables
ssh-keyen works fine on Git Bash,
how can I make ssh-keygen to also work with Powershell/Posh-Git ?
EDIT:
It turns out that the error is due to the fact that ssh-keygen in PowerShell is running the ssh-keygen.bat file instead of ssh-keygen.exe
So setting an alias as mention below is the way to go.
I use Set-Alias instead of New-Alias because New-Alias requires me to reset my $profile every now and then, which is weird.
To reset, type . $profile
One way to do this is to add it to your path.
Unfortunately, there appears to be no way to add only the executable. In other words, you will be required to add the whole bin folder (namely C:\Program Files\Git\usr\bin) to your path.
I can show you how to add the whole directory to the path, but I don't think this is what you want. Instead, below is an alternative method that only adds the ssh-keygen.exe executable.
Navigate to $env:homepath\Documents\WindowsPowerShell (create it if you don't have it).
Create a file called profile.ps1.
Add to the file the following line of code.
New-Alias Ssh-Keygen "C:\Program Files\Git\usr\bin\ssh-keygen.exe"
Now, each time you launch Powershell, Ssh-Keygen will be available. It even works with tab completion (e.g. type ssh- and press tab, then it automatically becomes Ssh-Keygen).
Actually, you can add single executables from the git bin folder to your path by symlinking them into a folder that is contained in your path variable.
I also wanted to use some of the git tools inside powershell but I didn't want to load the git-bin-folder into path every time I wanted to use one of the tools and I also didn't want to overwrite tools like cp, find, ls and so on...
Create a folder that you can add to path. I created mine in C:\dev\bin and added it to the path variable.
Then you need to symlink all the dll-files from the git bin folder to your new bin folder because the tools you'll link need them in the same directory (the runpath won't be the git-bin-dir but the new bin-dir). I'll add a Script to do that below.
And finally you just need to create symlinks for all tools you'd like to use in powershell as well (hint: ssh.exe is really nice to use in powershell ;))
Here are my powershell functions that'll help you set up your new bin-folder with all the nice tools from git:
# generic symlink function
function Create-Symlink {
param(
[string]$link,
[string]$target
)
& cmd.exe /c mklink "$link" "$target"
}
# symlink all teh git dlls
function Create-GitDllSymlinks {
param(
[string]$newBinDir='C:\dev\bin',
[string]$gitBinDir='C:\Program Files (x86)\Git\bin'
)
$dlls = gci $gitBinDir -Filter *.dll
$dlls | foreach {
Create-Symlink -link (join-path $newBinDir $_.Name) -target $_.FullName
}
}
# to easily link your git tools
function Create-GitSymlink {
param(
[string]$executable,
[string]$newBinDir='C:\dev\bin',
[string]$gitBinDir='C:\Program Files (x86)\Git\bin'
)
if (-not $executable.EndsWith('.exe')) {
$executable = ($executable + '.exe')
}
Create-Symlink -link (join-path $newBinDir $executable) -target (join-path $gitBinDir $executable)
}
# create all dll symlinks needed
Create-GitDllSymlinks
# link ssh and ssh-keygen to use in powershell
Create-GitSymlink -executable ssh-keygen
Create-GitSymlink -executable ssh
Another nice thing to do is this:
create a bash.bat file in your new bin-folder
write this into that .bat file:
"C:\Program Files (x86)\Git\bin\sh.exe" --login -i
quickly switch between powershell and bash:
when in powershell, type bash and git-bash will start inside the same window with access to all git tools in the git-bin-folder.
want to go back to powershell? just type exit!
Edit:
I reinstalled my computer a few days ago (with Win 10) and ran into some issues with my solution above. Apparently, git and/or the cygwin environment in git has been updated and the cygwin applications now search for their unix-environment-paths differently.
For example, ssh always said that it couldn't find my home path:
Could not create directory '/home/myuser/.ssh'.
The authenticity of host 'hostx (IP)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxx.
Are you sure you want to continue connecting (yes/no)?
Using procmon I found out, that it was looking for files in c:\etc and c:\home\myuser. Setting environment variables like HOME or USERPROFILE didn't work, so I just made two additional symlinks to satisfy my cygwin tools:
PS bin # cmd /c mklink /D C:\etc "C:\Program Files\Git\etc"
symbolic link created for C:\etc <<===>> C:\Program Files\Git\etc
PS bin # cmd /c mklink /D C:\home "C:\Users"
symbolic link created for C:\home <<===>> C:\Users
I solved the problem by generating my own ssh key pair using command
$ ssh-keygen -t rsa -C "your_email#mail.com"
in powershell. If you already have a SSH key, then don't a generate new key, as they will be overwritten. You can use ssh-keygen command, only if you have installed Git with Git Bash.
When you run the above command, it will create 2 files in the ~/.ssh directory.
~/.ssh/id_rsa − It is private key or identification key.
~/.ssh/id_rsa.pub − public key
See link generate ssh key