Repository navigation
Return the deserialized object when CIM classes cannot be rehydrated - #28192
Nova-Logic wants to merge 2 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟢 Approval recommended
The fallback is narrowly scoped, thread-safe, and covered by an appropriate cross-platform regression test.
0 open findings
What changed in this PR
Prevents CIM deserialization from failing when the native MI library is unavailable, preserving deserialized property bags instead.
Changes:
- Gracefully handles native CIM deserializer initialization failures.
- Caches deserializer unavailability to avoid repeated attempts.
- Adds cross-platform regression coverage and CIM CliXml fixture.
| File | Description |
|---|---|
src/System.Management.Automation/engine/serialization.cs |
Adds fallback handling for unavailable CIM rehydration. |
test/powershell/engine/Api/Serialization.Tests.ps1 |
Verifies CIM data remains accessible after deserialization. |
test/powershell/engine/Api/assets/CimInstance-Win32_TimeZone.clixml |
Provides serialized CIM class metadata for testing. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Deserializing a CIM instance rehydrates its CIM class through the native MI library. Where that library is not available (for example macOS, which ships no libmi), loading CimDeserializer throws DllNotFoundException. RehydrateCimClass only caught CimException, so the whole deserialization failed - e.g. Invoke-Command against a Windows host running any CIM-based cmdlet (Get-StorageQoSFlow, Get-Disk, ...) failed from macOS. Treat an unavailable CIM deserializer like any other rehydration failure: keep the deserialized property bag, as RehydrateCimInstance already does when the class cannot be rehydrated, and remember the failure so the native load is not retried for every object.
4623748 to
0c41b87
Compare
|
I encountered this problem when testing PSWSMan and I just patched out the CIM deserialization process on non-Windows client https://github.com/jborean93/PSWSMan/blob/main/src/PSWSMan/Patches/InternalDeserializer.cs#L15-L51. This patching is definitely not an option so would be great to see this fix landing in PowerShell and I can drop the patch. I did also drop the As for workarounds in the Invoke-Command -HostName win-host { Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$pid" }
# OperationStopped: Unable to load shared library 'libmi' or one of its dependencies. In order to help diagnose loading problems, consider using a tool like strace. If you're using glibc, consider setting the LD_DEBUG environment variable:
# /home/jborean/.local/powershell/libmi.so: cannot open shared object file: No such file or directory
# /home/jborean/.local/powershell/liblibmi.so: cannot open shared object file: No such file or directory
# /home/jborean/.local/powershell/libmi: cannot open shared object file: No such file or directory
# /home/jborean/.local/powershell/liblibmi: cannot open shared object file: No such file or directory
Invoke-Command -HostName win-host { Get-CimInstance -ClassName Win32_Process -Filter "ProcessId=$pid" | Select-Object *}
# ProcessName : pwsh.exe
# Handles : 523
# ...This isn't great but it gets you moving forward if you need such objects back.
|
The serializer attaches __ClassMetadata and __InstanceMetadata as hidden note properties, but the hidden flag is not serialized, so when the instance falls back to the deserialized property bag the metadata showed up in Select-Object * and Format-List *. Hide it again on every fallback path. It is kept, so serializing the object again still carries it and a receiver that can rehydrate CIM instances gets a CimInstance.
|
Thanks, glad this would let you drop the patch in PSWSMan. Good point about The serializer already adds both as hidden note properties, only the hidden flag doesn't survive serialization. So f2033dd hides them again on every fallback path (including the existing And thanks for the |
PR Summary
Deserializing a CIM instance (CliXml with
__ClassMetadata) rehydrates its CIM class through the native MI library. On platforms where that library is not available - macOS ships nolibmi- creatingCimDeserializerthrowsDllNotFoundException.InternalDeserializer.RehydrateCimClassonly catchesCimException, so the exception escapes and the whole deserialization fails, althoughRehydrateCimInstanceis designed to fall back to the deserialized property bag when a class cannot be rehydrated.This PR treats an unavailable CIM deserializer like any other rehydration failure:
RehydrateCimClassreturnsnull,RehydrateCimInstancereturns the deserialized object (Deserialized.Microsoft.Management.Infrastructure.CimInstance#...) with all its properties, and the failure is remembered so the native load is not retried for every object.Repro on macOS (7.5.4 release and current
master):With this change both return the object with its properties (e.g.
Bias,Caption), typed asDeserialized.Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_TimeZone.PR Context
Managing Windows servers from macOS over SSH remoting is common, and many Windows cmdlets return CIM instances (
Get-StorageQoSFlow,Get-Disk,Get-Volume,Get-NetAdapter, ...). Today none of them can be used from a macOS client: the call fails instead of returning deserialized objects, which is what PowerShell already returns whenever CIM rehydration is not possible for any other reason.Behaviour where the MI library is available (Windows, Linux) is unchanged: CIM instances are still rehydrated.
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerTest added to
test/powershell/engine/Api/Serialization.Tests.ps1with the assetassets/CimInstance-Win32_TimeZone.clixml(aWin32_TimeZoneinstance serialized on Windows with class metadata). It asserts the deserialized object's properties and type name, so it passes both where the instance is rehydrated (Windows, Linux) and where it is not (macOS). On macOS it fails with 7.5.4 ("Unable to load shared library 'libmi'") and passes with this change. Also verified manually from macOS:Invoke-Commandto a Windows Server 2022 host runningGet-StorageQoSFlownow returns the flows instead of failing.