首页 > 系统相关 >如何编写一个 PowerShell 脚本

如何编写一个 PowerShell 脚本

时间:2024-01-16 18:47:59浏览次数:35  
标签:脚本 project Path 编写 line foundLines eq PowerShell vcxprojContent

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 的函数一一讲解,有兴趣的可以查阅文档来了解其作用

标签:脚本,project,Path,编写,line,foundLines,eq,PowerShell,vcxprojContent
From: https://www.cnblogs.com/strive-sun/p/17968286

相关文章

  • 在CMD和PowerShell下如何制作图片马
    目录在CMD中使用copy命令:在PowerShell中使用gc命令:总结:图片马通常是在图片文件中嵌入其他信息,以隐藏额外的数据。当使用命令行工具(如CMD或PowerShell)制作图片马时,copy命令和Get-Content(简写为gc)命令的目标是将一段数据(可能是一段脚本或其他二进制数据)嵌入到图片文......
  • 使用shell脚本将doDBA采集到的日志会话信息导入到MySQL数据库
    【背景说明】使用doDBA工具监控的会话信息导入到MySQL数据库的表中【环境说明】doDBA工具采集会话信息(之前有脚本说明)【脚本说明】处理dodba日志信息将日志的innodb日志信息去除审计日志的名称要改为原来的dodba.log名称cd/data/backup/doDBA/log/cpdodba_20231226_09......
  • shell脚本使用 $? 记录返回值
    在shell脚本中,使用$?来获取上一次命令执行时的返回状态。实际使用中需要注意$?可能会被清零或覆盖,最好先使用中间变量存起来,以后使用该中间变量;请看如下几种案例的$?值的变化:1)shellA文件调用 shellB文件  shellB文件:①若有$?=2......
  • 使用shell脚本xtrabackup自动恢复MySQL数据库
    【背景说明】按照安全的一些要求,需要定期对数据库进行恢复演练操作【环境说明】MySQL5.7的xtrabackup全库xbstream的加密备份(如果不是流备份跟加密,去掉相关参数)【脚本说明】v_backupdir="/mysqlbackup/recovery/yiyuan"备份文件的目录路径v_dir="/mysqlbackup/recovery/......
  • jenkins中配置linux/windows脚本: python文件传dict参数
    1)前提:jenkinjob中选择linux脚本:如果是传dict参数,那么需要在py文件后跟单引号(跟双引号会报错):正确得案例: 2)前提:jenkinjob中选择windos脚本:如果是传dict参数,那么需要在py文件后跟双引号(跟单引号会报错),dict中得双引号也需要\''转义:正确得案例: ......
  • shell脚本检测mysql服务状态
    shell脚本检测mysql状态:通过多种方案实现方法一:netstat命令 方法二:ss命令 方法三:使用lsof监控端口 执行结果: ......
  • linux or macos 将当前脚本文件以某个方式执行:#! /usr/bin/env
    #!/usr/bin/env 在linux的一些bash的脚本,需在开头一行指定脚本的解释程序,如: #!/usr/bin/envpython但是也有直接写绝对路径的#!/usr/bin/python这个的虽然可以,但是如果我们将脚本换了一台设备,可能它的python并非安装在此处,则需要更换相反:#!/usr/bin/envpython,它是从环境......
  • dolphinscheduler 3.2.0版本执行install.sh脚本报错 command not found
    环境:linuxcentos7dolphinscheduler集群安装,正确配置完/env/install_env.sh、/env/dolphinscheduler_env.sh脚本后,执行安装脚本报错。排错期间排查了sudo、mkdir、bash命令是否已安装等问题。怀疑是环境问题,尝试将整个解压包拷贝至其他相同版本系统的机器上,发现可正常安装启动。后......
  • (2)Powershell开发工具
    (2)Powershell开发工具在上一节对Powershell进行了简单介绍,详细内容参考Powershell简介,这一节介绍Powershell的开发工具及其设置注意事项。本文包含以下知识点如何启动WindowsPowershell命令行开发工具WindowsPowershell命令行的简单设置如何启动WindowsPowershel......
  • 41. 干货系列从零用Rust编写负载均衡及代理,websocket与tcp的映射,WS与TCP互转
    wmproxywmproxy已用Rust实现http/https代理,socks5代理,反向代理,静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子项目地址国内:https://gitee.com/tickbh/wmproxygithub:https://github.com/......