Use Argument with Invoke-Command

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 

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

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

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.

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

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.

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.

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.

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