dotnet 职业技术学院

PowerShell

dotnet 职业技术学院

| powershell

按类别查找文章:PowerShell


uwp dotnet dotnet-core dotnet-standard csharp 技术 gif解析 wpf windows C# WPF D2D DirectX UWP DirectComposition win2d SharpDX VisualStudio dotnetremoting rpc visualstudio Win10 编程 slack web team msbuild linux xamarin ios resharper git nuget xaml algorithm ime vscode directx roslyn markdown ui ux miscellaneous cpp sharpdx algorithms JavaScript Unicode c# 工具 系统 架构 编译 数学 几何 C#入门 原理 Powershell 性能测试 命令行 asp aspdotnetcore dotnetcore 控制台 WMI .net framework .net源代码 源代码分析 Latex C 算法 Emit Roslyn MSBuild 编译器 调试 渲染 Resharper 打包 Pandoc PowerShell VisualStudio插件 TotalCommander 软件 Jenkins gif await 安装包 InnoSetup 触摸 WPF调试 图片处理 黑科技 UI sublimetext usb 笔迹 输入法 数据库 sqlite Framework dotnetframework remoting 布局 mvvm frp Avalonia 设计规范 规范 反射 jekyll DevOps AzureDevOps 源代码 多线程 VisualStudio调试 doevents 性能优化 水印 uwp文件 pip python 软件设计 文档 docfx 资源分享 p2p 爬虫 SublimeText AE dotpeek 反编译 btsync pandoc Telegram 聊天软件 微信 P2P PPT v8 .NET JVM Direct2D MobaXterm 代理 ssh vps 代理服务器 mock 单元测试 NuGet dnc 进程通信 IPC pipe ScrollViewer WPF源代码 ink dotnettool tool Github GithubAction Diagnostics DUMP Xamarin GTK
2019
12-08 2019

可集成到文件管理器,一句 PowerShell 脚本发布某个版本的所有 NuGet 包

要发布 NuGet 包,只需要执行命令 nuget push xxx.nupkg 即可,或者去 nuget.org 点鼠标上传。

不过,如果你有很多的 NuGet 包并且经常需要推送的话,也可以集成到 Directory Opus 或者 Total Commander 中。


NuGet 推送命令

NuGet 推送命令可直接在微软官方文档中阅读到:

在你已经设置了 ApiKey 的情况下:

nuget setapikey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -source https://api.nuget.org/v3/index.json

之后你只需要执行一句命令即可:

nuget.exe push Walterlv.Themes.FluentDesign.Source.0.8.0-alpha.nupkg -source https://api.nuget.org/v3/index.json

或者推送此文件夹下 0.8.0-alpha 版本的所有 NuGet 包:

nuget.exe push *.0.8.0-alpha.nupkg -source https://api.nuget.org/v3/index.json

用 PowerShell 包装一下

要执行 NuGet 的推送命令,我们需要一个可以执行命令的终端,比如 PowerShell。命令的执行结果我们也可以直接在终端看到。

不过,如果命令是集成到其他工具里面,那么就不一定能够看得到命令的执行结果了。

这个时候,可以考虑用 PowerShell 间接执行这个命令:

# PowerShell 版本
powershell -NoExit -c "nuget push *.0.8.0-alpha.nupkg -Source https://api.nuget.org/v3/index.json"
# PowerShell Core 版本
pwsh -NoExit -c "nuget push *.0.8.0-alpha.nupkg -Source https://api.nuget.org/v3/index.json"

关于使用 PowerShell 间接执行命令的更多细节,可以参考我的另一篇博客:

集成到 Directory Opus

我将这个命令集成到了 Directory Opus 中,这样,一次点击或者一个快捷键就能发布某个特定版本的所有的 NuGet 包了。

集成到 Directory Opus

关于使用 Directory Opus 继承工具栏按钮的细节,可以阅读我的另一篇博客:

具体来说,就是安装上文中所述的方法添加一个按钮,在按钮当中需要执行的脚本如下:

cd "{sourcepath} "
pwsh -NoExit -c "$file=[Regex]::Match('{file}', '\.\d+\.\d+\.\d+.+.nupkg').Value; nuget push *$file -Source https://api.nuget.org/v3/index.json"

含义为:

  1. 转到 Directory Opus 当前目录
  2. 执行一段 PowerShell 脚本,但执行完之后不退出(这样,我可以观察到我实际上推送的是哪一些包,并且可以知道推送是否出现了错误)
  3. 要执行的命令为 nuget push *.xxx.nupkg -Source https://api.nuget.org/v3/index.json
    • 其中,中间的 xxx 是使用正则表达式匹配的 {file} 文件名
    • {file} 是 Directory Opus 当前选中的文件,我用正则表达式匹配出其版本号和后面的 .nupkg 后缀
    • 将正则表达式匹配出来的文本作为 nuget push 的包,最终生成的命令会非常类似于本文一开始提到的命令 nuget push *.0.8.0-alpha.nupkg -Source https://api.nuget.org/v3/index.json

Directory Opus 工具栏按钮

于是,当我选中了一个包,按下这个工具栏按钮之后,就可以推送与这个包相同版本的所有的 NuGet 包了。

毕竟我一次编译产生的 NuGet 包太多了,还是需要使用这样的方式来提高一点效率。至于为什么不用持续集成,是因为目前 SourceYard 还不支持在 GitHub 上集成。

一键推送 NuGet 包


参考资料

11-20 2019

PowerShell 的命令行启动参数(可用于执行命令、传参或进行环境配置)

有一些程序不支持被直接启动,而要求通过命令行启动。这个时候,你就需要使用 PowerShell 或者 PowerShell Core 来启动这样的程序。我们都知道如何在命令行或各种终端中启动一个程序,但是当你需要自动启动这个程序的时候,你就需要知道如何通过 PowerShell 或其他命令行终端来启动一个程序,而不是手工输入然后回车运行了。

本文就介绍 PowerShell 的命令行启动参数。利用这些参数,你可以自动化地通过 PowerShell 程序来完成一些原本需要通过手工执行的操作或者突破一些限制。


一些必须通过命令行启动的程序

一般来说,编译生成的 exe 程序都可以直接启动,即便是命令行程序也是如此。但是有一些程序就是要做一些限制。比如下面的 FRP 反向代理程序:

FRP 反向代理程序限制必须从命令行启动

借助 cmd.exe 来启动的方法可以参见我的另一篇博客:

那么我们如何能够借助于 PowerShell 或者 PowerShell 来启动它呢?

PowerShell 的帮助文档

先打开一个 PowerShell。

对于 Windows 自带的基于 .NET Framework 的 PowerShell,使用 powershell 命令可以直接启动 PowerShell。对于基于 .NET Core 版本的 PowerShell Core,使用 pwsh 命令可以直接启动。

关于 .NET Core 版本的 PowerShell Core 可以参见我的另一篇博客:

接下来输入下面三个命令中的任何一个:

  • PowerShell -Help
  • PowerShell -?
  • PowerShell /?

或者对于 PowerShell Core 来说,是下面三个命令中的任何一个:

  • pwsh -Help
  • pwsh -?
  • pwsh /?

你就可以看到 PowerShell 的使用说明:

PowerShell 的使用说明

PowerShell 的启动参数示例

使用 PowerShell 间接启动一个程序并传入参数

下面的命令,使用 PowerShell 间接启动 frpc.exe 反向代理程序,并给 frpc.exe 程序传入 -c ./frpc.ini 的启动参数:

> pwsh -Command "D:\walterlv\frpc.exe -c ./frpc.ini"

或者简写为:

> pwsh -c "D:\walterlv\frpc.exe -c ./frpc.ini"

实际上使用 PowerShell 来做这些事情简直是用牛刀杀鸡,因为本身 PowerShell 非常强大。我们只是因为一些程序的限制不得不使用这样的方案来启动程序而已。

比如其中之一,执行脚本。

使用 PowerShell 执行命令/脚本后保留窗口不退出

需要加上 -NoExit 参数。

> pwsh -NoExit -c "D:\walterlv\frpc.exe -c ./frpc.ini"

一定要注意,-c 和后面的命令必须放到最末尾,因为 -c 后面的所有字符串都会被解析为需要执行的命令。

使用 PowerShell 执行多条命令/脚本

多条脚本之间使用 ; 作为分隔:

> pwsh -c "D:\walterlv\frpc.exe -c ./frpc.ini"; "D:\walterlv\frps.exe -c ./frps.ini"

如果引号里面还需要写引号,则可以把里面的引号改成单引号 ' 或者把外面的引号改为单引号 '

使用 PowerShell 间接执行一个脚本

# Execute a PowerShell Command in a session
PowerShell -Command "Get-EventLog -LogName security"

# Run a script block in a session
PowerShell -Command {Get-EventLog -LogName security}

# An alternate way to run a command in a new session
PowerShell -Command "& {Get-EventLog -LogName security}"

附 PowerShell 的全部启动参数说明

PowerShell[.exe] [-PSConsoleFile <文件> | -Version <版本>]
    [-NoLogo] [-NoExit] [-Sta] [-Mta] [-NoProfile] [-NonInteractive]
    [-InputFormat {Text | XML}] [-OutputFormat {Text | XML}]
    [-WindowStyle <样式>] [-EncodedCommand <Base64 编码命令>]
    [-ConfigurationName <字符串>]
    [-File <文件路径> <参数>] [-ExecutionPolicy <执行策略>]
    [-Command { - | <脚本块> [-args <参数数组>]
                  | <字符串> [<命令参数>] } ]

PowerShell[.exe] -Help | -? | /?

-PSConsoleFile
    加载指定的 Windows PowerShell 控制台文件。若要创建控制台
    文件,请在 Windows PowerShell 中使用 Export-Console。

-Version
    启动指定版本的 Windows PowerShell。
    使用参数输入版本号,如 "-version 2.0"。

-NoLogo
    启动时隐藏版权标志。

-NoExit
    运行启动命令后不退出。

-Sta
    使用单线程单元启动 shell。
    单线程单元(STA)是默认值。

-Mta
    使用多线程单元启动 shell。

-NoProfile
    不加载 Windows PowerShell 配置文件。

-NonInteractive
    不向用户显示交互式提示。

-InputFormat
    描述发送到 Windows PowerShell 的数据的格式。有效值为
    "Text" (文本字符串)或 "XML" (序列化的 CLIXML 格式)。

-OutputFormat
    确定如何设置 Windows PowerShell 输出内容的格式。有效值
    为 "Text" (文本字符串)或 "XML" (序列化的 CLIXML 格式)。

-WindowStyle
    将窗口样式设置为 Normal、Minimized、Maximized 或 Hidden。

-EncodedCommand
    接受 base-64 编码字符串版本的命令。使用此参数
    向 Windows PowerShell 提交需要复杂引号
    或大括号的命令。

-ConfigurationName
    指定运行 Windows PowerShell 的配置终结点。
    该终结点可以是在本地计算机上注册的任何终结点,包括
    默认的 Windows PowerShell 远程处理终结点或具有特定用户角色功能
    的自定义终结点。

-File
    在本地作用域("dot-sourced")中运行指定的脚本,以便
    脚本创建的函数和变量可以在当前
    会话中使用。输入脚本文件路径和任何参数。
    File 必须是命令中的最后一个参数,因为在 File 参数
    名称后面键入的所有字符都将解释
    为后跟脚本参数的脚本文件路径。

-ExecutionPolicy
    设置当前会话的默认执行策略,并将其保存
    在 $env:PSExecutionPolicyPreference 环境变量中。
    该参数不会更改在注册表中
    设置的 Windows PowerShell 执行策略。

-Command
    执行指定的命令(和任何参数),就好像它们是
    在 Windows PowerShell 命令提示符下键入的一样,然后退出,除非
    指定了 NoExit。Command 的值可以为 "-"、字符串或
    脚本块。

    如果 Command 的值为 "-",则从标准输入中读取
    命令文本。

    如果 Command 的值为脚本块,则脚本块必须
    用大括号({})括起来。只有在 Windows PowerShell 中运行 PowerShell.exe 时,
    才能指定脚本块。脚本块的结果将作为反序列化的 XML 对象
    (而非活动对象)返回到父 Shell。

    如果 Command 的值为字符串,则 Command 必须是命令中的
    最后一个参数,因为在命令后面键入的所有字符
    都将解释为命令参数。

    若要编写运行 Windows PowerShell 命令的字符串,请使用以下格式:
        "& {<命令>}"
    其中,引号表示一个字符串,调用运算符(&)
    导致执行命令。

-Help, -?, /?
    显示此消息。如果在 Windows PowerShell 中键入 PowerShell.exe
    命令,请在命令参数前面添加连字符(-),而不是添加正
    斜杠(/)。你可以在 Cmd.exe 中使用连字符或正斜杠。

示例
    PowerShell -PSConsoleFile SqlSnapIn.Psc1
    PowerShell -version 2.0 -NoLogo -InputFormat text -OutputFormat XML
    PowerShell -ConfigurationName AdminRoles
    PowerShell -Command {Get-EventLog -LogName security}
    PowerShell -Command "& {Get-EventLog -LogName security}"

    # To use the -EncodedCommand parameter:
    $command = 'dir "c:\program files" '
    $bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
    $encodedCommand = [Convert]::ToBase64String($bytes)
    powershell.exe -encodedCommand $encodedCommand

参考资料

05-25 2019

cmd.exe 的命令行启动参数(可用于执行命令、传参或进行环境配置)

有一些程序不支持被直接启动,而要求通过命令行启动。这个时候,你就需要使用 cmd.exe 来启动这样的程序。我们都知道如何在 cmd.exe 中启动一个程序,但是当你需要自动启动这个程序的时候,你就需要知道如何通过 cmd.exe 来启动一个程序,而不是手工输入然后回车运行了。

本文就介绍 cmd.exe 的命令行启动参数。利用这些参数,你可以自动化地通过 cmd.exe 程序来完成一些原本需要通过手工执行的操作或者突破一些限制。


一些必须通过命令行启动的程序

一般来说,编译生成的 exe 程序都可以直接启动,即便是命令行程序也是如此。但是有一些程序就是要做一些限制。比如下面的 FRP 反向代理程序:

FRP 反向代理程序限制必须从命令行启动

那么我们如何能够借助于 cmd.exe 来启动它呢?接下来说明。

顺便,使用 PowerShell 来启动的方法可以参见我的另一篇博客:

cmd.exe 的帮助文档

先打开一个 cmd,然后输入:

> cmd /?

你就可以看到 cmd.exe 的使用说明:

cmd.exe 的使用说明

启动 Windows 命令解释器的一个新实例

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
    [[/S] [/C | /K] string]

你可以随时输入上面的 cmd /? 命令来查看这些参数详细说明,所以本文不会非常详细地列举各个参数的含义,只会列出一些常见的使用示例。

cmd.exe 的启动参数示例

使用 cmd.exe 间接启动一个程序并传入参数

下面的命令,使用 cmd 间接启动 frpc.exe 反向代理程序,并给 frpc.exe 程序传入 -c ./frpc.ini 的启动参数:

> cmd /c D:\walterlv\frp\frpc.exe -c ./frpc.ini

关于为什么会用这种方式启动 frpc.exe,则是为了设置 frpc.exe 为开机自动启动。

因为我写了一些 Asp.NET Core 的服务,详见:

另外,间接启动一个程序的时候也可以传入 /k 参数。与 /c 参数不同的是:

  • /c 在执行完程序之后,cmd.exe 也会终止
  • /k 在执行完程序之后,cmd.exe 依然会继续运行

所以 /c 命令会更适用于自动化的脚本,而 /k 命令则更适用于半自动化的脚本。

cmd.exe 启动参数使用中的坑

在上面的例子中,我们的路径中不涉及到空格。我们知道,路径中有空格的话,在命令行中使用需要加上引号。但实际上如果你真的给路径加上了引号,会发现 cmd.exe 就开始不识别你的命令路径了。

这个时候,你需要在整个传给 cmd.exe 的命令外层再加一层引号:

> cmd /c " "D:\walterlv folders\frp\frpc.exe" -c ./frpc.ini "

以上,感谢 林德熙 挥泪踩出来的坑,详见:

附 cmd.exe 的全部启动参数说明

启动 Windows 命令解释器的一个新实例

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
    [[/S] [/C | /K] string]

/C 执行字符串指定的命令然后终止 /K 执行字符串指定的命令但保留 /S 修改 /C 或 /K 之后的字符串处理(见下) /Q 关闭回显 /D 禁止从注册表执行 AutoRun 命令(见下) /A 使向管道或文件的内部命令输出成为 ANSI /U 使向管道或文件的内部命令输出成为 Unicode /T:fg 设置前台/背景颜色(详细信息见 COLOR /?) /E:ON 启用命令扩展(见下) /E:OFF 禁用命令扩展(见下) /F:ON 启用文件和目录名完成字符(见下) /F:OFF 禁用文件和目录名完成字符(见下) /V:ON 使用 ! 作为分隔符启用延迟的环境变量 扩展。例如,/V:ON 会允许 !var! 在执行时 扩展变量 var。var 语法会在输入时 扩展变量,这与在一个 FOR 循环内不同。 /V:OFF 禁用延迟的环境扩展。

注意,如果字符串加有引号,可以接受用命令分隔符 “&&” 分隔多个命令。另外,由于兼容性 原因,/X 与 /E:ON 相同,/Y 与 /E:OFF 相同,且 /R 与 /C 相同。任何其他开关都将被忽略。

如果指定了 /C 或 /K,则会将该开关之后的 命令行的剩余部分作为一个命令行处理,其中,会使用下列逻辑 处理引号(“)字符:

1.  如果符合下列所有条件,则会保留
    命令行上的引号字符:

    - 不带 /S 开关
    - 正好两个引号字符
    - 在两个引号字符之间无任何特殊字符,
      特殊字符指下列字符: &<>()@^|
    - 在两个引号字符之间至少有
      一个空格字符
    - 在两个引号字符之间的字符串是某个
      可执行文件的名称。

2.  否则,老办法是看第一个字符
    是否是引号字符,如果是,则去掉首字符并
    删除命令行上最后一个引号,保留
    最后一个引号之后的所有文本。

如果 /D 未在命令行上被指定,当 CMD.EXE 开始时,它会寻找 以下 REG_SZ/REG_EXPAND_SZ 注册表变量。如果其中一个或 两个都存在,这两个变量会先被执行。

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun

    和/或

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun

命令扩展是按默认值启用的。你也可以使用 /E:OFF ,为某一 特定调用而停用扩展。你 可以在机器上和/或用户登录会话上 启用或停用 CMD.EXE 所有调用的扩展,这要通过设置使用 REGEDIT.EXE 的注册表中的一个或两个 REG_DWORD 值:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\EnableExtensions

    和/或

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\EnableExtensions

到 0x1 或 0x0。用户特定设置 比机器设置有优先权。命令行 开关比注册表设置有优先权。

在批处理文件中,SETLOCAL ENABLEEXTENSIONS 或 DISABLEEXTENSIONS 参数 比 /E:ON 或 /E:OFF 开关有优先权。请参阅 SETLOCAL /? 获取详细信息。

命令扩展包括对下列命令所做的 更改和/或添加:

DEL or ERASE
COLOR
CD or CHDIR
MD or MKDIR
PROMPT
PUSHD
POPD
SET
SETLOCAL
ENDLOCAL
IF
FOR
CALL
SHIFT
GOTO
START (同时包括对外部命令调用所做的更改)
ASSOC
FTYPE

有关特定详细信息,请键入 commandname /? 查看。

延迟环境变量扩展不按默认值启用。你 可以用/V:ON 或 /V:OFF 开关,为 CMD.EXE 的某个调用而 启用或停用延迟环境变量扩展。你 可以在机器上和/或用户登录会话上启用或停用 CMD.EXE 所有 调用的延迟扩展,这要通过设置使用 REGEDIT.EXE 的注册表中的 一个或两个 REG_DWORD 值:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion

    和/或

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\DelayedExpansion

到 0x1 或 0x0。用户特定设置 比机器设置有优先权。命令行开关 比注册表设置有优先权。

在批处理文件中,SETLOCAL ENABLEDELAYEDEXPANSION 或 DISABLEDELAYEDEXPANSION 参数比 /V:ON 或 /V:OFF 开关有优先权。请参阅 SETLOCAL /? 获取详细信息。

如果延迟环境变量扩展被启用, 惊叹号字符可在执行时间被用来 代替一个环境变量的数值。

你可以用 /F:ON 或 /F:OFF 开关为 CMD.EXE 的某个 调用而启用或禁用文件名完成。你可以在计算上和/或 用户登录会话上启用或禁用 CMD.EXE 所有调用的完成, 这可以通过使用 REGEDIT.EXE 设置注册表中的下列 REG_DWORD 的全部或其中之一:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\CompletionChar
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\PathCompletionChar

    和/或

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\CompletionChar
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\PathCompletionChar

由一个控制字符的十六进制值作为一个特定参数(例如,0x4 是Ctrl-D,0x6 是 Ctrl-F)。用户特定设置优先于机器设置。 命令行开关优先于注册表设置。

如果完成是用 /F:ON 开关启用的,两个要使用的控制符是: 目录名完成用 Ctrl-D,文件名完成用 Ctrl-F。要停用 注册表中的某个字符,请用空格(0x20)的数值,因为此字符 不是控制字符。

如果键入两个控制字符中的一个,完成会被调用。完成功能将 路径字符串带到光标的左边,如果没有通配符,将通配符附加 到左边,并建立相符的路径列表。然后,显示第一个相符的路 径。如果没有相符的路径,则发出嘟嘟声,不影响显示。之后, 重复按同一个控制字符会循环显示相符路径的列表。将 Shift 键跟控制字符同时按下,会倒着显示列表。如果对该行进行了 任何编辑,并再次按下控制字符,保存的相符路径的列表会被 丢弃,新的会被生成。如果在文件和目录名完成之间切换,会 发生同样现象。两个控制字符之间的唯一区别是文件完成字符 符合文件和目录名,而目录完成字符只符合目录名。如果文件 完成被用于内置式目录命令(CD、MD 或 RD),就会使用目录 完成。 用引号将相符路径括起来,完成代码可以正确处理含有空格 或其他特殊字符的文件名。同时,如果备份,然后从行内调用 文件完成,完成被调用时位于光标右方的文字会被调用。

需要引号的特殊字符是: <space> ()[]{}^=;!'+,~(&()`

04-30 2019

安装和运行 .NET Core 版本的 PowerShell

Windows 自带一个强大的 PowerShell,不过自带的 PowerShell 一直是基于 .NET Framework 的版本。你可以下载安装一个 .NET Core 版本的 PowerShell,以便获得 .NET Core 的各种好处。包括跨平台,以及更好的性能。

本文将介绍在你的 Windows 系统上安装一个 .NET Core 版本的 PowerShell。


PowerShell Core 的图标

下载和安装

前往 .NET Core 版本 PowerShell 的发布页面来下载 PowerShell 全平台的安装包:

Windows 平台上建议下载 msi 格式的安装包,这样它可以帮助你完成大多数的安装任务。

PowerShell 安装界面

PowerShell 安装配置

运行

在安装完成之后启动新的 .NET Core 版本的 PowerShell 可以看见新的 PowerShell。

.NET Core 版本的 PowerShell

在任何一个文件夹中右键可打开 PowerShell 或者以管理员权限打开 PowerShell。这与自带的 PowerShell 的玩法是类似的。

使用右键菜单打开 PowerShell

在其他终端使用 PowerShell Core

如果你要在其他的终端使用 PowerShell Core,直接输入 pwsh 即可。其原理可以参考我的另一篇博客:

在 cmd 中启动 PowerShell Core

03-09 2019

在 Snoop 中使用 PowerShell 脚本进行更高级的 UI 调试

在 WPF 开发时,有 Snoop 的帮助,UI 的调试将变得非常轻松。使用 Snoop,能轻松地查看 WPF 中控件的可视化树以及每一个 Visual 节点的各种属性,或者查看数据上下文,或者监听查看事件的引发。

不过,更强大的是支持使用 PowerShell 脚本。这使得它即便 UI 没有给你提供一些入口,你也能通过各种方式查看或者修改 UI。


Snoop PowerShell 入口

常规 Snoop 的使用方法,将狮子瞄准镜拖出来对准要调试 UI 的 WPF 窗口松开。这里我拿 Visual Studio 2019 的窗口做试验。

调试 Visual Studio 2019 的 UI

在打开的新的 Snoop 窗口中我们打开 PowerShell 标签。

打开 PowerShell 标签

本文的内容将从这里开始。

自带的 PowerShell 变量

在 Snoop 的 PowerShell 提示窗口中,我们可以得知有两个变量可以使用:$root$selected。包含这两个,还有其他的可以使用:

  • $root 拿到当前 Snoop 窗口顶层元素类型的实例
  • $selected 拿到当前 Snoop 用鼠标或键盘选中的元素的实例
  • $parent 拿到当前 Snoop 选中元素的可视化树父级
  • $null 就是 .NET 中的 null

当然,你也可以定义和使用其他的变量,后面会说。

`$root`

`$selected`

基本的 PowerShell 命令

属性

# 获取属性
$selected.Visual.Content
# 将属性设置为 null
$selected.Visual.Content = $null

直接像 C# 语法那样一直在后面使用 . 可以访问实例中的属性。不需要关心实例是什么类型的,只要拥有那个属性,就可以访问到。

比如下面,上面的例子我们选中的是 MainWindow,于是我们使用 $selected.Visual.Content 访问到 MainWindowContent 属性,而后面 $selected.Visual.Content = $null 则是将 Window 的内容清空了。

获取 Content 属性

设置 Content 属性

创建对象

# 创建对象
$button = New-Object System.Windows.Controls.Button -property @{ Content = "欢迎访问 blog.walterlv.com" }

创建一个 Button

调用方法

$selected.Visual.Children.Add($button)

顶部的那个按钮就是通过上面的命令添加上去的。

调用实例方法

调用静态方法用的是 [类名]::方法名(参数)

$button.Content = [System.Environment]::Version.ToString() + " running for blog.walterlv.com"

调用静态方法


参考资料