简体   繁体   中英

Run Powershell script in C# to enable keyboardfilter

I have a problem that I just don't know what else to try to get it solved. I am on a Windows 10 Enterprise 2016 machine and am trying to enable filtering of keyboard shortcuts using WMI (WEKF_PredefinedKey).

I have created a Powershell skript, that does just what I want when being run by rightmousebutton -> Run with PowerShell:

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

function Disable-Predefined-Key($Id) {
$predefined = Get-WMIObject -class WEKF_PredefinedKey @CommonParams |
              where {
                $_.Id -eq "$Id"
              };

if ($predefined) {
    $predefined.Enabled = 1;
    $predefined.Put() | Out-Null;
    Write-Host Disabled $Id
    }
else {
    Write-Host $Id is not a valid predefined key
    }
}

Disable-Predefined-Key "Win+E"

After running this script, the shortcut "Win+E" is disabled as excpected.

Now the problem: I need to run this script from a C# WPF application. But whatever I do, I can't get the shortcut disabled in any way from C#.

What I have tried (Logged in as administrator AND included a manifest file with requestedExecutionLevel level="requireAdministrator" in all of the following cases just to be dead sure I have the correct credentials):

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"powershell.exe";
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.Arguments = Properties.Settings.Default.DisableKey;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();

And:

using (PowerShell PowerShellInstance = PowerShell.Create())
{             
  PowerShellInstance.AddScript(@"C:\Users\Administrator\Desktop\Newfolder\disablekey.ps1", false);             
  Collection<PSObject> PSOutput = PowerShellInstance.Invoke();

  foreach (PSObject outputItem in PSOutput)
  {
    if (outputItem != null)
    {
      //TODO: do something with the output item 
    }
  }
}

I also tried to parse the content of the script into a string and try to execute this with on a PowerShell object. I have also tried pretty much any thinkable way between the above mentioned methods, but nothings seems to take effect. The first method opens up a Powershell window and for a blink of an eye I can see the output, which is "Enabled Win+E", so the script seems to have run at least. However Win+E is still active.

What leaves me puzzled even more is, that the following code to enable/ disable the UWF filter (also WMI, also administrator rights needed) works just fine:

using (PowerShell PowerShellInstance = PowerShell.Create())
{
 PowerShellInstance.AddScript(Properties.Settings.Default.EnableUWF);
 // [0] = result or error
 var result = PowerShellInstance.Invoke();
}

With the following value for the EnableUWF setting:

$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}

Remark: Setting the ExecutionPolicy in the Keyboardfilter script does not make any difference (not even unrestriced). Installed PowerShell Version: Major 5 Minor 1 Build 14393 Revision 1944

Hopefully someone can help me with this problem.

Instead of using PowerShell, I would recommend using the native WMI library for C# in your WPF application. First, download System.Management via NuGet. Then create a new class for your KeyboardFilter

using System.Management;

namespace YourWPFApp
{
    public class KeyboardFilter
    {
        public static void DisablePredfinedKey(string keyId)
        {
            ManagementScope scope = new ManagementScope
            {
                Path = new ManagementPath
                {
                    NamespacePath = @"root\standardcimv2\embedded",
                    ClassName = "WEKF_PredefinedKey"
                }
            };
            ManagementClass wekfPredefinedKey = new ManagementClass(scope.Path);
            var output = wekfPredefinedKey.InvokeMethod("Enable", new object[] { keyId });
        }
    }
}

Then call your DisablePredefinedKeys method from your ViewModel or CodeBehind.

KeyboardFilter.DisablePredfinedKey("Win+E");

Note: I haven't tested this on Windows 10

This has been tested on Windows 10 Enterprise.

Note: be sure to compile with "Prefer 32-bit" turned off if running on a 64 bit system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM