1

Basically, I'm loading the XML from my local machine, and then I'm trying to save it on a remote machine using Invoke-Command.

I know I can use Copy-item via UNC path, but it takes too long on some machines, and Invoke-Command is faster - I tested this already.

However, I think I'm passing the argument wrong?

The error I get is:

Method invocation failed because [System.String] does not contain a method named 'Save'.
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
    + PSComputerName        : -

This is how I'm passing it:

    foreach ($serverPath in $serverLocations) {

        if ($null -ne $serverPath) {

            $generatedPath = "$(Get-Location)\Generated.ManageSQLJobs.xml" 
            [Xml]$generatedFile = Get-Content $generatedPath


            Write-Log "INFO" "Checking on $serverPath" $ExecutionLogFullPath
            $testPath = Invoke-Command -ComputerName "$serverPath" -ArgumentList [Xml]$generatedFile -ScriptBlock {

                param (
                    $value
                )
                Test-Path -Path "C:\AppData\MonitoringConfig\" 

                if (!$testPath) {
                    $destinationPath = New-Item -Path "C:\AppData\" -Name "MonitoringConfig" -ItemType Directory
                }
                if ($testPath) {
                    $destinationPath = "C:\AppData\MonitoringConfig"
                    #Write-Log "INFO" "Exists on $serverPath." $ExecutionLogFullPath 
                }

                $GetPathToDeleteXML = "C:\AppData\MonitoringConfig\Generated.ManageSQLJobs.xml" 
                if (Test-Path -Path $GetPathToDeleteXML) {
                    Remove-Item -Path * #-Filter Generated.ManageSQLJobs.xml
                }

                $GetPathForXML = "C:\AppData\MonitoringConfig\Generated.ManageSQLJobs.xml" 

                $value.Save($GetPathForXML.fullname)

            }

        }
    }

1 Answer 1

1

-ArgumentList [Xml]$generatedFile

should be (note the (...)):

-ArgumentList ([Xml]$generatedFile)

[Xml]$generatedFile isn't recognized as an expression, because when PowerShell parses in argument mode (commands with arguments, shell-style), an initial [ isn't special.

In effect, your argument is interpreted as an expandable string, i.e. as if you had passed
"[Xml]$generatedFile".
Therefore, $value in your remotely executed script block received a [string] instance, not an [xml] instance, and strings don't have a .Save() method, which explains the error message.

Enclosing your argument in (...) forces its interpretation as an expression.

See this answer for a comprehensive overview of how PowerShell parses unquoted tokens in argument mode.


A general caveat re passing complex objects as arguments to code executed remotely / in background jobs:

Arguments passed to remote / background script blocks must undergo XML-based serialization and deserialization, because they pass computer / process boundaries.

Only a limited set of known types are deserialized faithfully (deserialized as the original type), others are emulated.

While [xml] instances, [string] instances and .NET primitive types such as [int] are faithfully deserialized, most other types are not.

See this answer for more information.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm glad to hear it was helpful, @GhostyIs1337; thanks for the nice feedback.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.