Powershell Value of argument path is NULL
Asked Answered
O

1

2

I've developed a PS1 file which will be responsible to apply SQL Server Patches, based on a Server List. So, it'll read a text file with all servers I need to patch and apply Patch. I've decided using PARAM for "Source Folder" ( where I'll get Server List and record output ); "Destination Folder" ( where I'll be able to run patch ), "File" ( name of patch ), "Instance" ( SQL Server Instance which I'll be running Patch update ). When I start to run commands below, it's able to read Servers List ( so, 1st PARAM is ok ), but, it returns the error below aborting process. What is missing or what am I doing wrong on code below?

PS.: I also would like to use Try...Catch to record a message on the output file. Did I write it correctly? Thanks in advance!

[CmdletBinding()]
Param (
  [Parameter(Mandatory=$True,Position=0)]
  [string]$foldersource,

  [Parameter(Position=1)]
  [string]$folderdest,

  [Parameter(Position=2)]
  [string]$file,

  [Parameter(Position=3)]
  [string]$instance

)
foreach ($cluster in GC "$foldersource\Servers_List.txt")
{
    $output = "Server: $cluster Patch Installation on: $(Get-Date -format 'u')" 
try{
    Invoke-Command -ComputerName $cluster -ScriptBlock 
    {
        cd $folderdest
        .\$file /X:$folderdest
        Start-Sleep -s 10
        .\SETUP.exe /action=patch /instancename=$instance /quiet /IAcceptSQLServerLicenseTerms
    }
    -ErrorAction Stop; 
    $output += " SUCCESS"
   }
catch
   {
      $output += "Failed - $($_.exception.message)"
   }
$output | Out-File -Append $foldersource\Patch_Result_Non_SP.txt
} 

How I'm running command above: .\SQL_Server_install_non-Service_Pack_V2.ps1 "D:\Software\Patch" "D:\Software" "SQLServer2008R2-KB3045316-x64.exe" "MSSQLSERVER"

ERROR:

Cannot process argument because the value of argument "path" is null. Change the value of argument "path" to a non-null value.
+ CategoryInfo          : InvalidArgument: (:) [Set-Location],   PSArgumentNullException
+ FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName        : 

   The term '.\$file' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
+ CategoryInfo          : ObjectNotFound: (.\$file:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName        : 

The term '.\SETUP.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
+ CategoryInfo          : ObjectNotFound: (.\SETUP.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName        : 
Orson answered 25/10, 2017 at 3:57 Comment(3)
try catch use is correctNames
Thanks @Moerwald! :)Orson
I added an answer including the possible solution. If the answer is correct please mark it as correct one. Thx.Names
N
1

You've to pass your arguments either via -ArgumentList or via $using convention to the Invoke-Command cmdlet. Since you are not doing it that way $folderdest, $file will be null in the scope of the Invoke-Command scriptblock -> the scriptblock defines a seperate scope!

From Microsoft:

-ArgumentList

Supplies the values of local variables in the command. The variables in the command are replaced by these values before the command is run on the remote computer. Enter the values in a comma-separated list. Values are associated with variables in the order that they are listed. The alias for ArgumentList is Args.

Also checkout the exmamples of the Invoke-Commandcmdlet via Get-Help Invoke-Command -Examples.

If you don't like the ArgumentList solution you can also use remote variables.

Additionally you should also define an absolute path to your Setup.exe!

So your code should look like:

....
 Invoke-Command -ComputerName $cluster -ArgumentList $file, $folderdest, $instance -ScriptBlock 
{
    Param(
       [string] $rFile,
       [string] $rfileDest,
       [string] $rInstance
    )
    
    # Remove Write-Host after the script block works fine -> Write-Host is only a quick and dirty way to dump the variables content

    Write-Host $rFile
    Write-Host $rfileDest
    Write-Host $rInstance

    cd $rfileDest

    $someArgs = "/X:{0}" -f $rfileDest
    Start-Process -FilePath  $rFile -ArgumentList $someArgs -Wait -PassThru

    Start-Sleep -s 10

    $setupArgs = "action=patch /instancename={0} /quiet /IAcceptSQLServerLicenseTerms" -f $rInstance

    Start-Process -FilePath ".\Setup.exe" -ArgumentList $setupArgs -Wait -PassThru

}
....

Hope that helps.

Names answered 25/10, 2017 at 5:8 Comment(14)
Hi @Moerwald! It's awesome! I have no idea regarding ArgumentList. Thanks for sharing it :)Orson
I have updated code, but error has changed. I've tried to debug by myself, but once I even didn't know ArgumentList, I'm not being able to solve it. If you can give me a hand one more time, I really appreciate :) Follows, new code and error: Invoke-Command -ComputerName $cluster -ArgumentList $file, $folderdest -ScriptBlock{ Param( [string]$f, [string]$fDest ) cd $fDest .\$f /X:$fDest Start-Sleep -s 10 D:\Software\SETUP.exe /action=patch /instancename=$instance /quiet /IAcceptSQLServerLicenseTerms}Orson
ERROR: The term '.\$f' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.Orson
One more question: Can't I use $fDest as path to SETUP.EXE? Will it only work with absolute path? Tks!Orson
@AdemirP: Sorry. Of course you can use $fDest as path to Setup.exe -> my mistake -> I'll update the answer. Regarding the .\$fproblem, it seems that the content of $f points to something that is not an executeable. You can dump the content via Write-Host $f in the script block.Names
! I can only thanks to you :) No worries! Regarding .\$f it's pointing to filename I'm informing at param File: SQLServer2008R2-KB3045316-x64.exe. Also, I've tried to update Path to Setup.exe to $fDest and returns another error: Unexpected token '\SETUP.exe' in expression or statement.Orson
Use the call operator & to invoke Setup.exe -> social.technet.microsoft.com/wiki/contents/articles/…. You can also use the Start-Process cmdlet.Names
! Thanks for the updates! I've updated code as well, but error still persists on: The term '.\$rFile' is not recognized as the name of a cmdlet. Despite the param value is correct, it looks like it's trying to run from a place where file doesn't belong ( local, instead of remote ). Am I correct and why It's happening?Orson
what is the content of $rFile ?Names
follows contents for 03 parameters we've used write-host: SQLServer2008R2-KB3045316-x64.exe D:\Software MSSQLSERVER All of them are correct as expected. Have any idea why is it giving error yet? :( Thanks a lot!Orson
Is the directory, where SQLServer2008R2-KB3045316-x64.exe is situated, in the path variable of the remote machine?Names
I've checked on servers and the directory is not. :(Orson
Then you should add it to your PATH variable, or call the exe with an absolute path.Names
@AdemirP: Is your issue solved, or is it still open?Names

© 2022 - 2024 — McMap. All rights reserved.