如何编写一个 PowerShell 脚本
PowerShell 脚本的后缀是 .ps1
前提:
ps1 脚本可以帮忙我们快速修改文件内容,还不需要调用文件的底层 api,方便快捷
在编写 CMakeLists 时发现,项目不能够很好的使用 vcpkg tool chain,哪怕是在命令行中指定 vcpkg.cmake
如果只是简单的项目,vcpkg tool chain 可以正常工作,但是在稍微复杂一些的项目中,比如依赖的 vcpkg 的库过多,就会发现在编译时提示找不到相关的库
不过总的来说,这些都不是本文的重点,重点是如何编写好一个 ps1 脚本
正文:
我们需要读取一个文件的内容,并修改文件中的某个变量名,以及在特定的上下文中插入自定义字符串
# 读取项目文件内容
$scriptDir = $PSScriptRoot
$vcxprojPath = Join-Path $scriptDir "\build\project.vcxproj"
$vcxprojContent = Get-Content $vcxprojPath # 定义常量
$configurationPlatformDebug = '"''$(Configuration)|$(Platform)''==''Debug|Win32''"'
$configurationPlatformRelease = '"''$(Configuration)|$(Platform)''==''Release|Win32''"' # 添加 Vcpkg
$targetLine1 = ' <GenerateManifest Condition=' + $configurationPlatformRelease + '>true</GenerateManifest>'
$targetLine2 = ' </PropertyGroup>' # 修改 Debug 配置
$targetLine3 = ' <OutDir Condition=' + $configurationPlatformDebug + '>' + (Join-Path $scriptDir "build\Debug\") + '</OutDir>'
$targetLine4 = ' <IntDir Condition=' + $configurationPlatformDebug + '>project.dir\Debug\</IntDir>'
$targetLine5 = ' <TargetName Condition=' + $configurationPlatformDebug + '>project</TargetName>' # 修改 Release 配置
$targetLine6 = ' <OutDir Condition=' + $configurationPlatformRelease + '>' + (Join-Path $scriptDir "build\Release\") + '</OutDir>'
$targetLine7 = ' <IntDir Condition=' + $configurationPlatformRelease + '>project.dir\Release\</IntDir>'
$targetLine8 = ' <TargetName Condition=' + $configurationPlatformRelease + '>project</TargetName>' $targetLine9 = ' <PropertyGroup Condition=' + $configurationPlatformRelease + ' Label="Configuration">' $targetLine10 = ' <TargetExt Condition=' + $configurationPlatformRelease + '>.exe</TargetExt>' # 要替换的新文本
$newAttributes = @"
<PropertyGroup Label="Vcpkg" Condition=$configurationPlatformDebug>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Globals">
<VcpkgTriplet Condition="'`$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
</PropertyGroup>
"@ $newTargetLines3 = ' <OutDir Condition=' + $configurationPlatformDebug + '>$(SolutionDir)bin\$(Configuration)\</OutDir>'
$newTargetLines4 = ' <IntDir Condition=' + $configurationPlatformDebug + '>$(SolutionDir)temp\$(Configuration)\$(ProjectName)\</IntDir>'
$newTargetLines5 = ' <TargetName Condition=' + $configurationPlatformDebug + '>$(SolutionName)_d</TargetName>' $newTargetLines6 = ' <OutDir Condition=' + $configurationPlatformRelease + '>$(SolutionDir)bin\Project\$(PJVersion)\</OutDir>'
$newTargetLines7 = ' <IntDir Condition=' + $configurationPlatformRelease + '>$(SolutionDir)temp\$(Configuration)\$(ProjectName)\</IntDir>'
$newTargetLines8 = ' <TargetName Condition=' + $configurationPlatformRelease + '>$(SolutionName)</TargetName>' $newTargetLines9 = ' <ConfigurationType>DynamicLibrary</ConfigurationType>' $newTargetLines10 = ' <TargetExt Condition=' + $configurationPlatformRelease + '>.dll</TargetExt>' $foundLines = @() # 因为只遍历一遍,所以要按先后顺序放置待修改的行
for ($i = 0; $i -lt $vcxprojContent.Length - 1; $i++) {
$line = $vcxprojContent[$i] # 检查是否找到目标行
if ($line -eq $targetLine9) {
$foundLines += $i + 1
} if ($line -eq $targetLine3) {
$foundLines += $i
} if ($line -eq $targetLine4) {
$foundLines += $i
} if ($line -eq $targetLine5) {
$foundLines += $i
} if ($line -eq $targetLine6) {
$foundLines += $i
} if ($line -eq $targetLine7) {
$foundLines += $i
} if ($line -eq $targetLine8) {
$foundLines += $i
} if ($line -eq $targetLine10) {
$foundLines += $i
} if ($line -eq $targetLine1 -and $vcxprojContent[$i + 1] -eq $targetLine2) {
$foundLines += $i + 2
} } # 判断是否找到所有待替换的行
if ($foundLines.Count -eq 9) {
# 替换目标行
$vcxprojContent[$foundLines[0]] = $newTargetLines9
$vcxprojContent[$foundLines[1]] = $newTargetLines3
$vcxprojContent[$foundLines[2]] = $newTargetLines4
$vcxprojContent[$foundLines[3]] = $newTargetLines5
$vcxprojContent[$foundLines[4]] = $newTargetLines6
$vcxprojContent[$foundLines[5]] = $newTargetLines7
$vcxprojContent[$foundLines[6]] = $newTargetLines8
$vcxprojContent[$foundLines[7]] = $newTargetLines10
# 在目标行后面插入新文本
$vcxprojContent = [System.Collections.ArrayList]($vcxprojContent -split "`r`n")
$vcxprojContent.Insert($foundLines[8], $newAttributes)
# 将修改后的内容保存回文件
$vcxprojContent | ForEach-Object { $_ } | Set-Content $vcxprojPath Write-Host "Target lines replaced successfully in project."
} else {
Write-Host "Specific lines not found in the file in project."
}
我们还可以通过 ps1 脚本改文件编码格式
比如 visual studio 默认接受 UTF-16 编码的 rc 文件,而我们使用 CMake 中的 configure_file 函数生成的文件默认是 UTF-8 编码
那么我们可以使用 -Encoding 来改变
# project.rc 转为 UTF-16 编码
$rcPath = Join-Path $scriptDir "\build\project.rc"
# 读取 UTF-8 编码的文件内容
$content = Get-Content -Path $rcPath -Encoding UTF8
# 将内容以 UTF-16 编码保存
Set-Content -Path $rcPath -Value $content -Encoding Unicode
补充:
时间匆忙,无法对每个 ps1 的函数一一讲解,有兴趣的可以查阅文档来了解其作用
如何编写一个 PowerShell 脚本的更多相关文章
- 编写一个BAT脚本协助运维人员遇到问题时候调测数据库是否有效连接成功的操作攻略
简单摘要: 1.内网系统出现故障需要排查 2.运维人员不熟悉数据库操作,没法通过连接数据库和执行SQL语句的方式排查数据库及数据是否正常 3.解决方案:编写一个bat脚本,运维人员双击运行即可. ...
- 工程师技术(五):Shell脚本的编写及测试、重定向输出的应用、使用特殊变量、编写一个判断脚本、编写一个批量添加用户脚本
一.Shell脚本的编写及测 目标: 本例要求两个简单的Shell脚本程序,任务目标如下: 1> 编写一个面世问候 /root/helloworld.sh 脚本,执行后显示出一段话“Hello ...
- shell编写一个判断脚本
shell编写一个判断脚本 4.1问题 本例要求在虚拟机server0上创建/roo ...
- 从0开始的Python学习013编写一个Python脚本
通过之前的学习我们已经了解了Python的很多基础运用了,现在我们尝试着做一个有使用价值的小脚本. 问题 需求: 我想要一个可以给我备份重要文件的程序. 需求分析: 首先文件是有存储路径,文件的路径和 ...
- python+pytest接口自动化(12)-自动化用例编写思路 (使用pytest编写一个测试脚本)
经过之前的学习铺垫,我们尝试着利用pytest框架编写一条接口自动化测试用例,来厘清接口自动化用例编写的思路. 我们在百度搜索天气查询,会出现如下图所示结果: 接下来,我们以该天气查询接口为例,编写接 ...
- 分享我编写的powershell脚本:ssh-copy-id.ps1
问:通过[字符串界面].如何从win,通过ssh,连接到sshd?答:在任意版本win中,通过cmd.exe,powershell.exe中调用ssh.exe,连接sshd. 问:通过[pow ...
- 编写一个python脚本功能-备份
版本一 解决方案当我们基本完成程序的设计,我们就可以编写代码了,它是对我们的解决方案的实施.版本一例10.1 备份脚本——版本一 #!/usr/bin/python # Filename: backu ...
- 1.编写一个shell脚本
一.shell和shell脚本 在linux系统下,以 #/bin/bash开头的文本会被shell解释器进行解释. shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操 ...
- sql server编写一个语句脚本自动清空各表数据以初始化数据库
问题:有时已有项目要移植,例如原来在广州地区使用的某系统,突然说惠州那边也要用这套一样的系统.或者,在demo环境下弄了一些测试数据.然后要清空全部表数据.如果表比较多的话,逐个表手工编写脚本就太麻烦 ...
- Python编写一个Python脚本
我想要一个可以为我的所有重要文件创建备份的程序.(下面测试环境为python2.7) 1.backup_ver1.py #!/usr/bin/python import os import time ...
随机推荐
- Raid卡型号的简单辨认与问题发现过程
Raid卡型号的简单辨认与问题发现过程 背景 同事给了一个awr报告. !-_-! 其实我看不懂. 但是他告诉我 有大量的log file sync 的等待事件. 然后又给了一套其他的文件, 发现lo ...
- SkyWalking的学习之三
SkyWalking的学习之三 持续优化 SkyWalking 默认可以使用h2,但是感觉容量和性能都可能不太好 所以我想使用一下elasticSearch进行替换. 自己其实一直想心想去学习, 但是 ...
- megacli_sw服务器Raid卡的设置过程
megacli_sw服务器的设置过程 背景 采购的申威服务器有四块硬盘, 第一台服务器在sdd上面安装了一个银河麒麟v10的系统 sda,sdb,sdc 三块硬盘没有进行raid设置, 直接还是用的J ...
- [转帖]高性能网络实战:借助 eBPF 来优化负载均衡的性能
https://zhuanlan.zhihu.com/p/592981662 网络性能优化,eBPF 是如何发挥作用的呢? 本篇文章,我就以最常用的负载均衡器为例,带你一起来看看如何借助 eBPF 来 ...
- 当你对 redis 说你中意的女孩是 Mia
作者:京东科技 周新智 一.Redis 众所周知,Redis = Remote Dictionary Server,即远程字典服务. 是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久 ...
- React中事件的绑定
事件绑定 语法:on +事件名= { ()=>{ do something }} <!-- 点击事件 --> onClick={ () => { } } 注意的是:React采 ...
- Gorm 入门介绍与基本使用
Gorm 入门介绍与基本使用 目录 Gorm 入门介绍与基本使用 一.ORM简介 1.1 什么是ORM 1.2 使用ORM的好处 1.2.1 避免直接操作SQL语句 1.2.2 提高代码的可维护性 1 ...
- 什么是 Java 字节码?采用字节码的好处是什么?
在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机.Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效 ...
- Milvus 2.3.功能全面升级,核心组件再升级,超低延迟、高准确度、MMap一触开启数据处理量翻倍、支持GPU使用!
Milvus 2.3.功能全面升级,核心组件再升级,超低延迟.高准确度.MMap一触开启数据处理量翻倍.支持GPU使用! 1.Milvus 2.3版本全部升级简介 Milvus 2.3.0 不仅包含大 ...
- C/C++ 获取主机网卡MAC地址
MAC地址(Media Access Control address),又称为物理地址或硬件地址,是网络适配器(网卡)在制造时被分配的全球唯一的48位地址.这个地址是数据链路层(OSI模型的第二层)的 ...