我有一个脚本,在我开始将其分解成更小的部分之前,它一直在运行。我注意到,当我尝试使用变量时,信息没有被引入。我必须将该变量复制粘贴到我的 If、Else、While 或其他函数中才能使用它们。我被告知使用 $script: 但据我所知,这只允许变量“报告”出函数以供以后使用。我不需要它只是为了提取信息。
到目前为止我的脚本的细目:
- 用户将文件夹放入特定的放置文件夹中。
- 脚本检测到新文件并开始运行
- 文件夹名称已注明
- 所有文件都从其文件夹结构移动到另一个文件夹中。
- 然后将所有这些文件转换为单个 .pdf
- 该 .pdf 被移动到“已完成文件夹”
- 所有空文件夹和文件均被删除。
脚本在启动时运行所有这些,然后静待并观察更新。
我的代码:
#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 文档,您需要声明变量范围:
示例:要在脚本范围内创建相同的变量,请使用脚本范围修饰符:
$script:a = "one"
您所谈论的“报告输出”范围将是“全局”。这使得变量在脚本之外可用。