Skip to content

Instantly share code, notes, and snippets.

@mhudasch
Last active February 9, 2017 20:44
Show Gist options
  • Save mhudasch/da144c79fbb240b8f45979a3ec1eb4e9 to your computer and use it in GitHub Desktop.
Save mhudasch/da144c79fbb240b8f45979a3ec1eb4e9 to your computer and use it in GitHub Desktop.
Invoke a command via the task scheduler on any computer
#requires -version 5
Set-StrictMode -Version Latest
Function Invoke-ScheduledCommand {
[Diagnostics.CodeAnalysis.SuppressMessage("PSUseDeclaredVarsMoreThanAssignments", "", Justification = "This re-establishes the global environment preferences. They can be used all over child scripts.")]
[OutputType("ScheduledCommandResult[]")]
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,Position=0)]
[String]$TaskName,
[Parameter(Mandatory=$true,Position=1)]
[ScriptBlock]$ScriptBlock,
[Parameter(Mandatory=$false,Position=2)]
[object[]]$ArgumentList,
[Parameter(Mandatory=$false,Position=3)]
[String[]]$ComputerName = $env:COMPUTERNAME,
[Parameter(Mandatory=$false,Position=4)]
[pscredential]$Credential,
[Parameter(Mandatory=$false,Position=5)]
[pscredential]$TaskCredential,
[Parameter(Mandatory=$false,Position=6)]
[Switch]$Elevated,
[Parameter(Mandatory=$false,Position=7)]
[Switch]$Interactive,
[Parameter(Mandatory=$false,Position=8)]
[Switch]$AsJob)
Process {
$block = [scriptblock] {
param($tn, $sc, $scargs, $cn, [pscredential]$cred, [pscredential]$tcred, $elev, $inter, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref)
$VerbosePreference = $vpref;
$ErrorActionPreference = $erpref;
$WarningPreference = $wpref;
$DebugPreference = $dpref;
$InformationPreference = $ipref;
$registerBlock = [scriptblock] {
param($tn, $sc, $scargs, $elev, $inter, [pscredential]$tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref)
$ModuleLogLocationPreference = $llpref;
$ModuleScriptLocationPreference = $scpref;
$VerbosePreference = $vpref;
$ErrorActionPreference = $erpref;
$WarningPreference = $wpref;
$DebugPreference = $dpref;
$InformationPreference = $ipref;
if(!(Get-Command -Name Write-LogFile -ErrorAction SilentlyContinue)) {
# remap the passed logging function script
New-Item -Path function: -Name 'Write-LogFile' -Value $logsc | Out-Null;
}
if(!(Test-Path $llpref)) { New-Item -ItemType Directory -Path $llpref -Force | Out-Null; }
if(!(Test-Path $scpref)) { New-Item -ItemType Directory -Path $scpref -Force | Out-Null; }
$result = @{
ScriptName=$null;
ScriptPath=$null;
ScriptLog=$null;
ScriptReturn=$null;
ComputerName=$null;
Script=$null;
TaskDefinition=$null;
EndState=$null;
LastRunTime=$null;
ReturnCode=$null;
Out=$null;
Error=$null;
Warning=$null;
Verbose=$null;
Debug=$null;
Information=$null;
};
$result.ComputerName = $env:ComputerName;
$path = Join-Path $scpref ($tn + ".cmd");
$scrPath = Join-Path $scpref ($tn + ".ps1");
$logPath = Join-Path $llpref ($tn + ".log");
$outPath = Join-Path $scpref($tn + ".out");
$errPath = Join-Path $scpref($tn + ".err");
$vrbPath = Join-Path $scpref($tn + ".vrb");
$wrnPath = Join-Path $scpref($tn + ".wrn");
$dbgPath = Join-Path $scpref($tn + ".dbg");
$infoPath = Join-Path $scpref($tn + ".info");
if(!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")){
$ex = New-Object 'AccessViolationException' -ArgumentList "You must be in an Administrator role on the target computer to access the task scheduler there.", $null;
$result.Error = New-Object System.Management.Automation.ErrorRecord -ArgumentList $ex, "0", "SecurityError", $tn;
$result = New-Object -TypeName psobject -Property $result;
$result.psobject.typenames.Insert(0, "ScheduledCommandResult");
$result | Write-Output;
return;
}
#$TASK_STATE_UNKNOWN = 0;
#$TASK_STATE_DISABLED = 1;
$TASK_STATE_QUEUED = 2;
# $TASK_STATE_READY = 3;
$TASK_STATE_RUNNING = 4;
$serializeObjectDepth = 10;
("".PadRight(100,"=")) | Write-LogFile -Name $tn | Out-Null;
"[$env:ComputerName] Script-Name: '$tn'." | Write-LogFile -Name $tn | Write-Verbose;
"[$env:ComputerName] Script-Path: '$path'." | Write-LogFile -Name $tn | Write-Verbose;
"[$env:ComputerName] Script-Log: '$logPath'." | Write-LogFile -Name $tn | Write-Verbose;
"[$env:ComputerName] Script-Return: '$outPath'." | Write-LogFile -Name $tn | Write-Verbose;
$result.ScriptName = $tn;
$result.ScriptPath = $path;
$result.ScriptLog = $logPath;
$result.ScriptReturn = $outPath;
#region wrapper script build
$wlog = $logsc.Replace('"$ModuleLogLocationPreference"', "`"$llpref`"").Replace("-NoNewline", "").Replace('$', '`$');
$scPreamble = "`$VerbosePreference = '$vpref';`r`n";
$scPreamble += "`$ErrorActionPreference = '$erpref';`r`n";
$scPreamble += "`$WarningPreference = '$wpref';`r`n";
$scPreamble += "`$DebugPreference = '$dpref';`r`n";
$scPreamble += "`$InformationPreference = '$ipref';`r`n";
$scPreamble += "`$script:ScheduledCommandName=`"$tn`";`r`n";
$scPreamble += "`$script:ScheduledCommandLogPath=`"$logPath`";`r`n";
$scPreamble += "`$script:PostponeAutoCleanup=`$false;`r`n";
$scPreamble += "if(!(Get-Command `"Write-LogFile`" -ErrorAction Ignore)) { New-Item -Path 'function:' -Name 'Write-LogFile' -Value `@`"`r`n$wlog`r`n`"`@ | Out-Null; }`r`n"
$scPreamble += "`$scwarn=@(); `$scverbose=@(); `$scdebug=@(); `$scinfo=@();`r`n";
$scArgumentStatement = "-ArgumentList `$([System.Management.Automation.PSSerializer]::Deserialize(@`"`r`n$([System.Management.Automation.PSSerializer]::Serialize($scargs, 999))`r`n`"@))";
if($scargs) {
$scInvokation = "`r`n`(Invoke-Command -ScriptBlock { $sc } -ErrorAction Stop -ErrorVariable scerr $scArgumentStatement 3>&1 4>&1 5>&1 6>&1) | `r`n";
} else {
$scInvokation = "`r`n`(Invoke-Command -ScriptBlock { $sc } -ErrorAction Stop -ErrorVariable scerr 3>&1 4>&1 5>&1 6>&1) | `r`n";
}
$scStreamfilter = "ForEach-Object { `$t = `$_.GetType().Name; `$item = `$_; switch (`$t) { `"WarningRecord`" { `$scwarn+=`$item; } `"VerboseRecord`" { `$scverbose+=`$item; } `"DebugRecord`" { `$scdebug+=`$item; } `"InformationRecord`" { `$scinfo+=`$item; } default { `$item; } } } | ";
$scOutPipe = "Export-CliXml -Path `"$outPath`" -Depth $serializeObjectDepth -Force;`r`n";
$scErrPipe = "if(`$scerr) { `$scerr | Export-CliXml -Path `"$errPath`" -Depth $serializeObjectDepth -Force; }`r`n";
$scVrbPipe = "if(`$scverbose.Count -gt 0) { `$scverbose | Export-CliXml -Path `"$vrbPath`" -Depth $serializeObjectDepth -Force; }`r`n";
$scWrnPipe = "if(`$scwarn.Count -gt 0) { `$scwarn | Export-CliXml -Path `"$wrnPath`" -Depth $serializeObjectDepth -Force; }`r`n";
$scDbgPipe = "if(`$scdebug.Count -gt 0) { `$scdebug | Export-CliXml -Path `"$dbgPath`" -Depth $serializeObjectDepth -Force; }`r`n";
$scInfoPipe = "if(`$scinfo.Count -gt 0) { `$scinfo | Export-CliXml -Path `"$infoPath`" -Depth $serializeObjectDepth -Force; }`r`n";
$finalScript = "$scPreamble try { $scInvokation $scStreamfilter $scOutPipe $scErrPipe $scVrbPipe $scWrnPipe $scDbgPipe $scInfoPipe } catch [System.Exception] { `$(`$_.Exception | Format-List -Force | Out-String) | Out-File `"$logPath`" -Append -Encoding utf8; `$_.Exception | Export-CliXml -Path `"$errPath`" -Depth $serializeObjectDepth -Force; } ";
$result.Script = $finalScript;
#endregion
Set-Content -Path $scrPath -Value $finalScript -Encoding UTF8 -Force | Out-Null;
$cmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NonInteractive -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File $scrPath";
Set-Content -Path $path -Value $cmd -Encoding Ascii -Force | Out-Null;
$taskTemplate = "<?xml version=`"1.0`" encoding=`"UTF-16`"?><Task version=`"1.2`" xmlns=`"http://schemas.microsoft.com/windows/2004/02/mit/task`"><RegistrationInfo><Author>_AUTHOR_</Author><Description>_TASKNAME_</Description></RegistrationInfo><Triggers /><Settings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>true</StopIfGoingOnBatteries><AllowHardTerminate>true</AllowHardTerminate><StartWhenAvailable>true</StartWhenAvailable><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable><IdleSettings><Duration>PT10M</Duration><WaitTimeout>PT1H</WaitTimeout><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleSettings><AllowStartOnDemand>true</AllowStartOnDemand><Enabled>true</Enabled><Hidden>false</Hidden><RunOnlyIfIdle>false</RunOnlyIfIdle><WakeToRun>false</WakeToRun><ExecutionTimeLimit>PT72H</ExecutionTimeLimit><Priority>7</Priority></Settings><Actions Context=`"Author`"><Exec><Command>_COMMAND_</Command></Exec></Actions><Principals><Principal id=`"Author`"><UserId>_TASKUSER_</UserId><LogonType>_LOGONTYPE_</LogonType><RunLevel>_RUNLEVEL_</RunLevel></Principal></Principals></Task>";
$taskTemplate = $taskTemplate -replace "_AUTHOR_", $([Security.Principal.WindowsIdentity]::GetCurrent().Name);
$taskTemplate = $taskTemplate -replace "_TASKNAME_", $tn;
$taskTemplate = $taskTemplate -replace "_COMMAND_", $path;
if($null -ne $tcred) {
$taskCredUserName = $tcred.UserName;
$taskTemplate = $taskTemplate -replace "_TASKUSER_", $taskCredUserName;
} else {
$taskTemplate = $taskTemplate -replace "_TASKUSER_", "SYSTEM";
}
if($elev) {
$taskTemplate = $taskTemplate -replace "_RUNLEVEL_", "HighestAvailable";
} else {
$taskTemplate = $taskTemplate -replace "_RUNLEVEL_", "LeastPrivilege";
}
if($inter) {
$taskTemplate = $taskTemplate -replace "_LOGONTYPE_", "InteractiveToken";
} else {
$taskTemplate = $taskTemplate -replace "_LOGONTYPE_", "Password";
}
$result.TaskDefinition = $taskTemplate;
$scheduler = New-Object -ComObject Schedule.Service;
"[$env:ComputerName] Connect to scheduler and register task." | Write-LogFile -Name $tn | Write-Verbose;
for ($i=1; $i -le 3; $i++) {
Try {
$scheduler.Connect();
"[$env:ComputerName] OK" | Write-LogFile -Name $tn | Write-Verbose;
Break;
} Catch {
if($i -ge 3) {
"[$env:ComputerName] Can't connect to Schedule service." | Write-LogFile -Name $tn | Write-Error -ErrorAction Stop
} else {
Start-Sleep -Seconds 1;
}
}
}
$task = $scheduler.NewTask($null);
$task.XmlText = $taskTemplate;
$rootFolder = $scheduler.GetFolder("\");
if($tcred) {
$taskCredUserName = $tcred.UserName;
$taskCredPasswordClear = $tcred.GetNetworkCredential().Password;
if($inter) {
$td = ($rootFolder.RegisterTaskDefinition($tn, $task, 6, $taskCredUserName, $Null, 3) | Out-String);
} else {
$td = ($rootFolder.RegisterTaskDefinition($tn, $task, 6, $taskCredUserName, $taskCredPasswordClear, 1) | Out-String);
}
} else {
$td = ($rootFolder.RegisterTaskDefinition($tn, $task, 6, "SYSTEM", $Null, 1) | Out-String);
}
$td | Write-LogFile -Name $tn | Out-Null;
"[$env:ComputerName] Task $tn added to scheduler." | Write-LogFile -Name $tn | Write-Verbose;
"[$env:ComputerName] Running the task $tn in the scheduler." | Write-LogFile -Name $tn | Write-Verbose;
$r = ($rootFolder.GetTask($tn).Run(0) | Out-String);
if($r) { $r | Write-LogFile -Name $tn | Write-Verbose; }
# wait unil it is started
do {
Start-Sleep -Seconds 1;
$taskInstance = $rootFolder.GetTask($tn);
if($taskInstance.State -eq $TASK_STATE_QUEUED) {
"[$env:ComputerName] Still waiting for task $tn to start..." | Write-LogFile -Name $tn | Write-Verbose;
} else {
"[$env:ComputerName] Task $tn is started." | Write-LogFile -Name $tn | Write-Verbose;
break;
}
} while($true);
# wait until is finished
do {
$taskInstance = $rootFolder.GetTask($tn);
if($taskInstance.State -eq $TASK_STATE_RUNNING) {
"[$env:ComputerName] Task $tn is still running..." | Write-LogFile -Name $tn | Write-Verbose;
} else {
$result.EndState = $taskInstance.State;
$result.LastRunTime = $taskInstance.LastRunTime;
$result.ReturnCode = $taskInstance.LastTaskResult;
"[$env:ComputerName] Task $tn is done. (with state: $($taskInstance.State) - last run time: $($taskInstance.LastRunTime) - last task result: $($taskInstance.LastTaskResult))" | Write-LogFile -Name $tn | Write-Verbose;
break;
}
Start-Sleep -Seconds 5;
} while($true);
if(Test-Path $outPath) {
$result.Out = Import-Clixml -Path $outPath;
if($null -eq $result.ReturnValue) { "[$env:ComputerName] Scheduled task $tn returned nothing." | Write-LogFile -Name $tn | Write-Verbose; }
else { "[$env:ComputerName] Scheduled task $tn has returned something." | Write-LogFile -Name $tn | Write-Verbose; }
"[$env:ComputerName] Removing out file of task $tn." | Write-LogFile -Name $tn | Write-Verbose;
Remove-Item $outPath -Force | Out-Null;
"[$env:ComputerName] OK" | Write-LogFile -Name $tn | Write-Verbose;
} else {
"[$env:ComputerName] Scheduled task $tn returned nothing." | Write-LogFile -Name $tn | Write-Verbose;
}
if(Test-Path $errPath) {
$result.Error = Import-Clixml -Path $errPath;
if($null -ne $result.Error) { "[$env:ComputerName] Scheduled task $tn resulted in an error." | Write-LogFile -Name $tn | Write-Verbose; }
"[$env:ComputerName] Removing err file of task $tn." | Write-LogFile -Name $tn | Write-Verbose;
Remove-Item $errPath -Force | Out-Null;
"[$env:ComputerName] OK" | Write-LogFile -Name $tn | Write-Verbose;
}
if(Test-Path $vrbPath) {
$result.Verbose = Import-Clixml -Path $vrbPath;
Remove-Item $vrbPath -Force | Out-Null;
}
if(Test-Path $wrnPath) {
$result.Warning = Import-Clixml -Path $wrnPath;
Remove-Item $wrnPath -Force | Out-Null;
}
if(Test-Path $dbgPath) {
$result.Debug = Import-Clixml -Path $dbgPath;
Remove-Item $dbgPath -Force | Out-Null;
}
if(Test-Path $infoPath) {
$result.Information = Import-Clixml -Path $infoPath;
Remove-Item $infoPath -Force | Out-Null;
}
"[$env:ComputerName] Removing the task $tn out of the scheduler." | Write-LogFile -Name $tn | Write-Verbose;
$r = $rootFolder.DeleteTask($tn,0);
if($r) { $r | Write-LogFile -Name $tn | Write-Verbose; }
"[$env:ComputerName] OK" | Write-LogFile -Name $tn | Write-Verbose;
"[$env:ComputerName] Removing the script file ('$path', '$scrPath')." | Write-LogFile -Name $tn | Write-Verbose;
Remove-Item $path -Force | Out-Null;
Remove-Item $scrPath -Force | Out-Null;
"[$env:ComputerName] OK" | Write-LogFile -Name $tn | Write-Verbose;
$result = New-Object -TypeName psobject -Property $result;
$result.psobject.typenames.Insert(0, "ScheduledCommandResult");
$result | Write-Output;
};
if($env:COMPUTERNAME -eq $cn) { # locally
if($null -eq $cred) {
Invoke-Command -ScriptBlock $registerBlock -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | Write-Output;
} else {
Invoke-Command -Credential $cred -ScriptBlock $registerBlock -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | Write-Output;
}
} else { #remotely
$list = New-Object System.Collections.ArrayList;
$list.AddRange(@($cn)); $l = $false;
if($list -icontains $env:COMPUTERNAME) { $l = $true; $ln = New-Object System.Collections.ArrayList; $ln.AddRange(@($list | Where-Object { $_ -inotmatch $env:COMPUTERNAME })); $list = $ln; }
if($l) {
if($null -eq $cred) {
Invoke-Command -ScriptBlock $registerBlock -HideComputerName -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | ForEach-Object {
$_.psobject.typenames.Insert(0, "ScheduledCommandResult"); $_; } | Write-Output;
} else {
Invoke-Command -Credential $cred -ScriptBlock $registerBlock -HideComputerName -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | ForEach-Object {
$_.psobject.typenames.Insert(0, "ScheduledCommandResult"); $_; } | Write-Output;
}
}
if($null -eq $cred) {
Invoke-Command -ComputerName ($list.ToArray()) -ScriptBlock $registerBlock -HideComputerName -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | ForEach-Object {
$_.psobject.typenames.Insert(0, "ScheduledCommandResult"); $_; } | Write-Output;
} else {
Invoke-Command -ComputerName ($list.ToArray()) -Credential $cred -ScriptBlock $registerBlock -HideComputerName -ArgumentList @($tn, $sc, $scargs, $elev, $inter, $tcred, $logsc, $llpref, $scpref, $erpref, $vpref, $wpref, $dpref, $ipref) | ForEach-Object {
$_.psobject.typenames.Insert(0, "ScheduledCommandResult"); $_; } | Write-Output;
}
}
};
# normally this variable comes from a sorrounding module
# but when it is not there...
if(-not(Get-Variable -Name "ModuleLogLocationPreference" -ErrorAction Ignore)) {
$ModuleLogLocationPreference = 'C:\Users\Public'
$ModuleScriptLocationPreference = 'C:\Users\Public'
}
# normally this function comes from a sorrounding module
# but when it is not there...
if(-not(${function:Write-LogFile})) {
Function Write-LogFile {
param(
[Parameter(Mandatory=$true,Position=0, ValueFromPipeline=$true, ParameterSetName="IO")]
[object[]]$InputObject,
[Parameter(Mandatory=$true,Position=0, ParameterSetName="Message")]
[AllowEmptyString()]
[string]$Message,
[Parameter(Mandatory=$false, ParameterSetName="Message")]
[Switch]$PassThru,
[Parameter(Mandatory=$false,Position=1)]
[string]$Name = "log_$([datetime]::Now.ToString("yyyy-MM-dd"))",
[Parameter(Mandatory=$false,Position=2)]
[string]$Path = "$ModuleLogLocationPreference"
)
Process {
$pre = [datetime]::Now.ToString("[yyyy-MM-dd HH:mm:ss.fff]");
$llp = "$Path\$Name.log";
switch ($PSCmdlet.ParameterSetName) {
"IO" {
$InputObject | ForEach-Object { ("{0} {1}" -f $pre, $($_ | Format-List * | Out-String)) | Out-File $llp -Encoding utf8 -Append -NoNewline; $_ } | Write-Output;
}
"Message" {
if($PassThru.IsPresent) {
$Message | ForEach-Object { ("{0} {1}" -f $pre, $_) | Out-File $llp -Encoding utf8 -Append; $_ } | Write-Output;
} else {
$Message | ForEach-Object { ("{0} {1}" -f $pre, $_) | Out-File $llp -Encoding utf8 -Append; };
}
}
}
}
}
}
if($AsJob.IsPresent) {
Start-Job -Name $TaskName -ScriptBlock $block -ArgumentList @($TaskName, $ScriptBlock, $ArgumentList, $ComputerName, $Credential, $TaskCredential, $Elevated, $Interactive, ${function:Write-LogFile}.ToString(), $ModuleLogLocationPreference, $ModuleScriptLocationPreference, $ErrorActionPreference, $VerbosePreference, $WarningPreference, $DebugPreference, $InformationPreference) | Write-Output;
} else {
Invoke-Command -ScriptBlock $block -ArgumentList @($TaskName, $ScriptBlock, $ArgumentList, $ComputerName, $Credential, $TaskCredential, $Elevated, $Interactive, ${function:Write-LogFile}.ToString(), $ModuleLogLocationPreference, $ModuleScriptLocationPreference, $ErrorActionPreference, $VerbosePreference, $WarningPreference, $DebugPreference, $InformationPreference) | Write-Output;
}
}
}
Update-TypeData -TypeName "ScheduledCommandResult" -DefaultDisplayPropertySet "ScriptName","ScriptPath","ScriptLog","ScriptReturn","ComputerName","EndState","LastRunTime","ReturnCode","Out","Error","Warning","Verbose","Debug","Information" -Force;
Update-TypeData -TypeName "ScheduledCommandResult" -DefaultKeyPropertySet "ScriptName","ComputerName" -Force;
@KurtDeGreeff
Copy link

Sadly your function doesn't work for me.. No matter which parameters I always get:
You know how to solve this? Many thanks

You cannot call a method on a null-valued expression.
At C:\temp\Invoke-ScheduledCommand.ps1:295 char:7

  •   Invoke-Command -ScriptBlock $block -ArgumentList @($TaskName, $ ...
    
  •   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidOperation: (:) [], RuntimeException
    • FullyQualifiedErrorId : InvokeMethodOnNull

@mhudasch
Copy link
Author

This should be fixed now. The problem was that I use this script in context of a powershell module and not stand-alone. Some of the variables are not set when it is used stand-alone. Now this variables are initialized correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment