在 C# 中运行 Powershell 脚本以启用键盘过滤器

Posted

技术标签:

【中文标题】在 C# 中运行 Powershell 脚本以启用键盘过滤器【英文标题】:Run Powershell script in C# to enable keyboardfilter 【发布时间】:2019-01-09 22:49:25 【问题描述】:

我有一个问题,我只是不知道还有什么办法可以解决它。 我在 Windows 10 Enterprise 2016 机器上,正在尝试使用 WMI (WEKF_PredefinedKey) 启用键盘快捷键过滤。

我创建了一个 Powershell 脚本,它在通过鼠标右键运行时可以满足我的需求 -> 使用 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"

运行此脚本后,快捷键“Win+E”按预期禁用。

现在的问题: 我需要从 C# WPF 应用程序运行此脚本。 但无论我做什么,我都无法从 C# 中以任何方式禁用快捷方式。

我尝试过的(以管理员身份登录并在以下所有情况下都包含了一个带有 requestedExecutionLevel level="requireAdministrator" 的清单文件,只是为了确保我拥有正确的凭据):

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();

还有:

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 
    
  

我还尝试将脚本的内容解析为字符串,并尝试在 PowerShell 对象上执行此操作。 我也在上述方法之间尝试了几乎任何可以想到的方法,但似乎没有任何效果。 第一种方法打开一个Powershell窗口,一眨眼我就可以看到输出,即“Enabled Win+E”,所以脚本似乎至少已经运行了。 但是 Win+E 仍然有效。

让我更困惑的是,以下用于启用/禁用 UWF 过滤器(也是 WMI,还需要管理员权限)的代码工作正常:

using (PowerShell PowerShellInstance = PowerShell.Create())

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

EnableUWF 设置具有以下值:

$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

备注: 在 Keyboardfilter 脚本中设置 ExecutionPolicy 没有任何区别(甚至没有限制)。 安装的 PowerShell 版本: 专业 5 未成年人1 构建 14393 1944 年修订

希望有人能帮我解决这个问题。

【问题讨论】:

【参考方案1】:

我建议您在 WPF 应用程序中使用 C# 的本机 WMI 库,而不是使用 PowerShell。 首先,通过 NuGet 下载System.Management。 然后为您的 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 );
        
    

然后从您的 ViewModel 或 CodeBehind 调用您的 DisablePredefinedKeys 方法。

KeyboardFilter.DisablePredfinedKey("Win+E");

注意:我没有在 Windows 10 上测试过这个

这已在 Windows 10 企业版上进行了测试。

注意:如果在 64 位系统上运行,请务必关闭“首选 32 位”进行编译。

【讨论】:

感谢您的这篇文章。我用 UWF 过滤器做了同样的事情,它工作得很好,当我用键盘过滤器尝试同样的事情时,我一定搞砸了,这让我非常绝望,我想要丑陋的 PowerShell 方式。

以上是关于在 C# 中运行 Powershell 脚本以启用键盘过滤器的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 异步运行多个 PowerShell 脚本

如何从 C# 程序运行 PowerShell 脚本?

C# 中未获取 Powershell 结果集

在 C# 中使用不同的凭据调用远程 powershell 脚本

从 C# 应用程序的脚本中调用 PowerShell 函数

将 C# 转换为涉及 DllImport 的 Powershell