如何使用path作为参数?

时间:2015-09-22 09:08:17

标签: powershell parameters

我想在PS中有一个截图工具。因为我不想重新发明轮子,所以我搜索并在github(https://github.com/mikepruett3/psfetch)找到了一个脚本,我根据自己的需要进行了调整。

现在我想改变行为 - 当脚本启动时没有参数时,它应该在当前目录中截屏。如果用户输入路径(-Path),则应将屏幕截图保存在那里。

我的想法是定义(在我的情况下)$Tarpath并在给出选项时重新定义它。怎么做?

这是我的实际脚本:

# PSFetch.ps1
# A Screenfetch writen in PowerShell
#
# -----------------------------------------------------------
# The Original Inspirations for CMDfetch:
# -----------------------------------------------------------
# screenFetch by KittyKatt
#   https://github.com/KittyKatt/screenFetch
#   A very nice screenshotting and information tool. For GNU/Linux (Almost all Major Distros Supported) *This has been ported to Windows, link below.*
#
# archey by djmelik
#   https://github.com/djmelik/archey
#   Another nice screenshotting and information tool. More hardware oriented than screenFetch. For GNU/Linux
# -----------------------------------------------------------
#

# DONE: Function to Take the Screenshot
Function Take-Screenshot {
    [CmdletBinding()]
    Param(
        [string]$Width,
        [string]$Height,
        [string]$TarPath = "$PSScriptRoot"
    )

    PROCESS {
        [Reflection.Assembly]::LoadWithPartialName("System.Drawing") > $Null

        # Changed how $bounds is calculated so that screen shots with multiple monitors that are offset work correctly
        $bounds = [Windows.Forms.SystemInformation]::VirtualScreen
        # Check Path for Trailing BackSlashes
#           $TarPath = $PSScriptRoot
        if ( $TarPath.EndsWith("\") ) {
            $TarPath = $TarPath.Substring(0,$Path.Length-1)
        }

        # Define The Target Path
        $stamp = get-date -f MM-dd-yyyy_HH_mm_ss
        $target = "$TarPath\screenshot-$stamp.png"

        # Take the Screenshot
        $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
        $graphics = [Drawing.Graphics]::FromImage($bmp)
        $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
        $bmp.Save($target)
        $graphics.Dispose()
        $bmp.Dispose()
    }
}

# DONE: Fix support for Multiple Monitors
# FROM: Shay Levy's Response -     http://stackoverflow.com/questions/7967699/get-screen-resolution-using-wmi-powershell-in-windows-7
$ScreenWidth = 0
$ScreenHeight = 0
Add-Type -AssemblyName System.Windows.Forms
$DisplayCount = [System.Windows.Forms.Screen]::AllScreens.Bounds.Count
$Bounds = [System.Windows.Forms.Screen]::AllScreens | Select-Object -ExpandProperty Bounds

$ScreenWidth = $Bounds | Measure-Object -Property Width -Sum | Select-Object -ExpandProperty Sum
$ScreenHeight = $Bounds | Measure-Object -Property Height -Maximum | Select-Object -ExpandProperty Maximum

$RESOLUTION = "$ScreenWidth x $ScreenHeight"

# Take Screenshot if the Parameters are assigned...
Take-Screenshot -Width $ScreenWidth -Height $ScreenHeight -TarPath $target

修改的 我忘了删除PROCESS-block中的$ tarpath。 从我的第一次测试开始就一直存在......

4 个答案:

答案 0 :(得分:1)

您在函数体中重新定义$TarPath

$TarPath = $PSScriptRoot

这无条件地取代先前分配给参数的任何值。删除该行,您可以传递这样的参数:

Take-Screenshot -TarPath 'C:\some\folder'

或省略参数以使其保持默认值($PSScriptRoot)。

我建议也改行

$target = "$TarPath\screenshot-$stamp.png"

进入这个:

$target = Join-Path $TarPath "screenshot-$stamp.png"

所以你不需要摆弄尾随的反斜杠。

Function Take-Screenshot {
    [CmdletBinding()]
    Param(
        [string]$Width,
        [string]$Height,
        [string]$TarPath = "$PSScriptRoot"
    )

    PROCESS {
        [Reflection.Assembly]::LoadWithPartialName("System.Drawing") > $Null

        # Changed how $bounds is calculated so that screen shots with multiple monitors that are offset work correctly
        $bounds = [Windows.Forms.SystemInformation]::VirtualScreen

        # Define The Target Path
        $stamp = get-date -f MM-dd-yyyy_HH_mm_ss
        $target = Join-Path $TarPath "screenshot-$stamp.png"

        # Take the Screenshot
        $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
        $graphics = [Drawing.Graphics]::FromImage($bmp)
        $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
        $bmp.Save($target)
        $graphics.Dispose()
        $bmp.Dispose()
    }
}

附录:有两种情况,将参数-TarPath的默认值定义为$TarPath = "$PSScriptRoot"不起作用:

  • 该参数被定义为脚本的参数(而不是脚本中的函数),脚本从CMD运行:

    powershell -File 'C:\path\to\script.ps1'
    
  • 该脚本使用PowerShell v2运行。该变量仅在PowerShell v3之前的模块中可用。

在这两种情况下,"$PScriptRoot"都可以替换为$PWD.Path

[CmdletBinding()]
Param(
    [string]$Width,
    [string]$Height,
    [string]$TarPath = $PWD.Path
)

答案 1 :(得分:1)

好的,我自己解决了。

首先[string]$TarPath = "$PSScriptRoot"根本不起作用! 变量始终为空。

但是,我的第一个想法是定义$TarPath并保持不变直到再次定义。结果证明这不起作用。

这是我的解决方案:

# Define The Target Path
Write-Host "Please enter Screenshot-Path"
$TarPath = Read-Host "Else the screenshot will be in $PWD"
if (!$TarPath) {$TarPath = $pwd}

如果在提示符处输入任何内容$pwd将被使用。

答案 2 :(得分:0)

您只需要使用以下任一方法修改脚本的最后一行:

对于默认目录:

Take-Screenshot -Width $ScreenWidth -Height $ScreenHeight

对于自定义目录:

Take-Screenshot -Width $ScreenWidth -Height $ScreenHeight -TarPath "D:\Piyush\temp"

并注释掉PROCESS块中的以下行,因为您不希望使用默认路径覆盖自定义目录路径。

$TarPath = $PSScriptRoot

答案 3 :(得分:0)

嗯,是的,关于它,这种方法会起作用。唯一的问题是,在PROCESS区块中,您再次重新分配了$TarPath,使您的后备机制失效:

$TarPath = $PSScriptRoot

删除该行,它将像魅力一样工作。

此外,您可以添加验证,例如确保参数可以为null,但不能为空,并且必须是有效路径:

[ValidateScript({if ($_){  Test-Path $_}})]
[string]$TarPath = "$PSScriptRoot"

最后一件事,如您所希望的,如您所希望的那样,让用户在通话中使用-Path,您还可以为Param添加别名。

[Alias('Path')]
[ValidateScript({if ($_){  Test-Path $_}})]
[string]$Path = "$PSScriptRoot"