问题
I have users provide an input txt file as an argument -InputFile
which I store as $inputfile
. But when I try:
$reader = [System.IO.File]::OpenText("$inputfile")
PowerShell automatically appends the $inputfile
path to C:\Windows\system32. How can I have PowerShell not assume a path prefix, so a user could simply pass -InputFile inputfile.txt
if the file they want is in the same directory from which they run the script? How can I also support them enumerating a completely different path to the file if it's outside of the current directory without having it automatically append to C:\Windows\system32?
EDIT: Changed the variable "$input" to "$inputfile" per your advice.
回答1:
Use Resolve-Path for resolving the path before/when you pass it to OpenText()
:
$reader = [IO.File]::OpenText((Resolve-Path $InputFile).Path)
Since Resolve-Path
throws an exception when it can't resolve a path you may want to run this in a try..catch
block, e.g. like this:
try {
$path = (Resolve-Path $InputFile).Path
$reader = [IO.File]::OpenText($path)
} catch [Management.Automation.ItemNotFoundException] {
# cannot resolve path
} catch {
# other error
}
or, better yet, validate the parameter:
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path -LiteralPath $_ -Type Leaf})]
[string]$InputFile
回答2:
First: Be aware that $input
is a special variable in PowerShell. See help about_Automatic_Variables
for more information. (You don't put enough context in your question for me to know whether you're using that variable properly or not.)
Second, .NET objects don't assume the same working location as PowerShell. They can't, because PowerShell has "drives" other than file system drives. If you're sure you're in the file system, you can use something like this:
$fullPath = Join-Path (Get-Location).Path $inputFilenameFromUser
Cmdlets will use the working location.
回答3:
First, don't use $input
as a variable name; it's an automatic variable so it could be overwritten or have unexpected results.
Second, are you sure that the "current" directory is not C:\Windows\System32
? The working directory is not necessarily (and often isn't) the path where the script is.
If you want it to always use the script directory instead of the working directory, but only when the path is relative, then you have to do some coding to make sure (note I'm replacing your $input
variable with one called $Path
):
if (($Path | Split-Path -IsAbsolute)) {
$reader = [System.IO.File]::OpenText($Path)
} else {
$myPath = $PSScriptRoot | Join-Path -ChildPath $Path
$reader = [System.IO.File]::OpenText($myPath)
}
回答4:
First I'd like to second what everybody else has said: that you should not be using $Input
as your variable name since that is an automatic variable.
Aside from that I'd like to offer you an alternative. Personally I keep a function around that will pop up an Open File dialog box when I want people to specify an input file.
Function Get-FilePath{
[CmdletBinding()]
Param(
[String]$Filter = "All Files (*.*)|*.*|Comma Seperated Values (*.csv)|*.csv|Text Files (*.txt)|*.txt",
[String]$InitialDirectory = "C:\",
[String]$Title)
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $InitialDirectory
$OpenFileDialog.filter = $Filter
$OpenFileDialog.Title = $Title
[void]$OpenFileDialog.ShowDialog()
$OpenFileDialog.filename
}
Then you could just do something like
$InputFilePath = Get-FilePath
That would give you the full path to the file as a string.
来源:https://stackoverflow.com/questions/41577526/how-can-i-read-file-input-without-any-pre-defined-path-in-powershell