MartinGC94 / DisplayConfig

PowerShell module for configuring Windows display settings
MIT License
45 stars 2 forks source link

Intermittent Parameter Error When Switching Display Profiles #4

Closed Rtw915 closed 2 months ago

Rtw915 commented 3 months ago

Issue Description: When running version 1.1.1, I encounter the following error about once per week, which requires me to manually adjust the screens and recreate the profiles.

Error Details:

PSMessageDetails      : 
Exception             : System.ComponentModel.Win32Exception (0x80004005): The parameter is incorrect
                           at MartinGC94.DisplayConfig.API.DisplayConfig.ApplyConfig(SetDisplayConfigFlags flags)
                           at MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand.ProcessRecord()
TargetObject          : MartinGC94.DisplayConfig.API.DisplayConfig
CategoryInfo          : InvalidArgument: (MartinGC94.Disp...I.DisplayConfig:DisplayConfig) [Use-DisplayConfig], Win32Exception
FullyQualifiedErrorId : UseDisplayConfigError,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 5
PipelineIterationInfo : {}

PS C:\WINDOWS\system32> $Error.InvocationInfo

MyCommand             : Use-DisplayConfig
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 5
OffsetInLine          : 46
HistoryId             : 1
ScriptName            : 
Line                  :     Import-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -AllowChanges

PositionMessage       : At line:5 char:46
                        + ... ort-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -AllowChanges
                        +                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot          : 
PSCommandPath         : 
InvocationName        : Use-DisplayConfig
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition : 

Script Snippet:

$CurrentDisplayConfig = Get-DisplayConfig

if ((Get-DisplayInfo | Where-Object { $_.Active -eq $true }).Count -ge 3) {
    $CurrentDisplayConfig | Export-Clixml $home\4ScreensProfile.xml
    Import-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -AllowChanges
} elseif ((Get-DisplayInfo | Where-Object { $_.Active -eq $true }).Count -eq 1) {
    $CurrentDisplayConfig | Export-Clixml $home\1ScreenProfile.xml
    Import-Clixml $home\4ScreensProfile.xml | Use-DisplayConfig -AllowChanges
}

Environment Details:

Frequency and Pattern:

Steps to Reproduce:

  1. Use the provided PowerShell script to switch display profiles.
  2. After a few switches between profiles, the error occurs.

Temporary Workarounds:

Question: Why is this error occurring?

MartinGC94 commented 3 months ago

Seems like something changes in your environment that invalidates the old config files. Next time it happens you should manually fix the setup and export a new config file and then compare the old and new config file and see what's different. You can also post the files here and I can take a look at them.

Rtw915 commented 3 months ago

Good idea! I compared the two files, but I don't quite understand the differences. I had to change the file extensions to upload them to GitHub.

1ScreenProfile.txt 1ScreenProfileOldBusted.txt

Maybe this has somethiing to do with it? https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-displayconfig_path_target_info#members

Do you think I should update the config file on line 546 to this?

<ToString>DISPLAYCONFIG_TARGET_FORCIBLE</ToString>
<U32>2</U32>
MartinGC94 commented 3 months ago

You are using HDMI. "Forcing" a display is exclusive to analog signals like VGA as far as I can tell, see: https://github.com/MicrosoftDocs/windows-driver-docs/blob/staging/windows-driver-docs-pr/display/forced-versus-connected-targets.md

All analog target types are considered forceable, and all digital targets are not considered forceable.

I suspect the issue is caused by me not handling your cloned display properly. I remember having to reset some IDs in the Enable-Display command code when changing from cloned to extended so it's likely a similar problem here. I'll dig deeper and get back to you in a couple of days.

MartinGC94 commented 3 months ago

Sorry, I didn't look close enough at your PowerShell code. You need to use the -UpdateAdapterIds in Use-DisplayConfig to reliably import exported configurations as the adapter LUIDs may change whenever the system is rebooted. AllowChanges is also redundant because the config should contain the exact refresh rate values. Try this snippet instead:

$CurrentDisplayConfig = Get-DisplayConfig
$DisplayCount = (Get-DisplayInfo | Where-Object -Property Active -EQ $true).Count
if ($DisplayCount -ge 3)
{
    $CurrentDisplayConfig | Export-Clixml $home\4ScreensProfile.xml
    Import-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds
} elseif ($DisplayCount -eq 1)
{
    $CurrentDisplayConfig | Export-Clixml $home\1ScreenProfile.xml
    Import-Clixml $home\4ScreensProfile.xml | Use-DisplayConfig -UpdateAdapterIds
}

Try it out and let me know how it goes.

Rtw915 commented 3 months ago

I appreciate your help, but unfortunately, it's now completely broken. I'm encountering the same error in both directions, with only the line number differing. Additionally, all five screens are set to extend, not duplicate (clone). Also, I realize that I labeled the configuration for four screens, but that was because I forgot to include the laptop screen in the count.

It's probably worth noting that I haven't rebooted in 15 days, but this issue has occurred at least three times during that period. The laptop is almost always plugged in and is set to never sleep or hibernate, although the screens do turn off after 5 minutes of inactivity.

Error Details:

PSMessageDetails      : 
Exception             : System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
                           at System.ThrowHelper.ThrowKeyNotFoundException()
                           at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
                           at MartinGC94.DisplayConfig.API.DisplayConfig.UpdateAdapterIds()
                           at MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand.ProcessRecord()
TargetObject          : MartinGC94.DisplayConfig.API.DisplayConfig
CategoryInfo          : NotSpecified: (MartinGC94.Disp...I.DisplayConfig:DisplayConfig) [Use-DisplayConfig], KeyNotFoundException
FullyQualifiedErrorId : AdapterUpdateError,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, C:\Users\Ryan\Documents\Screens.ps1: line 5
PipelineIterationInfo : {}

PS C:\Windows\System32\WindowsPowerShell\v1.0> $error.InvocationInfo
MyCommand             : Use-DisplayConfig
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 5
OffsetInLine          : 46
HistoryId             : 57
ScriptName            : C:\Users\Ryan\Documents\Screens.ps1
Line                  :     Import-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds

PositionMessage       : At C:\Users\Ryan\Documents\Screens.ps1:5 char:46
                        + ... Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds
                        +                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot          : C:\Users\Ryan\Documents
PSCommandPath         : C:\Users\Ryan\Documents\Screens.ps1
InvocationName        : Use-DisplayConfig
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition : 

1ScreenProfile.txt 4ScreensProfile.txt

MartinGC94 commented 3 months ago

The issue you had in your 1ScreenProfile.txt and 1ScreenProfileOldBusted.txt profiles was because the DisplayId order had changed. This was because I didn't take multiple display adapters into account. This has been fixed and you can try it out with the changes I've made in my dev branch: https://github.com/MartinGC94/DisplayConfig/tree/Dev note however that you need to create new profiles from scratch because the old ones will have a different order. Also note that you still need to use the UpdateAdapterIds parameter I mentioned before.
If you don't want to build locally I will also attach the dll to this comment and you can just download and import that one: import-module C:\PathTo.Dll. DisplayConfig.txt
rename to .dll and check that the MD5 hash matches 7939B14F1B791E1BE237E2C7AAB985AD

I cannot reproduce the KeyNotFoundException error you posted most recently but it seems quite strange. The dictionary is built using the available paths so I guess it happens when I'm looping over the ModeArray? https://github.com/MartinGC94/DisplayConfig/blob/main/src/DisplayConfig/API/DisplayConfig.cs#L886 seems weird that the mode array would contain an adapter not in the path array. I could presumably solve this problem by also looping through the ModeArray when creating the old -> new adapter mappings. However, I'd like to get 2 sample profiles where I can see this for myself before I make any changes here. So if you see this error again, make sure to send me a before and after display profile where you've fixed it manually.

So try my most recent changes for a week or two and report back if you experience any issues. If I don't hear anything I will assume it's good and make an official release.

Rtw915 commented 3 months ago

I appreciate your help so far. I deleted the existing configuration XML files and started fresh by removing the old module and importing the development version. However, I might have missed something because it’s still not working as expected.

Using the same code as before, with -UpdateAdapterIds, I encountered this error:

Use-DisplayConfig : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:42
+ ... Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds
+                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (MartinGC94.Disp...I.DisplayConfig:PSObject) [Use-DisplayConfig], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand

I also tried running it without the -UpdateAdapterIds parameter, but I got the same error.

Next, I attempted this approach:

$5ScreensProfile = Import-Clixml $home\5ScreensProfile.xml
Use-DisplayConfig -DisplayConfig $5ScreensProfile -UpdateAdapterIds

But I ran into a different error:

PSMessageDetails      : 
Exception             : System.Management.Automation.ParameterBindingException: Cannot bind parameter 'DisplayConfig'. Cannot convert value "MartinGC94.DisplayConfig.API.DisplayConfig" to type "MartinGC94.DisplayConfig.API.DisplayConfig". Error: "Cannot 
                        convert the "MartinGC94.DisplayConfig.API.DisplayConfig" value of type "Deserialized.MartinGC94.DisplayConfig.API.DisplayConfig" to type "MartinGC94.DisplayConfig.API.DisplayConfig"." ---> 
                        System.Management.Automation.PSInvalidCastException: Cannot convert value "MartinGC94.DisplayConfig.API.DisplayConfig" to type "MartinGC94.DisplayConfig.API.DisplayConfig". Error: "Cannot convert the 
                        "MartinGC94.DisplayConfig.API.DisplayConfig" value of type "Deserialized.MartinGC94.DisplayConfig.API.DisplayConfig" to type "MartinGC94.DisplayConfig.API.DisplayConfig"." ---> System.Management.Automation.PSInvalidCastException: 
                        Cannot convert the "MartinGC94.DisplayConfig.API.DisplayConfig" value of type "Deserialized.MartinGC94.DisplayConfig.API.DisplayConfig" to type "MartinGC94.DisplayConfig.API.DisplayConfig".
                           at System.Management.Automation.LanguagePrimitives.ThrowInvalidCastException(Object valueToConvert, Type resultType)
                           at System.Management.Automation.LanguagePrimitives.SetObjectProperties(Object o, PSObject psObject, Type resultType, MemberNotFoundError memberNotFoundErrorAction, MemberSetValueError memberSetValueErrorAction, IFormatProvider 
                        formatProvider, Boolean recursion, Boolean ignoreUnknownMembers)
                           at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable 
                        backupTable, Boolean ignoreUnknownMembers)
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable 
                        backupTable, Boolean ignoreUnknownMembers)
                           at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable 
                        backupTable)
                           at System.Management.Automation.LanguagePrimitives.ConvertCheckingForCustomConverter.Convert(Object valueToConvert, Type resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable 
                        backupTable)
                           at System.Management.Automation.LanguagePrimitives.ConversionData`1.Invoke(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
                           at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion, IFormatProvider formatProvider, TypeTable backupTypeTable)
                           at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
                           at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
                           at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
                           at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
                           at System.Management.Automation.CmdletParameterBinderController.BindParameters(UInt32 parameterSets, Collection`1 arguments)
                           at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
                           at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
                           at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
                           at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
                           at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
                           at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
                           at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
                        --- End of stack trace from previous location where exception was thrown ---
                           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                           at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
                           at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, 
                        FunctionContext funcContext)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          : 
CategoryInfo          : InvalidArgument: (:) [Use-DisplayConfig], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgumentNoMessage,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
MartinGC94 commented 3 months ago

My mistake. I forgot that the module had other dependencies outside of the .dll.
Copy the .dll into your existing displayconfig module folder, replacing the existing .dll. Then import the module like you normally would (either with just the name, or a path to the .psd1).

Rtw915 commented 3 months ago

Apologies for the delayed response. I encountered some challenges while trying to place the DLL in the appropriate folder due to a UAC permissions issue. After finally managing to copy it over, I'm now facing a new problem when attempting to import the module. Here’s the error I’m receiving:

PSMessageDetails      : 
Exception             : System.IO.FileLoadException: Could not load file or assembly 'file:///C:\Program 
                        Files\WindowsPowerShell\Modules\DisplayConfig\1.1.1\DisplayConfig.dll' or one of its dependencies. Operation is not 
                        supported. (Exception from HRESULT: 0x80131515)
                        File name: 'file:///C:\Program Files\WindowsPowerShell\Modules\DisplayConfig\1.1.1\DisplayConfig.dll' ---> 
                        System.NotSupportedException: An attempt was made to load an assembly from a network location which would have 
                        caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework 
                        does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the 
                        assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more 
                        information.
                           at System.Management.Automation.Runspaces.InitialSessionState.Bind_LoadAssemblies(ExecutionContext context)
                           at System.Management.Automation.Runspaces.InitialSessionState.Bind(ExecutionContext context, Boolean updateOnly, 
                        PSModuleInfo module, Boolean noClobber, Boolean local)
                           at System.Management.Automation.Runspaces.InitialSessionState.Bind(ExecutionContext context, Boolean updateOnly)
                           at Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModuleManifest(String moduleManifestPath, 
                        ExternalScriptInfo manifestScriptInfo, Hashtable data, Hashtable localizedData, ManifestProcessingFlags 
                        manifestProcessingFlags, Version minimumVersion, Version maximumVersion, Version requiredVersion, Nullable`1 
                        requiredModuleGuid, ImportModuleOptions& options, Boolean& containedErrors)

TargetObject          : 
CategoryInfo          : InvalidOperation: (:) [Import-Module], FileLoadException
FullyQualifiedErrorId : FormatXmlUpdateException,Microsoft.PowerShell.Commands.ImportModuleCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
MartinGC94 commented 3 months ago

A quick google search indicates that the error is caused by the alternative data stream that indicates that the file was downloaded from the internet. Unblock the file with Unblock-File, or right click -> Properties -> Unblock.

Rtw915 commented 3 months ago

I had a moment of oversight where I unchecked the Unblock-File box but forgot to relaunch ISE, which led to the same error reappearing.

Even after updating to the new DisplayConfig.dll, I’m still encountering the following error:

writeErrorStream      : True
PSMessageDetails      : 
Exception             : System.Management.Automation.ParameterBindingException: The input object cannot be bound to any parameters for the 
                        command either because the command does not take pipeline input or the input and its properties do not match any of 
                        the parameters that take pipeline input.
TargetObject          : MartinGC94.DisplayConfig.API.DisplayConfig
CategoryInfo          : InvalidArgument: (MartinGC94.Disp...I.DisplayConfig:PSObject) [Use-DisplayConfig], ParameterBindingException
FullyQualifiedErrorId : InputObjectNotBound,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, C:\Users\Ryan\Documents\Screens.ps1: line 5
PipelineIterationInfo : {0, 1, 0}

I also tried with this code:

$CurrentDisplayConfig = Get-DisplayConfig
$DisplayCount = (Get-DisplayInfo | Where-Object -Property Active -EQ $true).Count
if ($DisplayCount -ge 3) {
    $CurrentDisplayConfig | Export-Clixml $home\5ScreenProfile.xml
    $DisplayConfig = Import-Clixml $home\1ScreenProfile.xml
    Use-DisplayConfig -DisplayConfig $DisplayConfig -UpdateAdapterIds
} elseif ($DisplayCount -eq 1) {
    $CurrentDisplayConfig | Export-Clixml $home\1ScreenProfile.xml
    $DisplayConfig = Import-Clixml $home\5ScreenProfile.xml
    Use-DisplayConfig -DisplayConfig $DisplayConfig -UpdateAdapterIds

And I get this error:

PSMessageDetails      : 
Exception             : System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
                           at System.ThrowHelper.ThrowKeyNotFoundException()
                           at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
                           at MartinGC94.DisplayConfig.API.DisplayConfig.UpdateAdapterIds()
                           at MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand.ProcessRecord()
TargetObject          : MartinGC94.DisplayConfig.API.DisplayConfig
CategoryInfo          : NotSpecified: (MartinGC94.Disp...I.DisplayConfig:DisplayConfig) [Use-DisplayConfig], KeyNotFoundException
FullyQualifiedErrorId : AdapterUpdateError,MartinGC94.DisplayConfig.Commands.UseDisplayConfigCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, C:\Users\Ryan\Documents\Screens.ps1: line 10
PipelineIterationInfo : {}
MartinGC94 commented 3 months ago

The parameter binding error that mentions PSObject is caused by it not converting the PSObject from Import-CliXML into an actual object. There are 2 scenarios where this can happen: 1: You import the .dll directly instead of the .psd1 manifest. 2: You run Import-CliXML before importing the module (I'm guessing this is what happened in this scenario).

As for the KeyNotFoundException error, I'd like to compare a working config with a broken one. So when you see it, send me the config file that causes this error as well as a fresh config file created with Get-DisplayConfig | Export-Clixml.

Rtw915 commented 3 months ago

I’m not quite following what’s happening in your scenarios. Here’s what I did:

Get-Module
Remove-Module DisplayConfig
Get-Module
# Copied the DLL
Import-Module "C:\Program Files\WindowsPowerShell\Modules\DisplayConfig\1.1.1\DisplayConfig.psd1"
Get-Module

However, now the KeyNotFoundException error occurs every time, and the script no longer functions as expected.

1ScreenProfile.txt

MartinGC94 commented 3 months ago

I think I have found the cause of the KeyNotFoundException and have added a workaround. As far as I can tell it only happens if you happen to have an adapter that isn't used for any displays. Here's the compiled fix: DisplayConfig.txt Same procedure as before: Download, unblock, check hash and copy into the module folder. MD5 hash: 85B1666F451D651487D04A5FDFF3A575

Rtw915 commented 3 months ago

Great news! Everything is working again. For completeness, here's the code I ran that succeeded without needing to recreate the screen profiles from yesterday's attempt:

$CurrentDisplayConfig = Get-DisplayConfig
$DisplayCount = (Get-DisplayInfo | Where-Object -Property Active -EQ $true).Count
if ($DisplayCount -ge 3) {
    $CurrentDisplayConfig | Export-Clixml $home\5ScreenProfile.xml
    $DisplayConfig = Import-Clixml $home\1ScreenProfile.xml
    Use-DisplayConfig -DisplayConfig $DisplayConfig -UpdateAdapterIds
} elseif ($DisplayCount -eq 1) {
    $CurrentDisplayConfig | Export-Clixml $home\1ScreenProfile.xml
    $DisplayConfig = Import-Clixml $home\5ScreenProfile.xml
    Use-DisplayConfig -DisplayConfig $DisplayConfig -UpdateAdapterIds
}

I also tried uising the pipeline, and that was successfull too!

$CurrentDisplayConfig = Get-DisplayConfig
$DisplayCount = (Get-DisplayInfo | Where-Object -Property Active -EQ $true).Count
if ($DisplayCount -ge 3) {
    $CurrentDisplayConfig | Export-Clixml $home\5ScreenProfile.xml
    Import-Clixml $home\1ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds
} elseif ($DisplayCount -eq 1) {
    $CurrentDisplayConfig | Export-Clixml $home\1ScreenProfile.xml
    Import-Clixml $home\5ScreenProfile.xml | Use-DisplayConfig -UpdateAdapterIds
}

Thank you so much for resolving this issue and dedicating your time to help. Since the original problem was intermittent, would it be possible to keep this ticket open for 7 days to ensure consistent reliability? Or do you believe the solution has fully addressed the issue?

MartinGC94 commented 3 months ago

Excellent. I'm going to leave it alone for a week or two and if I don't hear anything from you I'll merge the changes into main and make a new release.

MartinGC94 commented 2 months ago

This has been fixed in the 2.0 release. I've already published it to the gallery so you can update to the latest version with Update-Module DisplayConfig. I'd advice you to also update to this version as it includes some other fixes in addition to the ones you already have.