"Unable to find specified file" - Powershell - windows

I wrote this function in my powershell profile:
function start {
if ($args[0] == "blender") {
Invoke-Item 'C:\Program Files\Blender Foundation\Blender 2.90\blender.exe'
}
}
It gives me the error below on line 1, at character 1:
Unable to find specified file
The file path is correct, since if I copy and paste the code Invoke-Item ... in my powershell it opens Blender normally. What can the problem be?
Thank you!

This happens, as your function name collides with Start-Process.:
get-alias -Name start
CommandType Name Version Source
----------- ---- ------- ------
Alias start -> Start-Process
Renaming the function is the first step for correction like so,
function start-myApps {
if ($args[0] == "MyApplication") {
Invoke-Item 'C:\Program Files\MyApplication\MyApplication.exe'
}
}
But that isn't enough, as it gives another an error:
Start-MyApps "MyApplication"
= : The term '=' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:2 char:19
+ if ($args[0] == "MyApplication") {
+ ~
+ CategoryInfo : ObjectNotFound: (=:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CommandNotFoundException
This one is caused because Powershell's equality comparison operator is -eq, not ==.
The working version has different name and operator like so,
function start-myApps {
if ($args[0] -eq "MyApplication") {
Invoke-Item 'C:\Program Files\MyApplication\MyApplication.exe'
}
}

Related

How to use Jenkins pipeline variable into powershell or cmd code?

I am in need of modifying a Jenkins Pipeline script. This is a snippet. It works down to the Def in the rename. The error I get is
groovy.lang.MissingPropertyException: No such property: newFileName for class: groovy.lang.Binding
I am looking to inject the version number into the filename which is then processed by a homegrown app to move it where it needs to go and some other stuff. I have tried passing the concatenated ${version} into the Upload executable but it then errors as a literal instead of a variable.
Update: I predefine the variable and get a new error
powershell.exe : newFileName : The term 'newFileName' is not recognized as the name of a cmdlet, function, script file, or operable
At C:\workspace\workspace\Centurion Dashboard#tmp\durable-eb5db1ae\powershellWrapper.ps1:3 char:1
& powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -Comm
CategoryInfo : NotSpecified: (newFileName : T...e, or >operable :String) [], RemoteException
FullyQualifiedErrorId : NativeCommandError
Thoughts?
stage('Rename') {
powershell """
rename-item -Path "C:\\Users\\Administrator\\Documents\\Advanced Installer\\Projects\\Proj\\Setup Files\\SetupCenturionDashboard.exe" -NewName "OtherProject-${version}.exe"
def newFileName = "C:\\Users\\Administrator\\Documents\\Advanced Installer\\Projects\\Proj\\Setup Files\\OtherProject-" + ${version} + ".exe"
echo ${newFileName}
"""
}
stage('Upload') {
bat label: 'Upload', script: 'C:\\Static\\BuildHelper\\BuildHelper.exe ${newFileName} "develop" "home" "${version}"'
}
powershell != groovy
You cannot run groovy inside of powershell block
powershell """
"""
and def newFileName is groovy, that is why you get the error:
The term 'newFileName' is not recognized as the name of a cmdlet...
As you can see, newFileName executable does not exist on windows.
variables on windows
If you just need to pass the version and newFileName variables to your powershell or bat code, you need to use the windows syntax %var% for variables, not the unix ${var} and use global variables if it is possible in your pipeline:
def version = "1.0.0";
def newFileName;
stage('Rename') {
powershell """
rename-item -Path "C:\\Users\\foo.exe" -NewName "OtherProject-%version%.exe"
"""
newFileName = "C:\\Users\\OtherProject-${version}.exe"
}
stage('Upload') {
bat label: 'Upload', script: 'C:\\Static\\BuildHelper\\BuildHelper.exe %newFileName% "develop" "home" "%version%"'
}

Powershell warning and error handling

The following code I am writing to replace a batch script which I have below.
$Script:srcpath = ((Get-Location).Path)
$Script:configure = "$Script:srcpath\qtbase\configure.bat"
if (Get-Item "$Script:srcpath\qtbase\configure.bat" -WarningAction (Write-Warning "$Script:configure not found. Did you forget to run 'init-repository'?")) {
continue
}
I am try to rewrite the qt configure batch script:
set "srcpath=%~dp0"
set "configure=%srcpath%qtbase\configure.bat"
if not exist "%configure%" (
echo %configure% not found. Did you forget to run "init-repository"? >&2
exit /b 1
)
if not exist qtbase mkdir qtbase || exit /b 1
echo + cd qtbase
cd qtbase || exit /b 1
echo + %configure% -top-level %*
call %configure% -top-level %*
set err=%errorlevel%
cd ..
exit /b %err%
The error I am getting in PowerShell is the following:
Get-Item : Cannot bind parameter 'WarningAction' to the target. Exception setting
"WarningAction": "Object reference not set to an instance of an object."
At line:4 char:67
+ ... rningAction (Write-Warning "$Script:configure not found. Did you forg ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Get-Item], ParameterBindingException
+ FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.GetItemCommand
The problem is the error being thrown is erroneous because the warning am calling is what should take its place to tell people that the item doesn't exist. so run "init-repository".
There isn't a good, "if not exist" in PowerShell.
Okay, there is, but it looks like this:
catch [System.Management.Automation.ItemNotFoundException]
which I am having problems with getting to work.
Why am I doing this before someone asks is because I feel that Microsoft will phase out CMD some time it's good to have updated scripts.
Why it's not working
WarningAction does not work like that.
From the about_CommonParameters documentation:
Determines how the cmdlet responds to a warning from the command. "Continue" is the default value. This parameter works only when the command generates a warning message. For example, this parameter works when a command contains the Write-Warning cmdlet.
So, essentially, the value of WarningAction is Continue by default and can be set to Inquire, SilentlyContinue or Stop. The value it is set to determine what action is taken if the Get-item command throws a warning, not what warning to write if Get-item throws a warning.
You can change the preference variable $WarningPreference to set the WarningAction within the current scope, or precede by a scope modifier.
How to make it work
Test-Path
I second Richard's comment to use Test-Path. This will return True or False, depending on whether it finds the file.
if (-not (Test-Path -Path "$Script:srcpath\qtbase\configure.bat")){
Write-Warning 'Does not exist!'
# do other stuff
continue
}else{
Get-Item $configure
}
try/catch
You could try to catch the exception thrown by Get-Item directly in a try/catch. In a similar way to WarningAction, there is ErrorAction which determines what to do if an error is thrown. Terminating error is required, so ErrorAction is set to Stop.
try{
Get-Item $configure -ErrorAction Stop
}catch [System.Management.Automation.ItemNotFoundException]{
Write-Output "Item not found"
# do other stuff
}catch{
Write-Output "Some other error"
$Error[0] # prints last error
}

7Zip Powershell not working

I'm having trouble getting a .7z file to extract via Powershell.
My PowerShell function looks like this:
function unzip($file, $destination)
{
& 'C:\Program Files\7-Zip\7z.exe' x -y $file -o"$destination";
}
I get this error:
7z.exe :
At restoreQA.ps1:26 char:5
+ & 'C:\Program Files\7-Zip\7z.exe' x -y $file -o"$destination";
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Command Line Error:
Too short switch:
-o
There seems to be some sort of parsing error but I've tried every different combination to get it working.
Any ideas on why this is not working?
You need to put -o in quotes:
& 'C:\Program Files\7-Zip\7z.exe' x -y $file "-o$destination"

How to remove partial path from Get-Location output?

I'm trying to write a custom prompt for PowerShell and I was wondering how I would filter out the 1...n directories in the output of Get-Location.
function prompt {
"PS " + $(get-location) + "> "
}
So, if the path is too long I would like to omit some of the directories and just display PS...blah\blah> or something. I tried (get-container) - 1 but it doesn't work.
Use Split-Path with the -Leaf parameter if you want just the last element of a path:
function prompt {
"PS {0}> " -f (Split-Path -Leaf (Get-Location))
}
I wanted to make a more dynamic function. I do just basic string manipulation. You could do some logic nesting Split-Path but the string manipulation approach is just so much more terse. Since what you want to be returned wont be a fully validated path I feel better offering this solution.
Function Get-PartialPath($path, $depth){
If(Test-Path $path){
"PS {0}>" -f (($path -split "\\")[-$depth..-1] -join "\")
} else {
Write-Warning "$path is not a valid path"
}
}
Sample Function call
Get-PartialPath C:\temp\folder1\sfg 2
PS folder1\sfg>
So you can use this simple function. Pass is a string for the path. Assuming it is valid then it will carve up the path into as many trailing chunks as you want. We use -join to rebuild it. If you give a $depth number that is too high the whole path will be returned. So if you only wanted to have 3 folders being shown setting the $depth for 3.
Ansgar Wiechers' answer will give you the last directory but if you want a way to do multiple directories at the end of the filepath (using the triple dot notation) you can cast the directory path to a uri and then just get and join the segments:
function prompt {
$curPath = pwd
$pathUri = ([uri] $curPath.ToString())
if ($pathUri.Segments.Count -le 3) {
"PS {0}>" -f $curPath
} else {
"PS...{0}\{1}>" -f $pathUri.Segments[-2..-1].trim("/") -join ""
}
}
Or using just a string (no uri cast)
function prompt {
$curPath = pwd
$pathString = $curPath.Tostring().split('\') #Changed; no reason for escaping
if ($pathString.Count -le 3) {
"PS {0}>" -f $curPath
} else {
"PS...{0}\{1}>" -f $pathString[-2..-1] -join ""
}
}
$a = prompt
Write-Host $a
Then just change -2 to whatever you want to be the first directory and -le 3 to match. I typically use the uri cast when I have to run stuff through a browser or over connections to Linux machines (as it uses "/" as a path separator) but there is no reason to not use the string method for normal operations.

Multiple statements using && [duplicate]

This question already has answers here:
Can I get "&&" or "-and" to work in PowerShell?
(13 answers)
Closed 9 years ago.
What would be the equivalent statement of CMD's:
dir && cd ..
in Powershell?
I tried:
dir -and cd ..
but it throws error:
Get-ChildItem : A parameter cannot be found that matches parameter name
'and'.
At line:1 char:5
+ dir -and (cd ..)
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell
.Commands.GetChildItemCommand
There is not a direct equivalent in PowerShell of cmd.exe && which means "only execute right-hand side if the left-hand side succeeds." However you could write a short function to do the equivalent:
function IfTrue([ScriptBlock] $testExpression, [ScriptBlock] $runExpression) {
if ( & $testExpression ) { & $runExpression }
}
For example:
IfTrue { get-childitem "fileThatExists.txt" -ea SilentlyContinue } { "File exists..." }
If you want for the $testExpression to produce output, the IfTrue function can be written as follows:
function IfTrue([ScriptBlock] $testExpression, [ScriptBlock] $runExpression) {
& $testExpression
if ( $? ) { & $runExpression }
}
Bill
How about this?
dir; if ($?) {cd ..}
Running get-help about_automatic_variables | more explains:
$? Contains the execution status of the last operation. It contains
TRUE if the last operation succeeded and FALSE if it failed.
In PS, dir is just an alias for get-ChildItem; cd likewise for Set-Location.
edit: Same question here, including an answer straight from the horse's mouth.

Resources