VMware Cloud Community
cafesito
Contributor
Contributor

Exception: You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not alllowed. Please reset them to $null and reconnect to the vSphere server.

Hi,

I've been running into an issue attempting to retrieve information from multiple Virtual Center servers using the PowerCLI in a multi-threaded environment using C#. Essentially, in one test scenario, I have one PowerCLI script that is used to retrieve raw disk information from VMs, one thread per Virtual Center, and multiple Virtual Centers.

When using a single thread to retrieve such information, everything works fine. Using multi-threading generates this error:

Message: VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidState: You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server. at VMware.VimAutomation.ViCore.Util10Ps.BaseCmdlet.SessionStateManager.SyncDefaultVISeverPSVariables(SessionState sessionState, PSHost host) at VMware.VimAutomation.Sdk.Util10Ps.BaseCmdlet.ErrorCallbackCmdletBase.BeginProcessing() at System.Management.Automation.Cmdlet.DoBeginProcessing() at System.Management.Automation.CommandProcessorBase.DoBegin()

The PowerCLI script that retrieves raw disk info looks like this:

if ( (Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue) -eq $null )

{

Add-PsSnapin "VMware.VimAutomation.Core"

}

$global:DefaultVIServer = $null

$global:DefaultVIServers = $null

$server = connect-viserver -Server "ServerName" -User "UserName" -Password "Password" #-NotDefault -Verbose:$true -Debug:$true

$global:DefaultVIServer

$global:DefaultVIServers

$VMs = Get-VM -Server $server

$count= 0

$Disks = @()

foreach($VM in $VMs)

{

  1. if (++$count % 10 -eq 0) {Write-Output "Done $count VMs"}

if($VM -ne $null)

{

foreach ($HDD in get-HardDisk -VM $VM -Server $server)

{

if ($HDD.DiskType -eq "rawPhysical" -or $HDD.DiskType -eq "rawVirtual")

{

if ($Disks -notcontains $HDD) {$Disks += $HDD}

}

}

}

}

return $Disks

As a stand-alone script, the code above works just fine. However, if the " -NotDefault -Verbose:$true -Debug:$true" is enabled in the call to connect-viserver, the line that reads "$VMs = Get-VM -Server $server" throws the same exception:

You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset

them to $null and reconnect to the vSphere server.

I have attempted to resolve the issue by doing exactly what the exception says, resetting the $global:DefaultVIServer and $global:DefaultVIServers variables to null and reconnecting to the vSphere server, however, the error persists. I'm thinking that if I can resolve this issue when running the code as a standalone script, and using the -NotDefault option in connect-viserver cmdlet, then I will be able to run the script by invoking it from C# and using multi-threading.

Any suggestions for how I can resolve this issue?

Thanks,

Juan

17 Replies
avlieshout
VMware Employee
VMware Employee

Try setting the servermode to multiple

Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false | Out-Null

Arnim

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
cafesito
Contributor
Contributor

I've modified the script with your recommendation, but the error persists. The script now looks like this:

if ( (Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue) -eq $null )

{

Add-PsSnapin "VMware.VimAutomation.Core"

}

Set-PowerCLIConfiguration -DefaultVIServerMode Multiple-Confirm:$false | Out-Null

$global:DefaultVIServer = $null

$global:DefaultVIServers = $null

$server = connect-viserver -Server "ServerName" -User "Username" -Password "Password" -NotDefault -Verbose:$true -Debug:$true

$global:DefaultVIServer

$global:DefaultVIServers

$VMs = Get-VM -Server $server

$count= 0

$Disks = @()

foreach($VM in $VMs)

{

if($VM -ne $null)

{

foreach ($HDD in get-HardDisk -VM $VM -Server $server)

{

if ($HDD.DiskType -eq "rawPhysical" -or $HDD.DiskType -eq "rawVirtual")

{

if ($Disks -notcontains $HDD) {$Disks += $HDD}

}

}

}

}

return $Disks

It still errors out with the same exception on the line, " $VMs = Get-VM -Server $server" even though the $server variable holds the connection info to the Virtual Center server.

Reply
0 Kudos
LucD
Leadership
Leadership

Try removing the following 2 lines

$global:DefaultVIServer = $null
$global:DefaultVIServers = $nul

____________

Blog: LucD notes

Twitter: lucd22


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
cafesito
Contributor
Contributor

The error persists. Why would the call "$VMs = Get-VM -Server $server" fail when the $server variable is set and the connection is established? Not sure what else I need to do here...

Reply
0 Kudos
LucD
Leadership
Leadership

Is there anything in the $Server variable ?

Did the Connect-VIServer work ?

____________

Blog: LucD notes

Twitter: lucd22


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
cafesito
Contributor
Contributor

I'm using PowerGUI Script Editor to debug the script. I set a breakpoint on the connect-viserver line, pressed F10, and then typed the following into the command prompt:

: PS C:\Windows\SysWOW64> $server.IsConnected

True

: PS C:\Windows\SysWOW64> $server.IsConnected

True

After connecting and pressing F10, the following still comes up:

You have modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server.

At :line:12 char:13

+ $VMs = Get-VM <<<< -Server $server

Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee

I don't have any problems running your script.

I ran it using PowerCLI 4.1 against vCenter 4.0

I think it must be something in your PowerShell environment.

If you use the -Notdefault parameter, the serverconnection is not added to $global:DefaultVIServer (single mode) or $global:DefaultVIServers (multiple mode)

Why do you want to run multiple threads?

If you set the servermode to multiple, PowerCLI handles the session management to multiple VIServers.

If connected to multiple servers your command automatically runs against all the connected servers.

I've modified your code. The body of your code can be easily turned into a oneliner.

if ( (Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue) -eq $null ) { 
    Add-PsSnapin "VMware.VimAutomation.Core" 
}
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false | Out-Null
$server = connect-viserver -Server "ServerName1","ServerName2" -User "Username" -Password "Password"

Get-VM | Get-HardDisk | ?{$_.DiskType -eq "rawPhysical" -or $_.DiskType -eq "rawVirtual"}

-


Arnim van Lieshout

Blogging: http://www.van-lieshout.com

Twitter: http://www.twitter.com/avlieshout

If you find this information useful, please award points for "correct" or "helpful".

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

Your script seems to work from the PowerCLI prompt.

This looks like a possible PowerGui problem.

Did you raise the question in their forum as well ?

____________

Blog: LucD notes

Twitter: lucd22


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee

I don't have any problems running it in PowerGUI editor.

-


Arnim van Lieshout

Blogging: http://www.van-lieshout.com

Twitter: http://www.twitter.com/avlieshout

If you find this information useful, please award points for "correct" or "helpful".

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee

Ok, I can reproduce your problem now!.

It looks like a PowerGUI problem.

The problem only raises when you use the -NotDefault parameter in Connect-VIserver

If you remove the parameter your code runs fine.

-


Arnim van Lieshout

Blogging: http://www.van-lieshout.com

Twitter: http://www.twitter.com/avlieshout

If you find this information useful, please award points for "correct" or "helpful".

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
cafesito
Contributor
Contributor

Hi,

Thank you guys for your comments - they've helped me realize what the cause of this problem is.

I'm using multiple threads in C#, and calling different powershell scripts from each thread. I decided to use multiple threads in C# because I noticed the calls that PowerCLI is making take a while to respond, and since I want to run multiple PowerCLI scripts at a time to retrieve data, I thought using multi-threading was a good approach.

However, this multi-threading approach generates the aforementioned exception, since the PowerShell Runspace in C# is not thread safe, and each script may connect to a different vSphere server at the same time. Since connections to different VCs may happen at the same time, this modifies the global:DefaultVIServer variables and the exception is raised.

For the time being, I've managed to avoid the exception by placing a lock around where the Runspace is open and closed. However, this seems to defeat the purpose of having multi-threading, since the lock is placed around one of the most expensive operations executed. I've read that using processes instead of threads will resolve the issue, but that seems kind of hackish.

Might you know of another way to make the Runspace thread-safe, or run multiple threads within a Runspace without modifying the global:DefaultVIServer variables?

Your comments are very much appreciated,

Juan

Reply
0 Kudos
admin
Immortal
Immortal

I'm not sure if it's possible to make the Runspace thread-safe - you could probably post a question in the PowerShell forum, there might be someone who knows how to achieve this.

Another option to achieve what you want is to make all the necessary connections from the main thread. Then you can pass the appropriate connection to each child thread(script). You'll just have to modify your scrips to work only against the specified connection, rather than all available connections (e.g. use the -Server parameter of the cmdlets).



-


PowerCLI development team

Reply
0 Kudos
cafesito
Contributor
Contributor

Thanks for all your feedback guys, its been very helpful. After re-thinking the problem, I've decided to use the vSphere SDK, as that is thread-safe. Its been a good learning experience using the PowerCLI though. Many thanks Smiley Happy

Reply
0 Kudos
SameerBaveja
Contributor
Contributor

Hi,

Can you please send me the code you have written using vSphere SDK. My id is sameer.baveja19@gmail.com

Thanks in advance.

Reply
0 Kudos
AlbertWT
Virtuoso
Virtuoso

Hi,

Does anyone know why when I execute PowerCLI in PowerGUI, I get this error mesage:

Get-VMHost : You have  modified the global:DefaultVIServer and global:DefaultVIServers system variables. This is not allowed. Please reset them to $null and reconnect to the vSphere server.
At C:\Users\Admin\AppData\Local\Temp\02ab4fc2-7014-44fe-acda-606e70e4db22.ps1:5 char:11
+ Get-VMHost <<<<
    + CategoryInfo          : NotSpecified: (:) [Get-VMHost], InvalidState
    + FullyQualifiedErrorId : VMware.VimAutomation.ViCore.Types.V1.ErrorHandling.InvalidState,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVMHost

I cannot execute any Get- powerCLI command and the above is the result from the one simple command Get-VMHost.

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos
eeldivady
Contributor
Contributor

I finally found a workaround to this problem. runspaces are not thread-safe so you have to run them out of process. You don't even have to use snapin like one guy mentions.  Here's my solution in C#, you should be able to reference this to make modifications to your powershell script to create a runspace out of processes. See line: RunspaceFactory.CreateOutOfProcessRunspace()

        public async Task TestPowercli(string name, string vcenterHost) {

            if (string.IsNullOrWhiteSpace(name)) { return; }

            if (string.IsNullOrWhiteSpace(vcenterHost)) { return; }

            instanceName = name.Trim();

            int timeoutMins = 5;

            string script = @"c:\temp\testpowercli\testpowercli.ps1 " + instanceName + " " + vcenterHost + " -verbose";

            PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(5, 0), null, null, false);

            using (Runspace runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance)) {

                PowerShell ps = PowerShell.Create();

                runspace.Open();

                ps.Runspace = runspace;

                ps.AddScript(script);

                outputCollection.DataAdded += outputCollection_DataAddedPowercli;

                // the streams (Error, Debug, Progress, etc) are available on the PowerShell instance.

                // we can review them during or after execution.

                // we can also be notified when a new item is written to the stream (like this):

                ps.Streams.Error.DataAdded += Error_DataAddedPowercli;

                ps.Streams.Verbose.DataAdded += Verbose_DataAddedPowercli;

                IAsyncResult result = ps.BeginInvoke<PSObject, PSObject>(null, outputCollection);

                DateTime start = DateTime.Now;

                while (result.IsCompleted == false) {

                    if ((DateTime.Now - start).TotalMinutes > timeoutMins) {

                        Clients.All.getPowercliMessage(instanceName, "ERROR: Time out exceeded after " + timeoutMins + " minutes");

                        break;

                    }

                    await Task.Delay(1000);

                }

            }

            Clients.All.getPowercliMessage(instanceName, "Done");

        }

NetAppJamesGrif
Contributor
Contributor

This was the first thread I ran across concerning parallelism so I'm adding some other findings for whomever runs across this.

https://www.lucd.info/2015/03/17/powercli-and-powershell-workflows/

I think `workflows` work on Powershell Desktop (5.1) and Powershell Core (6+)

Support for the PSv7 feature Foreach -Parallel | VMware PowerCLI

Thanks LucD​!!