2

У меня есть сценарий, который работал до того, как я начал разбивать его на более мелкие части. Что-то, что я заметил, поскольку я пытаюсь использовать переменные, информация не вводится. Мне нужно скопировать эту переменную в мои функции 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 }

3 ответа3

2

Подведены итоги решения:

Преобразовал мои блоки скриптов в функции, т.е.

$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 }
1

Как и в большинстве языков программирования / сценариев, переменные имеют область видимости. Они могут обмениваться данными в основном коде или функции, но не пересекают эту границу, если вы не скажете сценарию, что это возможно.

Хотя вы можете использовать глобальные переменные, чтобы установить что-то глобально, вы также можете работать с функциями, если вы делаете это хорошо. Позволь мне объяснить.

Функции могут получать переменные извне скрипта и возвращать их вызывающей функции. 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]

Это возвращает:

Мой переключатель был активирован
MyVar содержит: + Мой SwitchWithReturn был активирован
Параметр имеет значение: + test
Первое значение: + значение с номером 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"

Это возвращает:

Доступ к глобальному: + Эта строка доступна глобально.
Мой параметр: + тестирование
Глобальная строка: + Эта строка доступна глобально.

Я надеюсь, это поможет вам. Если нет, пожалуйста, оставьте комментарий. :)

0

В соответствии с этим документом Microsoft о области видимости переменной необходимо объявить область видимости переменной:

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

ПРИМЕР: Чтобы создать ту же переменную в области видимости скрипта, используйте модификатор области видимости скрипта:

$script:a = "one"

Объем "отчета", о котором вы говорите, будет "глобальным". Это делает переменную доступной вне вашего скрипта.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .