Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
901 views
in Technique[技术] by (71.8m points)

powershell - Function parameter value changing without modification on my behalf

I'm a powershell novice and am currently encountering a goofy issue (to me at least) that I'll try my best to explain below.

I'm having issues with what seems to be prior values for a function parameter being "pre-pended" to that same parameter the next time that function is called. That or my two parameters for the function are being combined and something else is occurring that I'm not aware of. Stepping through the ISE debugger has not helped with solving this issue. I'll throw in my code and the text files that I am reading from then explain the issue further below.

[CmdletBinding()]
Param(
    #Path to file containing weak ACL's before software installation
    [Parameter(Mandatory = $false)] [string]$BeforeInstallACL = "./Before.txt", 

    #Path to file containing weak ACL's after software installation
    [Parameter(Mandatory = $false)] [string]$AfterInstallACL = "./After.txt",

    #Folder location of output file
    [Parameter(Mandatory = $false)] [string]$OutputPath = "./"
)

$latestRegPath = $null

function ReadFromBeforeInstallation ($line, $newRegisteryItem) {
    # Checks if the param (file, dir, or registery key path) exists in $BeforeInstallACL 
    $regItem = $newRegistryItem
    $isPath = CheckIfPath($line)
    Write-Host $line
    $pathFound = $false
    if ($isPath) {
        $content = Get-Content $BeforeInstallACL
        $content | ForEach-Object {
            if ($_.ToString().Trim() -eq $line) {
                $pathFound = $true
                break
            }
       }
       if (!$pathFound) {
           # We have a path that only showed up after installation and want to output this
           $regItem = $line
           WriteToOutput("`r`n{0}`r`n" -f $regItem)
       }
   }
   return $regItem
}

function ReadFromAfterInstallation {
    $content = Get-Content $AfterInstallACL
    $newRegistryItem = $null
    $content | ForEach-Object {
        $_ = $_.Trim()
        if ($_) {
            if ($newRegistryItem) {
                WriteToOutput($_)
            }
            $newRegistryItem = ReadFromBeforeInstallation($_, $newRegistryItem)
        }
        else {
            $newRegistryItem = $null
        }
    }            
}

function WriteToOutput {
    param (
        # Line of a File, Dir or Registery Key from $AfterInstallACl
        [Parameter(Mandatory=$true, Position=0)]
        [string] $Line
    )
    $Line | Out-File -FilePath $OutputFile -Append
}

function CheckIfPath($line) {
    # Check if the line paramater is a path or not
    $isMatch = $false
    if ($line -match "HKEY_LOCAL_MACHINE") {
        $isMatch = $true
    }
    return $isMatch
}

#Create the empty output file we're going to use for logging
$OutputFile = Join-Path -Path $OutputPath -ChildPath difference_output.txt
New-Item $OutputFile -type File -force >$null


Get-Date | Out-File -FilePath $OutputFile 
ReadFromAfterInstallation
Get-Date | Out-File -FilePath $OutputFile -Append

Here is after.txt

Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftDRM
Everyone
SetValue, CreateSubKey, CreateLink, ReadKey, ChangePermissions, TakeOwnership


Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftFunction DiscoveryRegistryStorePublicationExplorer
Everyone
SetValue, CreateSubKey, ReadKey
BUILTINUsers
SetValue, CreateSubKey, ReadKey


Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftInputHwkSettings
BUILTINUsers
SetValue, CreateSubKey, ReadKey

and here is before.txt

Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftFunction DiscoveryRegistryStorePublicationExplorer
Everyone
SetValue, CreateSubKey, ReadKey
BUILTINUsers
SetValue, CreateSubKey, ReadKey


Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftInputHwkSettings
BUILTINUsers
SetValue, CreateSubKey, ReadKey


Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftInputLocales
BUILTINUsers
SetValue, CreateSubKey, ReadKey


Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftInputLocalesloc_0039
BUILTINUsers
SetValue, CreateSubKey, ReadKey

The issue is in ReadFromBeforeInstallation() which is called in ReadFromAfterInstallation(). In ReadFromAfterInstallation, I am iterating through the lines of a after.txt, passing them to ReadFromBeforeInstallation and then seeing if the line contains "HKEY_LOCAL_MACHINE". If so, and that line is not present in before.txt, I want to write the line to my output file.

Sounds simple enough. I'm just trying to find the HKLM registry keys that are in after.txt but not before.txt. What I noticed was that the $line param in ReadFromBeforeInstallation was holding results from past functional calls. A simple Write-Host statement would show lines like the following

Everyone Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftDRM
SetValue, CreateSubKey, ReadKey Everyone Microsoft.PowerShell.CoreRegistry::HKEY_LOCAL_MACHINESOFTWAREMicrosoftFunction DiscoveryRegistryStorePublicationExplorer 

I never had lines like this in after.txt. Hovering over the $line parameter in ReadFromBeforeInstallation in ISE when the program was running showed that $line was what it was supposed to be too but it once I reached CheckifPath() call it would have an HKEY path appended to it. I'm really stumped what could be going on here. I realize this was a long post, but if anyone could help me out, I would greatly appreciate it.

btw, my powershell version is 5.1

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're using the wrong invocation syntax

Change this:

ReadFromBeforeInstallation($_, $newRegistryItem)

to this:

ReadFromBeforeInstallation $_ $newRegistryItem
# or
ReadFromBeforeInstallation -line $_ -newRegisteryItem $newRegistryItem

Otherwise, PowerShell will interpret the expression ($_, $newRegistryItem) as 1 argument and bind that only to the first positional parameter of the function!

The following help topics might be useful in understanding PowerShell's command invocation syntax better:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...