I have the following bit of code-
Set-Location "$PSCommandPath"
Write-Host "Starting script."
Write-Host "Current directory is... $PSCommandPath"
Which just returns-
Starting script.
Current directory is...
How do I remedy this?
If I had to guess, you are running an older version of PowerShell that does not support $PSCommandPath. The variable is only available in versions 3.0 and newer. From the documentation:
$PSCommandPath
Contains the full path and name of the script that is being run.
This parameter is valid in all scripts. This automatic variable is
introduced in Windows PowerShell 3.0.
So, like all undefined variables, $PSCommandPath is being treated as $null:
PS > ($undefined).GetType()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ ($undefined).GetType()
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
PS >
PS > $var = 123
PS > Write-Host "My variable: $var"
My variable: 123
PS > Write-Host "My variable: $undefined"
My variable:
PS >
To fix the problem, you need to upgrade PowerShell to version 3.0 or newer.
Also, it seems like you actually want Get-Location, which returns the current working directory:
Write-Host "Current directory is... $(Get-Location)"
Related
I've read several similar posts but they focus on calling a PS script from within another PS script. I can do that and make the other script run, my issue is most likely linked to $MyInvocation when calling a script from another script.
Background
I have a script that half-way through needs to call another script. This other script cannot be a psm1 module because it is used as a standalone script in other processes. I begin the script with
$ScriptDir = (split-path -parent -path $MyInvocation.MyCommand.Path)
Problem
I then run
& "$ScriptDir\Another Script.ps1"
This throws the following error
Set-Location : A positional parameter cannot be found that accepts argument 'C:\Users\MyUser\Desktop\Scripts'.
At C:\Users\MyUser\Desktop\Scripts\Another Script.ps1:30 char:1
+ Set-Location = $ScriptDir
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Location], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Here's the full section of the Another Script.ps1 that is failing
#Requires -RunAsAdministrator
$ErrorActionPreference = "Stop"
$ScriptDir = (split-path -parent -path $MyInvocation.MyCommand.Path)
Set-Location = $ScriptDir
My guess is that the Set-Location does not work because it is currently running a script inside another script. The problem I have is that this part needs to be there in order for Another Script.ps1 to run as a standalone script as well. Are there any workarounds for this, such as ignoring this step if it's run from another script?
References
https://paulcunningham.dev/powershell-invoke-expressions-spaces-in-path/
Invoke-Expression: Positional parameter cannot be found that accepts argument /s
Call PowerShell script PS1 from another PS1 script inside Powershell ISE
Powershell: A positional parameter cannot be found that accepts argument "xxx"
I can't believe I missed it: Set-Location should not have an equal sign.
It currently says
Set-Location = $ScriptDir
When it should say
Set-Location $ScriptDir
I have a folder at C:\Folder that has files input.xml, output.xml and licensegenerator.exe. Licensegenerator.exe takes variables that we put into input.xml and creates a temporary license for one of our programs using the output.xml file. We typically do this via command line by navigating to the C:\Folder directory, then running the command:
LicenseGenerator.exe "C:\Folder\input.xml" "C:\Folder\output.xml"
I'm attempting to write a script to do the exact same thing in PowerShell, but I'm struggling... Here's what I have:
$inputtest = "C:\Folder\Input.xml"
$outputtest = "C:\Folder\Output.xml"
$licensegen = "C:\Folder\LicenseGenerator.exe"
Invoke-Command $licensegen "$inputtest" "$outputtest"
When I run this, I get the error:
Invoke-Command : A positional parameter cannot be found that accepts argument
'C:\Folder\Output.xml'.
At line:5 char:1
+ Invoke-Command $licengegen "$inputtest" "$outputtest"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
I have also tried running with Invoke-Expression but get the exact same error (except it says "Invoke-Expression" at the beginning). Anybody have any idea what I'm doing wrong here?
You're looking for the call operator (&):
& $licensegen "$inputtest" "$outputtest"
Invoke-Command is essentially for running scriptblocks on other hosts and/or in other user contexts.
Start-Process
is great because you can runas, redirect output, hide the child processes window and much more.
Start-Process -FilePath $licensegen -Argumentlist $inputtest,$outputtest
& "[path] command" [arguments]
Just replace Invoke-Command with &
It appears that PowerShell 2.0 cannot handle a space in the Env:PSModulePath variable when looking for a module. I have the function in a .psm1 file in a directory under the "\ORGHOST\USRSHR\USERS\lit\My Documents\WindowsPowerShell\Modules" directory.
My organization requires that my Windows document directory be on a network share. This causes the $Env:PSModulePath variable to have "My Documents" as part of the path in the first entry. No, I cannot change the policies set by the organization.
It sounds like I should iterate over the paths in $Env:PSModulePath and find the short (8.3) name for each, then set $Env:PSModulePath using those in my profile script. I would welcome a better suggestion. Any ideas?
If anyone could confirm that this is a problem in PowerShell 2.0, that would be helpful in pushing the organization to upgrade to PowerShell 5.0.
PS 5.0
PS C:\src\powershell> $Env:PSModulePath -split ";"
\\ORGHOST\ORGSHR\Users\lit\My Documents\WindowsPowerShell
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\system32\WindowsPowerShell\v1.0\Modules
PS 2.0
PS C:\Users\lit> $Env:PSModulePath -split ";"
\\ORGHOST\ORGSHR\USERS\lit\My Documents\WindowsPowerShell\Modules
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\
The term 'Phs-RunBat' 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 \\ORGHOST\USRSHR\Users\lit\Scripts\PSAutomation\Phs-RunRemoteBat.ps1:17 char:23
+ [int32]$r = Phs-RunBat <<<< -ComputerName $ComputerName -ScriptPath $ScriptPath -LogFile $LogFile -Verbose
+ CategoryInfo : ObjectNotFound: (Phs-RunBat:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I've been working on and off on a project to compress and move files older than x days to an archival folder. I've retrofitted the script here: https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Compress-Log-121e63b5 to assist me however I'm running into an issue that has proved fairly annoying.
When I run this on my machine, utilizing local directories, the script completes as expected. However, when I pass networked file paths to the script, the Get-WmiObject query begins returning null results.
For example, this is a sample command line that works:
powershell -executionpolicy remotesigned -File compress_and_move_files.ps1 c:\temp\ c:\temp\compress_test\ 14
When I move to a UNC path, I begin getting the null-valued expression error on the WMIQuery.Compress() call
powershell -executionpolicy remotesigned -File compress_and_move_files.ps1 \\server1\temp\ \\server1\temp\compress_test\ 14
This is the full error:
You cannot call a method on a null-valued expression.
At compress_and_move_files.ps1:14 char:23
+ If ($WMIQuery.Compress <<<< ()) {Write-Host "$FullName compressed successfull
y."-ForegroundColor Green}
+ CategoryInfo : InvalidOperation: (Compress:String) [], RuntimeE
xception
+ FullyQualifiedErrorId : InvokeMethodOnNull
That script attempts to retrieve a CIM_DataFile instance - a class that isn't accessible via UNC paths in WMI.
Change the script to target the remote computer and then use the local file system path:
$Server = "server1"
$WMIFile = "C:\temp\".Replace("\", "\\")
$WMIQuery = Get-WmiObject -Computer $Server -Query "SELECT * FROM CIM_DataFile WHERE Name='$WMIFileName'"
I am attempting to redirect output of a Powershell script to a txt file.
In the Powershell window, I try:
.\script.ps1 > list.txt
But it does not help, all output still gets printed to the window.
I then tried:
.\script.ps1 >& list.txt
And got this error:
Missing file specification after redirection operator.
At line:1 char:21
+ .\script.ps1 > <<<< & list.txt
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingFileSpecification
If you are writing output in script.ps1 using Write-Host (or [Console]::WriteLine) you will either need to change those to Write-Output or do this:
powershell.exe -File test.ps1 > out.txt
By the way > is syntactic sugar for Out-File, they are the same thing.
If the output you're wanting to capture is being written to the console using Write-Host, you need to change that to Write-Output.
You don't need the & after the >. It is only used to execute something.
.\script.ps1 > list.txt
If script.ps1 is outputting using Write-Host or [Console]::WriteLine you will need to update it.
Here is an example of updating a Write-Host script to be outputable.