Author Posts

April 29, 2017 at 8:03 am

Dear all,
I have a huge configuration of an application development server that needs to reboot a few times.
I've configured the LCM with 'RebootNodeIfNeeded = $True' and I'm using xPendingReboot to control the reboots throughout the config. I'm not using a pull server.

At some point in the config I don't want the node to auto-reboot anymore. But AFAIK I can only change the RebootNodeIfNeeded setting by running Set-DscLocalConfigurationManager again.

I tried something like this:

Script DisableAutoReboot {  
    SetScript  = {
        Set-DscLocalConfigurationManager -Path c:\DSC\DisableAutoReboot
    }
    TestScript = {
    $val = $True
    If ((Get-DscLocalConfigurationManager).RebootNodeIfNeeded) {
             $val = $False
        }
    return $val
    }
    GetScript  = {
        @{Result = (Get-DscLocalConfigurationManager).RebootNodeIfNeeded}
        }
    }
   }
 }

But then I get: The Start-DscConfiguration cmdlet is in progress and must return before Set-DscLocalConfigurationManager can be invoked.

My question is, is this even possible? Apologies if this is a beginner question.

Jacqueline

April 29, 2017 at 1:34 pm

It's really not. You're correct in that you have to reconfigure the LCM, and you can't do that while it's processing a configuration. The most you could do is manually inject a new meta-MOF, but it wouldn't be processed until the next run.

April 30, 2017 at 8:18 am

Thanks for the answer. I will break up the Configuration in smaller pieces then.

June 1, 2017 at 4:55 pm

I have a similar problem and ended up breaking it into sections and then checking to see it a reboot needed to occur. In some cases I wanted to trigger a reboot in others the various resources were potentially triggering a reboot.

I ended up using the Get-PendingReboot script by Brian Wilhite, and modifying it to also look for my particular reboot trigger

So I use the following function to Push my configurations, you will notice the call to WaitForServer that takes a parameter of $EncodedText. $EncodedText is just a structure of server information that I use to set up the configuration data and track which servers I want to deploy as part of this scenario.

 Function DoDscStuff($mofpath,$title)
        {
          if (Test-Path (Join-path $mofpath -ChildPath "*") -Include *.mof)
          {
            #
            # To get the output to a log file
            # https://github.com/PowerShell/SharePointDsc/issues/218
            #
            Dump  '----------------------------------------------------------------------------'
            Dump  "               $title"
            Dump  '----------------------------------------------------------------------------'
	    Dump  ' '
            Dump  ('MOFPath     = {0}' -f $mofPath)
            $errorCount = 0
            $Error.Clear()	       
	
		    if($LogToScreen)
		    {
			    Start-DscConfiguration -Path $mofpath -Wait -Force -credential $InstallerCredential  -Verbose 

                if( $error.Count -gt $errorCount )
                {
                    $AccessDeniedError = $false
                    $dscErrors = $error[$errorCount..($error.Count - 1)];
                    Foreach($prob in $dscErrors)
                    {
                        if($prob.FullyQualifiedErrorId -like '*0x80070005*')
                        {
                            $AccessDeniedError = $true
                            break;
                        }
                    }
                    if($AccessDeniedError)
                    {
                        $errorCount = 0
                        $Error.Clear()
                        Write-Host 'Attempting alternate credentials' -ForegroundColor Yellow
                        Start-DscConfiguration -Path $mofpath -Wait -Force -credential $ChildDomainCred  -Verbose 
                    }
                }
		    }
		    else
		    {
			    Start-DscConfiguration -Path $mofpath -Wait -Force -credential $InstallerCredential -Verbose -Debug *>>  $logFile

                if( $error.Count -gt $errorCount )
                {
                    $AccessDeniedError = $false
                    $dscErrors = $error[$errorCount..($error.Count - 1)];
                    Foreach($prob in $dscErrors)
                    {
                        if($prob.FullyQualifiedErrorId -like '*Access is Denied*')
                        {
                            $AccessDeniedError = $true
                            break;
                        }
                    }
                    if($AccessDeniedError)
                    {
                        $errorCount = 0
                        $Error.Clear()
                        Write-Host 'Attempting alternate credentials' -ForegroundColor Yellow *>> $logFile
                        Start-DscConfiguration -Path $mofpath -Wait -Force -credential $ChildDomainCred  -Verbose -Debug *>>  $logFile 
                    }
                }
		    }
            Dump  ' '
		    Dump  '----------------------------------------------------------------------------'
		    if( $error.Count -gt $errorCount )
            {
                $dscErrors = $error[$errorCount..($error.Count - 1)];
                Dump "The following errors occurred during dsc configuration"
                Dump ($dscErrors | fl * | out-string)

                $NonTermErrorFound = $false
                Foreach($prob in $dscErrors)
                {
                    if($prob.FullyQualifiedErrorId -like '*NonTerminatingError*')
                    {
                        $NonTermErrorFound =$true
                        break
                    }
                }
                if(!$NonTermErrorFound){throw $dscErrors[-1];}
            }
            else
            {
              WaitForServers $EncodedText
            }
          }
        } 
Function WaitForServers{
    [CmdletBinding()]
    Param(
    [Parameter(Mandatory = $true,Position=0)] 
    [string]$EncodedText

    ,[Parameter(Mandatory = $false)] 
    [int]$sleep=20
    )
    
    $Servers = ConvertFrom-Json ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedText)))

    $Computers = $Servers | ?{$_.BuildMe -eq 1} | Select-Object -ExpandProperty name

    $ServersToReboot = ((Get-PendingReboot -ComputerName $Computers)|?{$_.RebootPending -eq $true} | Select-Object -ExpandProperty Computer)

    if ($ServersToReboot -ne $null)
    {
        Restart-Computer $ServersToReboot -Force -Wait -For WinRM -Timeout 300 -Delay 5

        #Clean up any reboots triggered by ECI
        $HKLM = [UInt32] "0x80000002"
        Foreach($server in $ServersToReboot)
        {         
            $WMI_Reg = [WMIClass] "\\$server\root\default:StdRegProv"
            $WMI_Reg.DeleteKey($HKLM, "Software\DesiredStateConfiguration\RebootPending") | Out-Null
        }
    }
}

I use the following script to set my Reboot Flag so that I can control when it gets set

Script Reboot
        {
            SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock {
                Write-Verbose "Setting Reboot Pending"
                New-Item -Path "HKLM:\Software\DesiredStateConfiguration\RebootPending" -Force ;
                return $true;
            }            
            TestScript =Format-DscScriptBlock -Node $Node -ScriptBlock  {
                return (Boolean result from your Test);
            }
            GetScript = {@{Result = 'Doing Nothing'}} 
        }

Hope this help in some small way.

Joe