Extract values into variables from filename in Powershell - sql

I have a Powershell script to read .sql files from a specific folder and run them against a database depending on the name of the filename.
The filenames are always the same: myDatabase.script.SomeRandomCharacters.csv
There can be many files which is why the script has a foreach loop.
[CmdletBinding()]
param (
[parameter(Mandatory = $true)][ValidateSet('dev')][String]$serverName,
[parameter(Mandatory = $true)][String]$databaseName,
)
$dir = Split-Path $MyInvocation.MyCommand.Path
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name -like "$databaseName*" }
foreach ($s in $scripts) {
$script = $s.FullName
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -InputFile $script
}
The issue here is that if I would have 2 databases "myDatabase" and "myDatabase2", running the script with the former input would run the latter as well since the Where-Object filtering uses an asterisk.
I can't figure out how to modify the script so that I get the absolute value of whatever is before the first fullstop in the filename. What I would also what to do is to validate the value between the first and second fullstops, in the example filename it is script.
Any help is appreciated!

Use the database names to construct a regex pattern that will match either:
param(
[Parameter(Mandatory = $true)][ValidateSet('dev')][String]$ServerName,
[Parameter(Mandatory = $true)][String[]]$DatabaseNames,
)
# Construct alternation pattern like `db1|db2|db3`
$dbNamesEscaped = #($DatabaseNames |ForEach-Object {
[regex]::Escape($_)
}) -join '|'
# Construct pattern with `^` (start-of-string anchor)
$dbNamePattern = '^{0}' -f $dbNamesEscaped
# Fetch scripts associated with either of the database names
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" -and $_.Name -match $dbNamePattern }
# ...

You can use the StartsWith function to fix your filter:
$scripts = Get-ChildItem $dir | Where-Object { $_.Extension -eq ".sql" } | Where-Object { $_.Name.StartsWith("$($databaseName).") }

Related

PowerShell code to script out all SQL Server Agent jobs into a single file

I was trying to script out all the SQL Server Agent jobs for category 'Data Warehouse' into a single file
I was able to do it using PowerShell, where every single job creates a single file.
But I need one file for all the SQL Server Agent jobs under category ID = 100 (or Category : = 'Data Warehouse')
Code I'm currently using:
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
$serverInstance = "APAAUHC7DB01VD"
$server = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $serverInstance
$jobs = $server.JobServer.Jobs
#$jobs = $server.JobServer.Jobs | where-object {$_.category -eq "100"}
if ($jobs -ne $null)
{
$serverInstance = $serverInstance.Replace("\", "-")
ForEach ( $job in $jobs )
{
$FileName = "C:\SQLBackup\SQLJobs\" + $serverInstance + "_" + $job.Name + ".sql"
$job.Script() | Out-File -filepath $FileName
}
}
Give $FileName a single file name for the whole set. Then you can leave out the whole foreach block:
$FileName = "C:\SQLBackup\SQLJobs\whatever.sql"
$jobs | %{ $_.Script() } | Out-File -filepath $FileName

Need script to delete the old backup file from storage blob , the script need to run from managed instance

Can anyone help me to get the script to remove the backup file older than 45 days from storage Blob container.
Actually i want to run the script in Managed instance ( PAAS) through SQL server agent job.
Please help me on this.
According this post.
I think you can modifier the PS script. Change $FromDate = ((Get-Date).AddDays(-6)).Date to $FromDate = ((Get-Date).AddDays(-45)).Date . The script is as follows:
#PowerShell Script to delete System Databases .bak files from Azure Block Blob
#-eq = equals
#-ne = not equals
#-lt = less than
#-gt = greater than
#-le = less than or equals
#-ge = greater than or equals
#Set All Variables
$YesterdayDate = ((Get-Date).AddDays(-1)).Date #Get Yesterday date
$FromDate = ((Get-Date).AddDays(-45)).Date #Get 6 Days back date from Today
$BlobType = "Pageblob"
$bacs = Get-ChildItem $location -Filter *.bak
$container="dwhdatabasesbackup"
$StorageAccountName="analytics"
$StorageAccountKey="xxxxxx"
$context = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
$filelist = Get-AzureStorageBlob -Container $container -Context $context
#Foreach Loop With a Condition $_.LastModified.Date -eq $YesterdayDate to make Sure there was a File Uploaded Yesterday
foreach ($filein$filelist | Where-Object {$_.LastModified.Date -eq $YesterdayDate -and $_.BlobType -eq $BlobType -and ($_.Name -like "*.bak")})
{
$Yesterdayfile = $file.Name
if ($Yesterdayfile -ne $null)
{
$FileFullLength = $Yesterdayfile.Length
$FileNameWithoutDatePart = $Yesterdayfile.SubString(0, $FileFullLength-30)
Write-Output ("File Name Without Date Part: " +$FileNameWithoutDatePart)
#Foreach Loop With a Condition $_.LastModified.Date -lt $FromDate to Remove Files those are 5 Days Old
foreach ($filein$filelist | Where-Object {$_.LastModified.Date -lt $FromDate -and $_.BlobType -eq $BlobType -and ($_.Name -like "$FileNameWithoutDatePart*.bak")})
{
$removefile = $file.Name
$RemoveFileFullLength = $removefile.Length
$ModifiedDate = $file.LastModified.Date
if (($removefile -ne $null) -and ($RemoveFileFullLength -eq $FileFullLength))
{
Write-Output ("Remove File Name: ("+$removefile +") as Modified Date: ("+ $ModifiedDate +") of File is Older Than Date: ("+ $FromDate + ")")
}
}
}
}

How to pass 2 values from pipeline?

I am trying to convert an excel file containing multiple sheets to csv files.
$currentDir = $PSScriptRoot
$csvPATH = Join-Path -Path $currentDir -ChildPath CSV_Files
New-Item -ItemType Directory -Force -Path $csvPATH | out-null
function Convert-ExcelSheetsToCsv {
param(
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[Alias('FullName')]
[string]$Path,
[Parameter(Mandatory = $false, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[bool]$AppendFileName
)
Begin {
$excel = New-Object -ComObject Excel.Application -Property #{
Visible = $false
DisplayAlerts = $false
}
}
Process {
$root = Split-Path -Path $Path
$filename = [System.IO.Path]::GetFileNameWithoutExtension($Path)
$workbook = $excel.Workbooks.Open($Path)
foreach ($worksheet in $workbook.Worksheets) {
if ($AppendFileName) {
$name = Join-Path -Path $csvPATH <# $root #> -ChildPath "${filename}_$($worksheet.Name).csv"
}
else {
$name = Join-Path -Path $csvPATH <# $root #> -ChildPath "$($worksheet.Name).csv"
}
try {
$worksheet.SaveAs($name, 6) #6 to ignore formatting and covert to pure text, otherwise, file could end up containing rubbish
} catch {
Write-Error -Message "Failed to save csv! Path: '$name'. $PSItem"
}
}
}
End {
$excel.Quit()
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel)
}
}
Get-ChildItem -Path $currentDir -Filter *.xlsx 0 | Convert-ExcelSheetsToCsv
This is giving me the following error:
Get-ChildItem : A positional parameter cannot be found that accepts
argument '0'.
or if i put the 0 (for false) after like this: Get-ChildItem -Path $currentDir -Filter *.xlsx | Convert-ExcelSheetsToCsv 0
i get this error:
Convert-ExcelSheetsToCsv : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the
input and its properties do not match any of the parameters that take pipeline input.
basically, i am trying to have an option where if $AppendFileName is false, then the generated csv files will only be named by the sheet name, which is this else statement
$name = Join-Path -Path $csvPATH <# $root #> -ChildPath "$($worksheet.Name).csv"
Position needs to be specified.
[Parameter(Mandatory, ValueFromPipelineByPropertyName,Position=1)] [Parameter(Mandatory=$false,ValueFromPipeline,ValueFromPipelineByPropertyName,Position=0)]
and then:
Get-ChildItem -Path $currentDir -Filter *.xlsx | Convert-ExcelSheetsToCsv 0

Get variable from tenant in Octopus

Is there any way to get a variable from tenant in Octopus server?
I already extracting variable from projects, using code below, but this method is not working for tenants:
Import-Module "C:\Program Files\WindowsPowerShell\Modules\Octopus-Cmdlets\0.4.4\Octopus-Cmdlets.psd1"
connect-octoserver http://octohost.cloudapp.azure.com:8082 API-12345678901234567890
$raw = (Get-OctoVariable someproject somevariable | Where-Object { $_.Environment -eq "DEV" } )
$jsonfile = "c:\dataapi.json"
$raw.Value | ConvertFrom-Json | ConvertTo-Json | Out-File $jsonfile -Encoding UTF8
$data = Get-Content $jsonfile -Encoding UTF8 | ConvertFrom-Json
$data | ConvertTo-Json | Set-Content $jsonfile -Encoding UTF8
There is at least the following way to get a variable from a tenant in Octopus Deploy. I got this working with making OctopusClient.dll calls.
Add-Type -Path $OctopusClientDll #this should point to the dll
$Endpoint = New-Object Octopus.Client.OctopusServerEndpoint $octopusURI, $apiKey
$Repository = New-Object Octopus.Client.OctopusRepository $Endpoint
$TenantEditor = $Repository.Tenants.CreateOrModify($TenantName)
$Vars = $TenantEditor.Variables.Instance.LibraryVariables
$VarSet = $Vars[$COMMON_TENANT_VARSET_ID] # you need to know this
$VarTemplate = $VarSet.Templates | Where-Object -Property Name -eq "Tenant.VariableName"
$VariableValue = $VarSet.Variables[$varTemplate.Id].Value

Powershell script to run list of sql files

I want to read a file that contains a line separated list of *.sql file names (all located at the same directory) to execute the following:
$reader = [System.IO.File]::OpenText("_Scripts.txt")
try {
for(;;) {
$line = $reader.ReadLine()
if ($line -eq $null) { break }
#output
$out = $line.split(".")[0] + ".txt" ;
# -serverinstance u should change the value of it according to use
invoke-sqlcmd -inputfile $line -serverinstance "." | format-table | out-file -filePath $out
$line
}
}
finally {
$reader.Close()
}
I'm trying to execute this script file by using a batch file containing the command:
powershell.exe -ExecutionPolicy Bypass -Command "_scripts.ps1"
but I get the error shown below:
Can anyone help me fix my ps1 script please?
This works for me:
$lines = Get-Content C:\Temp\TEST\_Scripts.txt
ForEach ($line in $lines)
{
$out = $line.split(".")[0] + ".txt" ;
Invoke-Sqlcmd -InputFile $line -ServerInstance "localhost" -Database "master" | Format-Table | Out-File -FilePath $out
}