Use Argument with Invoke-Command

This topic contains 8 replies, has 4 voices, and was last updated by Profile photo of H Man H Man 1 year, 9 months ago.

  • Author
    Posts
  • #23126
    Profile photo of H Man
    H Man
    Participant

    I have a custom Function I am looking to use with invoke command. The function has a -filepath parameter. I am getting an error

    "Cannot bind argument to parameter 'Path' because it is an empty string."

    Here is what i am trying, Where am I going wrong? Any help would be great

    
    $pc = 'pc01'
    $grb = (get-item Function:\Import-RegistryFile).scriptblock
    invoke-command -ScriptBlock $grb -ComputerName $pc -ArgumentList "c:\windows\temp\IEView.reg"  -Verbose 
    
    
  • #23127
    Profile photo of Don Jones
    Don Jones
    Keymaster

    I think I don't understand. Import-RegistryFile already exists on the remote computer? Where is the -Path argument coming into it?

  • #23128
    Profile photo of H Man
    H Man
    Participant

    I am importing a local function into invoke-command ( thats from jeff hicks) .

    $grb = (get-item Function:\Import-RegistryFile).scriptblock
    

    The reg file is on the remote machine. The functions call for a path to the reg file.

    http://mcpmag.com/articles/2014/06/17/function-junction.aspx

  • #23129
    Profile photo of Don Jones
    Don Jones
    Keymaster

    That's a great article, but without seeing YOUR code, it's a little difficult for me to help you troubleshoot the problem. Basically, I don't have enough detail from you to understand what PowerShell is trying to do on your computer.

    Let me see if Jeff can take a look, since he's the one that gave you this idea.

  • #23130
    Profile photo of H Man
    H Man
    Participant

    Thanks Don

    Its just a matter of using's invoke-command -argument parameter in conjunction with the imported function. The Function only has 1 Parameter. I got the Function from Adam Bertman's SoftwareInstallManager Module

    here's the function

    function Import-RegistryFile {
    	
    	[CmdletBinding()]
    	param (
    		[Parameter()]
    		[ValidateScript({ Test-Path -Path $_ -PathType 'Leaf' })]
    		[string]$FilePath
    	)
    	begin {
    
    function Write-Log {
    [CmdletBinding()]
    	param (
    		[Parameter(
    				   Mandatory = $true)]
    		[string]$Message,
    		[Parameter()]
    		[ValidateSet(1, 2, 3)]
    		[int]$LogLevel = 1
    	)
    	
    	try {
    		$TimeGenerated = "$(Get-Date -Format HH:mm:ss).$((Get-Date).Millisecond)+000"
    		## Build the line which will be recorded to the log file
    		$Line = ''
    		$LineFormat = $Message, $TimeGenerated, (Get-Date -Format MM-dd-yyyy), "$($MyInvocation.ScriptName | Split-Path -Leaf):$($MyInvocation.ScriptLineNumber)", $LogLevel
    		$Line = $Line -f $LineFormat
    		
    		## Record the line to the log file if it's declared.  If not, just write to Verbose stream
    		## This is helpful when using these functions interactively when you don't preface a function
    		## with a Write-Log entry with Start-Log to create the $ScriptLogFilePath variable
    		if (Test-Path variable:\ScriptLogFilePath) {
    			Add-Content -Value $Line -Path $ScriptLogFilePath
    		} else {
    			Write-Verbose $Line
    		}
    	} catch {
    		Write-Error $_.Exception.Message
    	}
    
    
    
    
    
    		try {
    			## Detect if this is a registry file for HKCU, HKLM, HKU, HKCR or HKCC keys
    			$Regex = 'HKEY_CURRENT_USER|HKEY_CLASSES_ROOT|HKEY_LOCAL_MACHINE|HKEY_USERS|HKEY_CURRENT_CONFIG'
    			$HiveNames = Select-String -Path $FilePath -Pattern $Regex | foreach { $_.Matches.Value }
    			$RegFileHive = $HiveNames | Select-Object -Unique
    			if ($RegFileHive -is [array]) {
    				throw "The registry file at '$FilePath' contains more than one hive reference."
    			} else {
    				Write-Log -Message "Detected hive type as $RegFileHive"
    			}
    			if ((Get-Architecture) -eq 'x64') {
    				$RegPath = 'syswow64'
    			} else {
    				$RegPath = 'System32'
    			}
    		} catch {
    			Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3'
    			return $false
    		}
    
    }
    	}
    	process {
    		try {
    			if ($RegFileHive -ne 'HKEY_CURRENT_USER') {
    				Write-Log -Message "Starting registry import of reg file $FilePath..."
    				($Result = Start-Process "$($env:Systemdrive)\Windows\$RegPath\reg.exe" -Args "import `"$FilePath`"" -Wait -NoNewWindow -PassThru) | Out-Null
    				Check-Process -Process $Result
    				Write-Log -Message 'Registry file import done'
    			} else {
    				#########
    				## Import the registry file for the currently logged on user
    				#########
    				$LoggedOnSids = Get-LoggedOnUserSID
    				if ($LoggedOnSids.Count -gt 0) {
    					Write-Log -Message "Found $($LoggedOnSids.Count) logged on user SIDs"
    					foreach ($sid in $LoggedOnSids) {
    						## Replace all HKEY_CURRENT_USER references to HKCU\%SID% so that it can be applied to HKCU while not
    						## actually running under that context.  Create a new reg file with the replacements in the system's temp folder
    						$HkcuRegFilePath = "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
    						Write-Log -Message "Replacing HKEY_CURRENT_USER references with HKEY_USERS\$sid and placing temp file in $HkcuRegFilePath"
    						Find-InTextFile -FilePath $FilePath -Find $RegFileHive -Replace "HKEY_USERS\$sid" -NewFilePath $HkcuRegFilePath -Force
    						
    						## Perform a recursive function call to itself to import the newly created reg file
    						Write-Log -Message "Importing reg file $HkcuRegFilePath"
    						Import-RegistryFile -FilePath $HkcuRegFilePath
    						Write-Log -Message "Removing temporary registry file $HkcuRegFilePath"
    						Remove-Item $HkcuRegFilePath -Force
    					}
    				} else {
    					Write-Log -Message 'No users currently logged on.  Skipping current user registry import'
    				}
    				
    				########
    				## Use Active Setup to create a registry value to perform an import of the registry file for each logged on user
    				########
    				Write-Log -Message "Copying $FilePath to systemp temp folder for later user"
    				Copy-Item -Path $FilePath -Destination "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
    				Write-Log -Message "Setting Everyone full control on temp registry file so all users can import it"
    				$Params = @{
    					'Path' = "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
    					'Identity' = 'Everyone'
    					'Right' = 'Modify';
    					'InheritanceFlags' = 'None';
    					'PropagationFlags' = 'NoPropagateInherit';
    					'Type' = 'Allow';
    				}
    				Set-MyFileSystemAcl @Params
    				
    				Write-Log -Message "Setting registry file to import for each user"
    				
    				## This isn't the *best* way to do this because this doesn't prevent a user from clearing out all the temp files
    				Set-AllUserStartupAction -CommandLine "reg import `"$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)`""
    				
    			}
    			
    			
    		} catch {
    			Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3'
    			$false
    		}
    	}
    }
    
    
  • #23131
    Profile photo of Jeffery Hicks
    Jeffery Hicks
    Participant

    The error should also show you want command it is failing on. That's what we need to see. I would probably also strip out all the Write-Log pieces since that is only complicating the process and is really unnecessary for what you are trying to do. I think the other problem is that you have pulled a single function out of a module and it looks like it is calling other commands presumably from that module. I'm not sure this will even work.

  • #23132
    Profile photo of Don Jones
    Don Jones
    Keymaster

    I think I'd probably start by trying to simplify things. You're mixing and matching a few techniques, and that might be where the problem is occurring.

    Let's first look at your function's parameter declaration:

    [CmdletBinding()]
    	param (
    		[Parameter()]
    		[ValidateScript({ Test-Path -Path $_ -PathType 'Leaf' })]
    		[string]$FilePath
    	)
    

    So you've got a parameter, -FilePath. I might start by removing the [ValidateScript] attribute, just to make sure that isn't causing a problem.

    But ultimately, you said your error was:

    [blockquote]"Cannot bind argument to parameter 'Path' because it is an empty string."[/blockquote]

    Your parameter doesn't have a -Path parameter, it has a -FilePath parameter. That suggests it's another command, somewhere within Import-RegistryFile, that's causing the problem. Have you tried running this locally, just so you can get a better error message? The difficulty is that your function contains a LOT of commands that have a -Path parameter, so unless we know which one is upset, it's impossible to fix.

    You may also have a typo. I'm noticing that you have an unterminated quotation mark:

    $Line = "

    I don't know if that's just something that happened while you were pasting here, but I'm pointing it out just in case.

    As a note, the BEGIN/PROCESS blocks are redundant; because this isn't accepting pipeline input (and isn't written to do so), those are just ignored.

  • #23133
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Our forum software helpfully replaces a pair of single quotes (which would indicate an empty string in a script) with a single double-quotation mark. It's just one of those things I've learned to ignore, and when I post a reply to someone that needs to include an empty string, I use a pair of double-quotation marks.

  • #23134
    Profile photo of H Man
    H Man
    Participant

    Thank you Don and Jeff

    What i wound up doing was copying the module over and then doing the following and it worked fine

    
    $Script = {
    ipmo SoftwareInstallManager ; Import-RegistryFile -FilePath "c:\windows\temp\IEView.reg" 
    }
    Invoke-Command -ScriptBlock $Script -ComputerName $pc
    

You must be logged in to reply to this topic.