脚本未将变量信息传递到 If、Else、While 或函数中

脚本未将变量信息传递到 If、Else、While 或函数中

我有一个脚本,在我开始将其分解成更小的部分之前,它一直在运行。我注意到,当我尝试使用变量时,信息没有被引入。我必须将该变量复制粘贴到我的 If、Else、While 或其他函数中才能使用它们。我被告知使用 $script: 但据我所知,这只允许变量“报告”出函数以供以后使用。我不需要它只是为了提取信息。

到目前为止我的脚本的细目:

  1. 用户将文件夹放入特定的放置文件夹中。
  2. 脚本检测到新文件并开始运行
  3. 文件夹名称已注明
  4. 所有文件都从其文件夹结构移动到另一个文件夹中。
  5. 然后将所有这些文件转换为单个 .pdf
  6. 该 .pdf 被移动到“已完成文件夹”
  7. 所有空文件夹和文件均被删除。

脚本在启动时运行所有这些,然后静待并观察更新。

我的代码:

#File Locations
$rootPath = 'C:\IT\'
$inLoc = 'Convert Drop'
$prossLoc = 'Processing'
$outLoc = 'Converted PDF'

#File types to include in PDF creation.
$fileTypes = '*.{png,jpeg,jpg,tiff,tif}'

#Function Variables
$inPath  = Join-Path -Path "$rootPath" -ChildPath "$inLoc"
$outPath = Join-Path -Path "$rootPath" -ChildPath "$outLoc"
$runPath = Join-Path -Path "$rootPath" -ChildPath "$prossLoc"
$remove1 = Join-Path -Path "$rootPath" -ChildPath "$($inLoc + "\*")"
$remove2 = Join-Path -Path "$rootPath" -ChildPath "$($outLoc + "\*")"

#Folder Watching Variables
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "$inPath"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true

#Lone Counter
$freshStart = $null
$statusOld  = $null
$pathLoc    = (Get-Item -Path ".\").FullName

#Pulls the last write time of a folder to compare later.
$grabStatus = {$status = Get-Item $pathLoc | Foreach { $_.LastWriteTime } }

#Get PDF name from Folder
$grabFileName = {
    $folder = get-childitem -Path $inPath -Directory -Name
    $fileName = $folder + ".pdf"
}

#Move all nested files to single folder.
$moveFiles = {
    Get-ChildItem -Path $inPath -Recurse -File | Move-Item -Destination $runPath
}

#Convert Nested files into single PDF
$makePDF = {
    & CD $runPath
    & magick "$fileTypes" $fileName
}

#Move final PDF
$moveCmplt = {
    Get-ChildItem -Path $pdf -File | Move-Item -Destination $outPath
}

#Delete Old files
$deleteOld = {
    Remove-Item $remove1 -Recurse -Force
    Remove-Item $remove2 -Recurse -Force
}

#Set compare status to current status then fetches new status.
$stats = {
    $statusOld = $status
    $grabStatus
    sleep 10
}

#Exicute main conversion together.
$action = {
    $grabStatus
    If ($status -eq $statusOld){
        $grabFileName
        $moveFiles
        & CD $runPath
        $grabStatus
        If ($status -eq $statusOld) {
            $makePDF
        }
        Else{
            $stats
        }
        $deleteOld
    }
    Else
    {
        $stats
    }
}

#First Time Start, Then Loop run.
While ($freshStart -eq $null) {
    If ((Get-ChildItem $inPath | Measure-Object).Count -eq 0) {
    }
    Else {
        $action
    }
    $freshStart = "FreshStartDone!"
}

#Scan folder every 5 seconds for new content then run convert on change.
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {sleep 5}

更新代码 它在第一次运行时有效,但是在将所有内容转换为函数后循环就被打破了。

#File Locations
$rootPath = 'C:\IT\'
$inLoc = 'Convert Drop'
$prossLoc = 'Processing'
$outLoc = 'Converted PDF'

#File types to include in PDF creation.
$fileTypes = '*.{png,jpeg,jpg,tiff,tif}'

#Function Variables
$inPath = Join-Path -Path "$rootPath" -ChildPath "$inLoc"
$outPath = Join-Path -Path "$rootPath" -ChildPath "$outLoc"
$runPath = Join-Path -Path "$rootPath" -ChildPath "$prossLoc"
$remove1 = Join-Path -Path "$rootPath" -ChildPath "$($inLoc + "\*")"
$remove2 = Join-Path -Path "$rootPath" -ChildPath "$($prossLoc + "\*")"

#Folder Watching Variables
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "$inPath"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

#Lone Vars
$freshStart = $null
$statusOld = $null
$pathLoc = (Get-Item -Path ".\").FullName
#$pathMagick = 'C:\Program Files\ImageMagick-7.0.8-Q16\magick.exe'

#Pulls the last write time of a folder to compare later.
function grabStatus
{
    & CD $runPath
    $status = Get-Item $pathLoc | Foreach { $_.LastWriteTime }
}

#Get PDF name from Folder
function grabFileName
{
    $folder = get-childitem -Path $inPath -Directory -Name
    $global:fileName = $folder + ".pdf"
}

#Move all nested files to single folder.
function moveFiles
{
    Get-ChildItem -Path $inPath -Recurse -File | Move-Item -Destination $runPath
}

#Convert Nested files into single PDF
function makePDF
{
    & CD $runPath
    & magick $fileTypes $global:fileName
}

#Move final PDF
function moveCmplt
{
    Get-ChildItem -Path "$runPath\*.pdf" -File | Move-Item -Destination $outPath
}

#Delete Old files
function deleteOld
{
    Remove-Item $remove1 -Recurse -Force
    Remove-Item $remove2 -Recurse -Force
}

#Set compare status to current status then fetches new status.
function stats
{
    $statusOld = $status
    $grabStatus
    sleep 10
}

#Exicute main conversion together.
function action
{
    grabStatus
    If ($status -eq $statusOld)
    {
        grabFileName
        moveFiles
        grabStatus
        If ($status -eq $statusOld)
        {
            makePDF
            grabStatus
            If ($status -eq $statusOld)
            {
                grabStatus
                moveCmplt
                If ($status -eq $statusOld)
                {
                    deleteOld
                }
            }
            Else { stats }
        }
        Else { stats }
    }
    Else { stats }
}

$runIt = { action }

#First Time Start, Then Loop run.
While ($freshStart -eq $null)
{
    If ((Get-ChildItem $inPath | Measure-Object).Count -eq 0)
    {
    }
    Else
    {
        action
    }
    $freshStart = "FreshStartDone!"
}

#Scan folder every 5 seconds for new content then run convert on change.
Register-ObjectEvent $watcher "Created" -Action $runIt
#Register-ObjectEvent $watcher "Created" -Action $action
while ($true) { sleep 5 }

答案1

总结解决方案:

将我的脚本块转换为函数,即

$variable = {code}

function variable {code}

这对我的大多数脚本都有效,但意想不到的副作用是我的循环不再起作用。解决方案是将我使用的主函数转换为全局函数。即

function global:functionName {code}

此后,一切都按预期运行。感谢 Pimp Juice IT、LPChip 和 HackSlash 提供的所有帮助。

工作脚本:

#File Locations
$rootPath = 'C:\IT\'
$inLoc    = 'Convert_Drop'
$prossLoc = 'Processing'
$outLoc   = 'Converted PDF'

#File types to include in PDF creation.
$fileTypes = '*.{png,jpeg,jpg,tiff,tif}'

#Function Variables
$inPath  = Join-Path -Path "$rootPath" -ChildPath "$inLoc"
$outPath = Join-Path -Path "$rootPath" -ChildPath "$outLoc"
$runPath = Join-Path -Path "$rootPath" -ChildPath "$prossLoc"
$remove1 = Join-Path -Path "$rootPath" -ChildPath "$($inLoc + "\*")"
$remove2 = Join-Path -Path "$rootPath" -ChildPath "$($prossLoc + "\*")"

#Folder Watching Variables
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "$inPath"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

#Lone Vars
$freshStart = $null
$statusOld = $null
$pathLoc = (Get-Item -Path ".\").FullName

#Pulls the last write time of a folder to compare later.
function grabStatus
{
    & CD $runPath
    $status = Get-Item $pathLoc | Foreach { $_.LastWriteTime }
}

#Get PDF name from Folder
function grabFileName
{
    $folder = get-childitem -Path $inPath -Directory -Name
    $global:fileName = $folder + ".pdf"
}

#Move all nested files to single folder.
function moveFiles
{
    Get-ChildItem -Path $inPath -Recurse -File | Move-Item -Destination $runPath
}

#Convert Nested files into single PDF
function makePDF
{
    & CD $runPath
    & magick $fileTypes $global:fileName
}

#Move final PDF
function moveCmplt
{
    Get-ChildItem -Path "$runPath\*.pdf" -File | Move-Item -Destination $outPath
}

#Delete Old files
function deleteOld
{
    Remove-Item $remove1 -Recurse -Force
    Remove-Item $remove2 -Recurse -Force
}

#Set compare status to current status then fetches new status.
function stats
{
    $statusOld = $status
    $grabStatus
    sleep 10
}

#Exicute main conversion together.
function global:runIt
{
    grabStatus
    If ($status -eq $statusOld)
    {
        grabFileName
        moveFiles
        grabStatus
        If ($status -eq $statusOld)
        {
            makePDF
            grabStatus
            If ($status -eq $statusOld)
            {
                grabStatus
                moveCmplt
                If ($status -eq $statusOld)
                {
                    deleteOld
                }
            }
            Else { stats }
        }
        Else { stats }
    }
    Else { stats }
}

#$runIt = { action }

#First Time Start, Then Loop run.
While ($freshStart -eq $null)
{
    If ((Get-ChildItem $inPath | Measure-Object).Count -eq 0)
    {
    }
    Else
    {
        global:runIt
    }
    $freshStart = "FreshStartDone!"
}

#Scan folder every 5 seconds for new content then run convert on change.
Register-ObjectEvent $watcher "Created" -Action { global:runIt }
while ($true) { sleep 5 }

答案2

与大多数编程/脚本语言一样,变量具有作用域。它们可以在主代码或函数内共享数据,但不能跨越该边界,除非您告诉脚本可以这样做。

尽管您可以使用全局变量来全局设置某些内容,但如果操作得当,您也可以使用函数。让我解释一下。

函数可以从脚本外部获取变量并将其返回给函数的调用者。Powershell 的函数与大多数脚本略有不同,因为它将函数视为对象,这允许您执行一些很酷的事情。

下面是如何使用具有多个变量的函数的一个小例子:

function Tools
{

    param
    (   [switch]$MySwitch
    ,   [switch]$MySwitchWithReturn
    ,   [Parameter(Mandatory=$false)] [String] $MyParameter
    )


    if( $MySwitch )
    {
        write-host "My Switch was activated"
    }

    if( $MySwitchWithReturn )
    {
        "My SwitchWithReturn was activated"
    }

    if( $MyParameter )
    {
        Write-Host "The parameter has value: " + $MyParameter
        $MyValue2 = "Another value, 2"

        #Lets return 2 different values.
        "Value with nr 1"
        $MyValue2
    }
}

Tools -MySwitch

$MyVar = Tools -MySwitchWithReturn
write-host "MyVar contains: " + $MyVar

$ReturnValues = Tools -MyParameter "test"

Write-host "The first value is: " + $ReturnValues[0]
Write-host "The second value is: " + $ReturnValues[1]

返回:

我的 Switch 已激活
MyVar 包含:+ 我的 SwitchWithReturn 已激活
该参数具有值:+ 测试
第一个值是:+ 值为 1
第二个值是:+ 另一个值,2

回顾一下上面的内容,param 部分用于对如何将参数传递给函数进行大量控制。这不是唯一的方法,但可以实现非常酷的功能,因此这是我的首选方法。

要将任何内容返回给调用该函数的部分,只需将其打印到控制台即可。只需键入“字符串”或仅键入变量的名称,如 MyParameter 部分所示。

最后,如果你想快速做某事,这里有一个使用全局变量的示例。如果你想在脚本顶部有一个设置部分,这很有用:

$Global:MySetting = "This string is globally available."

Write-Host "Accessing the global: " + $Global:MySetting

function MyFunction ($MyParameter)
{
    write-host "My Parameter is:" + $MyParameter
    write-host "The global string is: " + $Global:MySetting
}

MyFunction "testing"

返回:

访问全局:+ 此字符串是全局可用的。
我的参数是:+ 测试
全局字符串是:+ 此字符串是全局可用的。

希望这对你有帮助。如果没有帮助,请留言。:)

答案3

根据有关变量范围的 Microsoft 文档,您需要声明变量范围:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-5.1

示例:要在脚本范围内创建相同的变量,请使用脚本范围修饰符:

$script:a = "one"

您所谈论的“报告输出”范围将是“全局”。这使得变量在脚本之外可用。

相关内容