You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本修改:按输入TXT文件名生成带日期的CSV

解决方案:按输入txt文件生成对应命名的CSV输出

以下是修改后的PowerShell脚本,实现每个输入txt文件对应一组带日期戳的CSV输出(用户角色、NSG规则、VM信息),文件名格式为[输入文件名前缀]_[数据类型]_[日期].csv:

$Folder = 'C:\Scrpting\Subscriptions'
$OutputFolder = 'C:\Scrpting\Output'
$dateStamp = (Get-Date).ToString("yyyyMMdd")

# 确保输出文件夹存在,不存在则创建
if (-not (Test-Path -Path $OutputFolder)) {
    New-Item -Path $OutputFolder -ItemType Directory | Out-Null
}

# 逐个处理每个订阅txt文件
Get-ChildItem -Path $Folder -File -Filter "*.txt" | ForEach-Object {
    $currentFile = $_
    $fileBaseName = $currentFile.BaseName # 提取文件名前缀(如ABC.txt -> ABC)
    
    # 读取当前文件中的订阅列表,过滤空行
    $azSubs = Get-Content -Path $currentFile.FullName | Where-Object { $_ -match '\S' }

    # --- 1. 导出用户角色数据 ---
    $userRolesOutput = Join-Path $OutputFolder "$fileBaseName_UserRoles_$dateStamp.csv"
    $userRolesData = @()

    foreach ($azSub in $azSubs) {
        try {
            Set-AzContext -SubscriptionName $azSub -ErrorAction Stop | Out-Null
            
            $userRoles = Get-AzRoleAssignment | Where-Object { $_.ObjectType -eq "User" }
            foreach ($user in $userRoles) {
                $userRolesData += [PSCustomObject]@{
                    DisplayName         = $user.DisplayName
                    SignInName          = $user.SignInName
                    RoleDefinitionName  = $user.RoleDefinitionName
                    SubscriptionName    = $azSub
                }
            }
        }
        catch {
            Write-Warning "处理订阅 $azSub 的用户角色时出错:$_"
        }
    }

    if ($userRolesData.Count -gt 0) {
        $userRolesData | Export-Csv -Path $userRolesOutput -NoTypeInformation -Force
        Write-Host "用户角色已导出:$userRolesOutput"
    }

    # --- 2. 导出NSG防火墙规则数据 ---
    $firewallOutput = Join-Path $OutputFolder "$fileBaseName_FirewallRules_$dateStamp.csv"
    $firewallData = @()

    foreach ($azSub in $azSubs) {
        try {
            Set-AzContext -SubscriptionName $azSub -ErrorAction Stop | Out-Null
            
            $azNsgs = Get-AzNetworkSecurityGroup
            foreach ($azNsg in $azNsgs) {
                $rules = Get-AzNetworkSecurityRuleConfig -NetworkSecurityGroup $azNsg | Select-Object `
                    @{label = 'NSG Name'; expression = { $azNsg.Name } }, `
                    @{label = 'NSG Location'; expression = { $azNsg.Location } }, `
                    @{label = 'Rule Name'; expression = { $_.Name } }, `
                    @{label = 'Source'; expression = { $_.SourceAddressPrefix } }, `
                    @{label = 'Source Application Security Group'; expression = { 
                        if ($_.SourceApplicationSecurityGroups) { $_.SourceApplicationSecurityGroups.id.Split('/')[-1] } 
                        else { $null } 
                    }}, `
                    @{label = 'Source Port Range'; expression = { $_.SourcePortRange } }, `
                    Access, Priority, Direction, `
                    @{label = 'Destination'; expression = { $_.DestinationAddressPrefix } }, `
                    @{label = 'Destination Application Security Group'; expression = { 
                        if ($_.DestinationApplicationSecurityGroups) { $_.DestinationApplicationSecurityGroups.id.Split('/')[-1] } 
                        else { $null } 
                    }}, `
                    @{label = 'Destination Port Range'; expression = { $_.DestinationPortRange } }, `
                    @{label = 'Resource Group Name'; expression = { $azNsg.ResourceGroupName } }, `
                    @{label = 'Subscription Name'; expression = { $azSub } }
                
                $firewallData += $rules
            }
        }
        catch {
            Write-Warning "处理订阅 $azSub 的NSG规则时出错:$_"
        }
    }

    if ($firewallData.Count -gt 0) {
        $firewallData | Export-Csv -Path $firewallOutput -NoTypeInformation -Force
        Write-Host "NSG规则已导出:$firewallOutput"
    }

    # --- 3. 导出VM信息数据 ---
    $vmOutput = Join-Path $OutputFolder "$fileBaseName_VMInfo_$dateStamp.csv"
    $vmData = @()

    foreach ($azSub in $azSubs) {
        try {
            Set-AzContext -SubscriptionName $azSub -ErrorAction Stop | Out-Null
            
            $vms = Get-AzVM
            $nics = Get-AzNetworkInterface | Where-Object { $_.VirtualMachine -ne $null }

            foreach ($nic in $nics) {
                $vm = $vms | Where-Object { $_.Id -eq $nic.VirtualMachine.id }
                if (-not $vm) { continue }

                # 获取公网IP(改用PowerShell cmdlet替代Azure CLI)
                $publicIP = (Get-AzPublicIpAddress | Where-Object { 
                    $_.Id -eq $nic.IpConfigurations.PublicIpAddress.Id 
                }).IpAddress

                $vmData += [PSCustomObject]@{
                    VMName              = $vm.Name
                    ResourceGroupName   = $vm.ResourceGroupName
                    OS                  = $vm.StorageProfile.OsDisk.OsType
                    PrivateIPAddress    = $nic.IpConfigurations.PrivateIpAddress
                    PublicIPAddress     = if ($publicIP) { $publicIP } else { "Not Assigned" }
                    SubscriptionID      = (Get-AzContext).Subscription.Id
                    Status              = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
                    NICName             = $nic.Name
                }
            }
        }
        catch {
            Write-Warning "处理订阅 $azSub 的VM信息时出错:$_"
        }
    }

    if ($vmData.Count -gt 0) {
        $vmData | Export-Csv -Path $vmOutput -NoTypeInformation -Force
        Write-Host "VM信息已导出:$vmOutput"
    }
}

Write-Host "所有文件处理完成"

关键修改说明
  1. 按单个txt文件独立处理

    • 遍历每个输入txt文件,而非一次性读取所有订阅到统一列表
    • 提取文件前缀(如ABC.txt→ABC)作为输出文件名的一部分
  2. 生成对应命名的输出文件
    每个输入文件会生成3个CSV,命名规则:[文件名前缀]_[数据类型]_[日期戳].csv
    例:ABC_UserRoles_20240520.csv、ABC_FirewallRules_20240520.csv

  3. 优化数据导出逻辑

    • 先收集所有数据到数组,再一次性导出,避免多次-Append导致的格式问题
    • 添加-NoTypeInformation移除CSV头部的类型信息,保持文件简洁
    • 添加-Force参数覆盖已存在的同名文件
  4. 修复原脚本的问题

    • 统一使用Set-AzContext -SubscriptionName切换订阅(原脚本VM部分误用-SubscriptionID会报错)
    • 替换Azure CLI命令Az vm list-ip-addresses为PowerShell cmdletGet-AzPublicIpAddress,保持脚本风格统一
    • 修复$subscriptionId未定义的问题,从当前上下文获取订阅ID
    • 添加空行过滤,跳过txt文件中的无效订阅条目
  5. 增强健壮性

    • 自动创建不存在的输出文件夹
    • 加入try/catch错误处理,输出警告信息并继续执行其他订阅
    • 无数据时跳过导出,避免生成空文件

内容的提问来源于stack exchange,提问作者Saurabh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:13:53