0

I have an application, that allows the user to configure basic WMI settings on a Win 10 IoT machine.

I am currently struggling with reading all WEKF_PredefinedKey settings, that are enabled. I am simply running a skript, that I added as string to the project settings named ReadEnabledKeys:

$CommonParams = @{"namespace"="root\standardcimv2\embedded"}
$CommonParams += $PSBoundParameters

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned;
     $keys = Get-WMIObject -class WEKF_PredefinedKey @CommonParams
        foreach($k in $keys) 
        {
            if($k.Enabled -eq $false)
            {
             "$k";
            }
        }

My call in C# code looks like this (Note: using System.Management.Automation):

 using (PowerShell PowerShellInstance = PowerShell.Create())
        {
          PowerShellInstance.AddScript(Properties.Settings.Default.ReadEnabledKeys);          
          var result = PowerShellInstance.Invoke();
        } 

My variable result will always stay empty. If I run the skript in Powershell directly, the output is just fine (all shortcuts, that are currently not disabled).

I have something similar programmed with the unified write filter, where I enable and disable it:

$COMPUTER = "localhost"
$NAMESPACE = "root\standardcimv2\embedded"

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned;
$objUWFInstance = Get-WMIObject -namespace $NAMESPACE -class UWF_Filter;
$retval = $objUWFInstance.Enable();
if ($retval.ReturnValue -eq 0) {"Unified Write Filter will be enabled after the next system restart."}
else {"Unknown Error: " + "{0:x0}" -f $retval.ReturnValue}

And the C# call:

 using (PowerShell PowerShellInstance = PowerShell.Create())
        {
          PowerShellInstance.AddScript(Properties.Settings.Default.EnableUWF);

          // [0] = result or error
          var result = PowerShellInstance.Invoke();
          if (result[0].ToString().ToLower().Contains("enabled"))
            MessageBox.Show(result[0].ToString(), "", MessageBoxButton.OK, MessageBoxImage.Information);
          else
            MessageBox.Show("Error when enabling the filter!  " + Environment.NewLine + result[0].ToString(), "",
                            MessageBoxButton.OK, MessageBoxImage.Error);
        }

Here my result variable will be filled with the expected strings.

I have tried Write-Host $k, as I suspected something wrong with the stream, but this was without any success.

The output in Powershell looks like this:

PS C:\Users\Administrator> C:\Users\Administrator\Desktop\Newfolder\Untitled1.ps1
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Alt"\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Application"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+Esc"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+F4"
\\DESKTOP-RMGOBMG\root\standardcimv2\embedded:WEKF_PredefinedKey.Id="Ctrl+Tab"
.
.
.

Can anyone tell me, what the problem is?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
christian
  • 110
  • 1
  • 2
  • 15
  • `Properties.Settings.Default.ReadEnabledKeys` where is this defined? And why do this in powershell instead of querying wmi through C#? – Maximilian Burszley Jul 31 '18 at 12:08
  • I edited the question, but this property is just a string in the project settings, that holds the content of the skript that I want to execute. – christian Jul 31 '18 at 12:11

1 Answers1

0

The problem appears to be with your script. Setting the ExecutionPolicy midstream doesn't do anything and you aren't writing a function so adding $PSBoundParameters also doesn't do anything. Here's an example that should work (I'd specify PS version in the future. I know you're on v5.1/win10 due to keyboard filtering)

$collection = [System.Collections.Generic.List[string]]::new()
foreach ($key in (Get-CimInstance -Namespace 'root\standardcimv2\embedded' -ClassName WEKF_PredefinedKey)) {
    if (-not $key.Enabled) {
        $collection.Add($key.ToString())
    }
}
return $collection

(simplified)

@(Get-CimInstance -Namespace root\standardcimv2\embedded -ClassName WEKF_PredefinedKey).
    Where{-not $_.Enabled}.
    ForEach('ToString')

Example:

using (PowerShell ps = PowerShell.Create())
{
    string script = @"Import-Module -Name C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1 -ErrorAction Stop; @(Get-WmiObject -Namespace root\standardcimv2\embedded -Class WEKF_PredefinedKey -ErrorAction Stop).Where{-not $_.Enabled}.ForEach('ToString')";
    ps.AddScript(script);
    var result = ps.Invoke();
}
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • First up, thank you for your quick answer. I added the ExecutionPolicy to make sure, that the script runs with administrative rights, at least for the uwf filter this is needed. You were absolutely right about the BoundParameters, those were a leftover. Your skript runs fine in my Powershell, id generates a slighty different formatted output than mine did. However, i still cant read that output in C# code. Edit: I can indeed read from the Invoke command, but it leaves me with an empty string. – christian Jul 31 '18 at 12:26
  • 1
    @christian and it populates in a powershell console? `ExecutionPolicy` does not determine rights; it's a separate concept. Have you tried removing the if statement and returning the entire collection of keys to see if anything is returned? – Maximilian Burszley Jul 31 '18 at 12:48
  • $collection = [System.Collections.Generic.List[string]]::new() foreach ($key in (Get-CimInstance -Namespace 'root\standardcimv2\embedded' -ClassName WEKF_PredefinedKey)) { "$key" } creates the same output in the Powershell as the skript you suggested. However when trying to assign PowerShell.Invoke() with the above skript to a variable, this variable will be an empty Collection. – christian Jul 31 '18 at 12:56
  • 1
    That sounds like an issue with how you're accessing the string. Have you considered adding the string to the code and testing it? I'll update my answer with an example @christian – Maximilian Burszley Jul 31 '18 at 13:02
  • I have edited your example, as assigning Collection to a string[] does not work without casting. Sadly this still leaves me with an empty result. I appreciate your effort so far. – christian Jul 31 '18 at 13:17
  • 1
    @christian You've set a breakpoint and result is populating with nothing? This is so bizarre. I don't have that class enabled to test returns unfortunately. And you get an empty collection if you remove the `Where` filter even? – Maximilian Burszley Jul 31 '18 at 13:23
  • Correct, I have set a breakpoint at var result = ps.Invoke. I get a valid Collection which has Count = 0, thus it is empty. This is driving me crazy right now, I needed to set up a Win 10 IoT machine here, as this filters are not provided with a VM either, so I understand, you cant test this. Edit: Removing the where filter does not make any difference. – christian Jul 31 '18 at 13:31
  • 1
    Have you considered adding `-ErrorAction Stop` to the parameter list to see if an exception isn't falling through/being ignored? – Maximilian Burszley Jul 31 '18 at 13:35
  • 1
    Just did that, and there seems to System.Management.Automation.ItemNotFoundException: 'Cannot find path 'C:\Users\Administrator\Documents\WindowsPowerShell\Modules' because it does not exist.' ----- And this one: ----- System.Management.Automation.ItemNotFoundException: 'Cannot find path 'C:\Windows\system32\WindowsPowerShell\v1.0\Modules\CimCmdlets\Microsoft.Management.Infrastructure.CimCmdlets' because it does not exist.' Leaves me a bit puzzled to be honest. – christian Jul 31 '18 at 13:56
  • 1
    @christian What version of powershell are you on when testing this? – Maximilian Burszley Jul 31 '18 at 13:58
  • Major 5 Minor 1 Build 14393 Revision 1944 – christian Jul 31 '18 at 14:01
  • Ok, it seems, like the skript is failing somewhere within the foreach. If I put a "Test" at the beginning of the skript, I get this as a result in my C# code. – christian Jul 31 '18 at 14:28
  • 1
    @christian Your module auto-finding isn't working. I've updated the example in my answer to import the module needed and moved away from the cim cmdlets since something on your test box is weird. – Maximilian Burszley Jul 31 '18 at 14:53
  • Thank you for your help so far, I will test this tomorrow as soon as I am at the machine again, if this was the problem, it definately was a easy to find one for a PS beginner. I will let you know, as soon as I have news, thank you once again! – christian Jul 31 '18 at 18:07
  • Ok, just tested the example, I get the following exception: ---------- "The running command stopped because the preference variable \"ErrorActionPreference\" or common parameter is set to Stop: Provider load failure " if I dig a bit deeper I find ErrorRecord -> CategoryInfo {InvalidOperation: (:) [Get-WmiObject], ManagementException} System.Management.Automation.ErrorCategoryInfo ---------- I dont understand, why this is a problem with the WEKF, loading a WMI object works with the UWF Filter, as described in my question above – christian Aug 01 '18 at 06:26
  • UPDATE: Semms like Im not the only one with this problem, whoever finds a solution might be able to hit two birds with one stone in terms of reputation: https://stackoverflow.com/questions/49322437/provider-load-failure-during-installation-process I do not mind any other way of configuring the keyboardfilter, if the scriptingway is just not working, this was just the only way I found in the microsoft online documentation. – christian Aug 01 '18 at 06:41
  • And another Update: When I try to go the C# way with: ManagementClass KeyBoardFilter = new ManagementClass(scope.Path.Path, "WEKF_Settings", null); I get a provider load exception when calling: foreach(ManagementObject mo in KeyBoardFilter.GetInstances()) {do sth with obj} – christian Aug 01 '18 at 09:56