Automation

 View Only
  • 1.  scriptBlock

    Posted Dec 30, 2021 04:53 AM

    I am having an issue passing Arrays to scriptblock. to substitute the variables, in order to run this script on the remote server using the invoke-vmscript   

    the code below will install agents on windows server after it has been deployed.

     

    foreach ($Agent in $WinoswsAgnetsList) {

    $AgentName=$AgentFile= $ListofServices= $ArgumentList=$MSIArguments= $DataStamp=$logFile=$InstallerFullpath =$AgentDetails=$null
    write-host "Now processing $Agent"
    $AgentDetails=Select-HashTable -Hashtable $loadVars -Include $Agent
    Write-Host $AgentDetails
    $AgentName =$AgentDetails.Keys
    $AgentFile =$AgentDetails.values.AgentName
    $ListofServices =$AgentDetails.values.ListofServices
    $Operators =$AgentDetails.values.ArgumentList
    if (-not([String]::IsNullOrWhiteSpace( $ListofServices))){
    $ListofServices= $ListofServices.split(",")}
    $InstallerFullpath=$AgentLocalfolder+"\"+$AgentFile

    $Arguments =$Operators.Split("|")

    foreach ($Argument in $Arguments){
    Write-host "Argumnet $Argument" -ForegroundColor Cyan
    $Argument=$Argument.trim()
    $ArgumentList += "$Argument `n"
    #$ArgumentList=@($ArgumentList)
    Write-host "AgentName $AgentName
    ListofServices $ListofServices
    ArgumentList $ArgumentList " -ForegroundColor Green

     


    $AgentInstall={

    Write-Host "Installing $AgentName
    Arguments $ArgumentDetails
    Services $ListofServices"
    Function Check-Service{

    Param ($ServiceName)
    Write-Host "checking $ServiceName "

    try{
    $Service = Get-Service -Name $ServiceName -ErrorAction stop
    }
    Catch { $_NoServiceFoundForGivenName
    write-host "Still Waiting for the $ServiceName Service on the $VMName, I will try again shortly " -ForegroundColor Yellow
    Start-Sleep -Seconds 5
    write-host "I am trying $ServiceName Service on the $VMName " -ForegroundColor Yellow
    }
    if ($Service.Status -eq "Running")
    {$Result = "PASS"
    Write-Host "Service $ServiceName ......PASS" -ForegroundColor Green}
    Else{$Result = "FAIL"
    Write-Host "Service $ServiceName ......FAIL" -ForegroundColor Red}
    Return $Result
    }

    #Install Agents

    Start-Process "msiexec.exe" -Wait -ArgumentList (,$ArgumentDetails) -Verb runas

    Start-Sleep -Seconds 140
    $AgentCounter= [int] "0"
    foreach($Agentservice in $ListofServices){
    do {$Status= Check-Service -ServiceName $Agentservice
    Write-Host "waiting Status....."
    if ($Status -eq "FAIL") {$AgentCounter ++
    Start-Sleep -Seconds 2 }
    write-host "$AgentCounter" -ForegroundColor Yellow

    if ($AgentCounter -eq "240") {write-host "Serivce $AgentName took a long time to Respond " -ForegroundColor Yellow
    Send-eMail -MessageType Failure -MessageContent "Serivce $AgentName took a long time to respond on $VMName"
    Stop-Process -Name powershell -Force}
    }until ($Status -eq "PASS")
    Write-Host "waiting....."
    }

    Start-Sleep -Seconds 20
    }
    Invoke-VMScript -vm $vmname -ScriptText $AgentInstall -GuestCredential $WinodwsLocalCredentials -Server $vCentre -ScriptType Powershell -Verbose


    Write-Host "Installing $AgentName
    Arguments $ArgumentList
    Services $ListofServices" -ForegroundColor Yellow

    }
    }

     



  • 2.  RE: scriptBlock
    Best Answer

    Posted Dec 30, 2021 07:47 AM

    The value on the ScriptText parameter of the Invoke-VMScript cmdlet has to be a String, not a Codeblock.


    If you want to pass values to the code to be executed by Invoke-VMSCript, you will have to incorporate those in that String.
    One way of doing that is by using the ExpandString method.

    See some samples of that method in my Here strings and the ExpandString method dive.

     



  • 3.  RE: scriptBlock

    Posted Jan 02, 2022 05:06 AM

    thank you for your feedback,
    I have followed your chain of thought and changed the datatype of the parameters from array to strings. but when I check inside the scriptblock if the string is null or has empty values, the statement comeback true

     


    Write-Host "Arguments is $ArgumentString "
    if ([String]::IsNullOrWhiteSpace($ArgumentString)){Write-Host "Arguments list is empty"}

     

    -----------------------------------------------------------------------------------------------------------------------| Installing
    | Arguments
    | Services
    |
    | Arguments is
    | Arguments list is empty
    | Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null, empty, or an element of
    | the argument collection contains a null value. Supply a collection that does not contain any null values and then try
    | the command again.
    | At line:34 char:49
    | + ... -Process "msiexec.exe" -Wait -ArgumentList (,$ArgumentString) -Verb ...
    | + ~~~~~~~~~~~~~~~~~~
    | + CategoryInfo : InvalidData: (:) [Start-Process], ParameterBindingValidationException
    | + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand
    |



  • 4.  RE: scriptBlock

    Posted Jan 02, 2022 09:08 AM

    Since you didn't show what exactly you did, I can't say what you did wrong.

    One common mistake is to use double quotes instead of single quotes for the here string.



  • 5.  RE: scriptBlock

    Posted Jan 02, 2022 09:44 AM

    please see the code below, 

    I am trying to pass 2 functions to push software to new vm, one function will check the services are up and running and the other will install agents with arguments.

    foreach ($Agent in $WinoswsAgnetsList) {

    $AgentName=$AgentFile= $ListofServices= $ArgumentList=$MSIArguments= $DataStamp=$logFile=$InstallerFullpath =$AgentDetails= $ArgumentString =$ServiceString=$null
    write-host "Now processing $Agent"
    $AgentDetails=Select-HashTable -Hashtable $loadVars -Include $Agent
    Write-Host $AgentDetails
    $AgentName =$AgentDetails.Keys
    $AgentFile =$AgentDetails.values.AgentName
    $ListofServices =$AgentDetails.values.ListofServices
    $Operators =$AgentDetails.values.ArgumentList
    $InstallerFullpath=$AgentLocalfolder+"\"+$AgentFile

    if (-not([String]::IsNullOrWhiteSpace( $ListofServices))){

    $ListofServices= $ListofServices.split(",")}

    foreach($Service in $ListofServices){
    Write-host "Service $ListofServices" -ForegroundColor Cyan
    $Service=$Service.trim()

    if ([String]::IsNullOrWhiteSpace($ServiceString)){
    $ServiceString = $Service
    }

    else {$ServiceString = $ServiceString+ -join ","+$Service}
    }

    $Arguments =$Operators.Split("|")

    foreach ($Argument in $Arguments){
    Write-host "Argumnet $Argument" -ForegroundColor Cyan
    $Argument=$Argument.trim()
    if ([String]::IsNullOrWhiteSpace($ArgumentString)){
    $ArgumentString = $Argument
    }

    else {$ArgumentString = $ArgumentString+ -join ","+$Argument}

    }


    Write-host "AgentName $AgentName
    ListofServices $ListofServices
    ArgumentList $ArgumentList " -ForegroundColor Green

     

    $AgentInstall={

    Function Check-Service{

    Param ($ServiceName)
    Write-Host "checking $ServiceName "

    try{
    $Service = Get-Service -Name $ServiceName -ErrorAction stop
    }
    Catch { $_NoServiceFoundForGivenName
    write-host "Still Waiting for the $ServiceName Service on the $VMName, I will try again shortly " -ForegroundColor Yellow
    Start-Sleep -Seconds 5
    write-host "I am trying $ServiceName Service on the $VMName " -ForegroundColor Yellow
    }
    if ($Service.Status -eq "Running")
    {$Result = "PASS"
    Write-Host "Service $ServiceName ......PASS" -ForegroundColor Green}
    Else{$Result = "FAIL"
    Write-Host "Service $ServiceName ......FAIL" -ForegroundColor Red}
    Return $Result
    }

    Function Install-Agent{
    param(
    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string]$AgentName,

    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string]$AgentArgument,

    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string]$AgentsServicesNames)

    $ArgumentList=@()

    Write-Host "Agent Name is $AgentName"
    #if ([String]::IsNullOrWhiteSpace($ArgumentString)){Write-Host "Arguments list is empty"}
    $ArgumentString=$ArgumentString.split(",")
    foreach ($Argu in $ArgumentString){
    Write-host "Argumnet $Argument" -ForegroundColor Cyan
    $ArgumentList += "$Argu `n" }
    $ArgumentList=@($ArgumentList)

    Start-Process "msiexec.exe" -Wait -ArgumentList ($ArgumentList) -Verb runas

    #Start-Sleep -Seconds 140
    $ListofServices=$ServiceString.split(",")
    $AgentCounter= [int] "0"
    foreach($Agentservice in $ListofServices){
    do {$Status= Check-Service -ServiceName $Agentservice
    Write-Host "waiting Status....."
    if ($Status -eq "FAIL") {$AgentCounter ++
    Start-Sleep -Seconds 2 }
    write-host "$AgentCounter" -ForegroundColor Yellow

    if ($AgentCounter -eq "240") {write-host "Serivce $AgentName took a long time to Respond " -ForegroundColor Yellow
    Send-eMail -MessageType Failure -MessageContent "Serivce $AgentName took a long time to respond on $VMName"
    Stop-Process -Name powershell -Force}
    }until ($Status -eq "PASS")
    Write-Host "waiting....."
    }

    Start-Sleep -Seconds 20

    }

    Install-Agent -AgentName $AgentName -AgentArgument $ArgumentString -AgentsServicesNames $ServiceString
    #invoke-command -ComputerName $vmname -ScriptBlock {param ($AgentName) & $ServiceString} -ArgumentList $ArgumentList

    }
    Invoke-VMScript -vm $vmname -ScriptText $install -GuestCredential $WinodwsLocalCredentials -Server $vCentre -ScriptType Powershell -Verbose


    Write-Host "Installing $AgentName
    Arguments $ArgumentList
    Services $ListofServices" -ForegroundColor Yellow

    Start-Sleep -Seconds 20

    }

     



  • 6.  RE: scriptBlock

    Posted Jan 02, 2022 09:49 AM

    Not sure what you are trying to there.

    The $AgentInstall variable is still a code block, which you don't seem to use in your code.
    On Invoke-VMScript you use a variable $install, which is nowhere defined or initialised.



  • 7.  RE: scriptBlock

    Posted Jan 02, 2022 09:55 AM

    yes you are right, I was trying to manipulate the scriptblock, even when i use the $AgentInstall  i am still having the same issue

    ScriptOutput
    -----------------------------------------------------------------------------------------------------------------------| Install-Agent : Cannot validate argument on parameter 'AgentName'. The argument is null or empty. Provide an argument
    | that is not null or empty, and then try the command again.
    | At line:72 char:27
    | + Install-Agent -AgentName $AgentName -AgentArgument $ArgumentString - ...
    | + ~~~~~~~~~~
    | + CategoryInfo : InvalidData: (:) [Install-Agent], ParameterBindingValidationException
    | + FullyQualifiedErrorId : ParameterArgumentValidationError,Install-Agent

     



  • 8.  RE: scriptBlock

    Posted Jan 02, 2022 02:31 PM

    I think I already mentioned that the value you pass to ScriptText can not be a code block, but needs to be a String.