-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PowershellDirect on Windows Server 2016: Invoke-Command -VMName 'blah' fails with Unable to cast object of type 'System.String' to type 'VMState'. #14738
Comments
Looking at the code there are 2 places where this could occur PowerShell/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs Line 942 in 3c7f4b5
PowerShell/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs Line 1007 in c7bdb24
They are both trying to cast the |
Just to clarify impact and what I'm looking for. Impact: blocking ability to ship new version of internal tool. We've update the tool's codebase from .NET 4.7 to .NET 5, which necessitated switching to PowerShell Core SDK from older Powershell SDK. Since we have to support Win 2016, Win 2019 and Win 10 OS, we cannot ship the new version of the tool What I'm looking for: some sort of work around to get past the issue. Please let me know if I can do anything to help root cause it and look for workaround. Would love to unblock my project as soon as possible. |
I'm not sure you can fix this without changing the PowerShell code. Maybe to start off could you share the output of the following (in both Windows PowerShell and PowerShell): $vm = @(Get-VM -VMName MyLocalVMName)[0]
$vm.State
$vm.State.GetType().FullName Comparing that between 2016 and 2019 guests would also help to potentially track down what is happening. |
$vm = @(Get-VM)[0]
$vm.State
$vm.State.GetType().FullName $vm.State is 'Running' in all the cases. Datatype is like this:
|
Cool so that code is definitely problematic, I just don't understand why Server 2016 on PowerShell is a string but not for Windows PowerShell. I would have to look at the code to see what it is doing to give you a better answer. In short I think the PowerShell code needs to be a bit more defensive here but it's still an interesting problem. |
I'd be happy to try a private fix of Powershell SDK. I personally used nested virtualization: Win 10 host -> Win 2016 server [for repro] -> Win 2019 guest, but I guess any VM will do |
I'm guessing the 2016 version is using implicit remoting (or w/e the automatic wincompat layer is called, I forget) due to the HyperV module not getting the |
Ahh I was assuming |
This workaround worked, thank you! PS C:\Users\ayeltsov> Import-Module Hyper-V -SkipEditionCheck
PS C:\Users\ayeltsov> (@(Get-VM)[0]).State.GetType().FullName
Microsoft.HyperV.PowerShell.VMState Let's see if this onion has more layers... |
Definitely more layers in this onion. Same workaround needed for this: (Get-VM ayeltsov-336442) | Get-VMNetworkAdapter
Get-VMNetworkAdapter: The specified wildcard character pattern is not valid: VirtualMachine (Name = 'ayeltsov-336442') [Id = '69d6d3ef-09d1-4682-8b2a-b6e2cf44c593'] Question: is there a way to hint "-SkipEditionCheck" globally so that I don't change all the scripts that app is using? In case it matters, I use powershell from c#: using (PowerShell powerShell = PowerShell.Create())
{
InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
initialSessionState.ExecutionPolicy = ExecutionPolicy.RemoteSigned;
powerShell.Runspace = RunspaceFactory.CreateRunspace(initialSessionState);
powerShell.Runspace.Open();
<...>
powerShell.Invoke<PSObject, PSObject>(executionInputCollection, outputCollection, new PSInvocationSettings());
<...>
} |
You could try If you control the environment you could edit the manifests yourself to add Last resort if you're desperate would be hooking into command lookup via |
@SeeminglyScience , FYI, the workaround with Import-Module:SkipEditionCheck did actually work (please don't break it in the next SDK :-)) Just for reference: if (IsWindows2016.Value)
{
System.Collections.Hashtable psDefaultParameterValues =
(System.Collections.Hashtable)powerShell.Runspace.SessionStateProxy.GetVariable("PSDefaultParameterValues");
psDefaultParameterValues["Import-Module:SkipEditionCheck"] = true;
}
private static readonly Lazy<bool> IsWindows2016 = new (
() =>
{
// Weirdly, ProductName reg key is easiest way to distinguish Server 2016 and Server 2019.
// It's not exposed via things like System.Environment.OSVersion
// Example values: "Windows 10 Enterprise" "Windows Server 2016 Datacenter"
string productName = (string)Registry.GetValue(
@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion",
valueName: "ProductName",
defaultValue: null);
return productName?.Contains("Server 2016", StringComparison.OrdinalIgnoreCase) ?? false;
}); |
@ayeltsov honestly with a C# application, you're probably better off always including that parameter in Core. Unless you're incredibly careful in your usage of returned objects (i.e. never statically typing them), wincompat mode is going to break you regardless. Another side note, |
Unfortunately, it seems that the original issue is "by-design". If a Windows inbox module manifest does not include |
Ack. We're ok with workaround, and will probably speed up deprecation of Server 2016 as a supported host. |
Steps to reproduce
Expected behavior
Actual behavior
Environment data
Notes:
The text was updated successfully, but these errors were encountered: