Perplexing validation error in advanced function

I have an advanced function that allows me to install software MSIs. This function has a parameter called MsiInstallerFilePath which is used to point to where the MSI is located. I have a script that installs 6 different MSIs via a foreach loop. When run on a Windows 7/PS v4.0 box the entire scripts works fine but when run on a XP/PSv2.0 box the function fails to validate on the very last MSIInstallerFilePath I pass to it. I have a ValidateScript block that looks like

 Test-Path -Path $_ -PathType ‘Leaf’ 
inside this function.

Here’s the example calling script:

$WorkingDir = $MyInvocation.MyCommand.Path | Split-Path -Parent

$SoftwareInstallers = @[
	@{ 'Title' = 'Cisco AnyConnect Secure Mobility Client'; 'Version' = '3.1.05182';'Installer' = 'anyconnect-win-3.1.05182-pre-deploy-k9.msi'  }
	@{ 'Title' = 'Cisco AnyConnect Start Before Login Module'; 'Version' = '3.1.05182';'Installer' = 'anyconnect-gina-win-3.1.05182-pre-deploy-k9.msi'  }
	@{ 'Title' = 'Cisco AnyConnect Diagnostics and Reporting Tool'; 'Version' = '3.1.05182'; 'Installer' = 'anyconnect-dart-win-3.1.05182-k9.msi' }
	@{ 'Title' = 'Cisco AnyConnect Network Access Manager'; 'Version' = '3.1.05182'; 'Installer' = 'anyconnect-nam-win-3.1.05182-k9.msi' }
	#@{ 'Title' = 'Cisco AnyConnect Posture Module'; 'Version' = '3.1.05182'; 'Installer' = 'anyconnect-posture-win-3.1.05182-pre-deploy-k9.msi' }
	#@{ 'Title' = 'Cisco AnyConnect Telemetry Module'; 'Version' = '3.1.05182'; 'Installer' = 'anyconnect-telemetry-win-3.1.05182-pre-deploy-k9.msi' }
	#@{ 'Title' = 'Cisco AnyConnect Web Security Module'; 'Version' = '3.1.05182'; 'Installer' = 'anyconnect-websecurity-win-3.1.05182-pre-deploy-k9.msi' }
	@{ 'Title' = 'Cisco NAC Agent'; 'Version' = '4.9.4.3'; 'Installer' = 'nacagentsetup-win-4.9.4.3.msi' }
]

$SoftwareInstallers | foreach {
	if (!(Validate-IsSoftwareInstalled -Productname $_.Title -Version $_.Version)) {
		Install-Software -MsiInstallerFilePath "$WorkingDir\$($_.Installer)" -Verbose
	}
}

The

Validate-IsSoftwareInstalled
is a function that checks WMI and the
Install-Software
executes the MSI given with a set of common switches. They are both inside a module that I import earlier in the script.

You can see that this function (and subsequently) the validationscript gets run for multiple MSIs but just fails validation on the very last one. This ONLY happens on a XP/PSv2 machine but again works fine on a Win7 PS v4 machine.

Any ideas?

Is the failure always for this element:

@{ 'Title' = 'Cisco NAC Agent'; 'Version' = '4.9.4.3'; 'Installer' = 'nacagentsetup-win-4.9.4.3.msi' }

Or is it just failing on whatever happens to be the last item in the array, regardless of its values? When you say it “fails”, what do you mean? Are there any error messages?

I also have a few Copy-Item lines below this code that were also failing only on the XP machine because it said it couldn’t find the files. However, I just commented out all of the code besides $WorkingDir and the Copy-Item lines and now it works.

It “fails” because I’m receiving the message that it failed to validate the MsiInstallerPath parameter. Powershell thinks the file isn’t there but it actually is.

I’d probably need to see the function bodies of Validate-IsSoftwareInstalled and Install-Software to do any troubleshooting. Just seeing the calling code isn’t enough.

Toying around with it I just confirmed it can’t be in either function. I didn’t include them because Install-Software is a monster and didn’t want to make it more complicated than what it could be. I moved the Cisco NAC Agent title up to the top of the SoftwareInstallers hash table and ran the calling code again. It then successfully ran through each MSI as I need. However, it still failed on these two lines saying it can’t find the source path.

Copy-Item -Path "$WorkingDir\configuration.xml" -Destination "C:\Cisco\Cisco AnyConnect Secure Mobility Client\Network Access Manager\newConfigFiles" -Force
Copy-Item -Path "$WorkingDir\NACAgentCFG.xml" -Destination 'C:\Cisco' -Force

…and I forgot to mention. If I run the Install-Software function outside of the script it works fine.

I don’t know what to tell you. With what little bit of code I can see here, I don’t see any reason why this would fail. On a side note, you blacked out your DNS name in some places in that screenshot, but not others (in the error messages.)

Is any of your code calling Set-Location for any reason? UNC paths can be a problem if you’ve changed your PowerShell location to a path that’s not on the FileSystem provider. You can get around that by using New-PSDrive and using the PSDrive name as the root of your path, at which point that path will work regardless of your current location. That’s a pretty big stab in the dark, though.

I agree with you. It doesn’t make sense at all. Thanks for the heads up. I removed the screenshot.

I am executing this from a UNC path. I’ll copy it locally and try it it. Thanks!

Good tip! It worked when I ran it locally. I sure wish it could have been a little more descriptive with the error messages. :frowning: