PowerShell Snippets: Prompt for Multiple Inputs

PowerShellThis post is part of the series on PowerShell Snippets.

Over the last two posts of this series, I’ve shown PowerShell cmdlets which prompt for user input and prompt for secure entry of passwords. A PowerShell script can prompt for multiple inputs as well as output text to screen.

When I originally posted about the Write-Output cmdlet, I only showed how it could be used to output text; you can also use a couple of parameters with this command to change the foreground or background colour.

The below script example, shows two outputs to screen using these parameters as well as prompting the user to input two pieces of data:

Write-Host "Please enter details of the plugin release" -ForegroundColor Green

$ghRepository = Read-Host "Please enter the repository name"

$ghTag = Read-Host "Please enter the tag"

Write-Host "$ghRepository $ghTag will be released." -ForegroundColor Yellow -BackgroundColor Black

PowerShell Snippets: Prompt User for Password

PowerShellThis post is part of the series on PowerShell Snippets.

In this last post, in this series, I showed a PowerShell snippet which would prompt a user for input. This is fine if you are prompting for a username, filename, version tag or similar, but if you are prompting for a password, you would not want to expose to people watching over the users shoulder.

The Read-Host cmdlet has a parameter which will allow for secure prompting of passwords:

$Password = Read-Host "Enter your password" -AsSecureString

Adding the AsSecureString parameter will prompt for the password with a popup input box which obscures the password during entry.

PowerShell Script to Change Language of SSRS Reports

Microsoft SQL ServerMicrosoft Dynamics GP ships with a set of standard SSRS reports which includes many useful reports which clients want to use. However, these reports ship with the language set to en-US which means all the numbers could out as US dollars. For a UK based client this isn’t very useful. There are also lots of reports which would need to be updated.

I looked into this years ago with a colleague and the PowerShell script below is our solution. The script does three things:

  1. Download the reports from SSRS to a folder.
  2. Changes the language code.
  3. Uploads the reports from the folder back into SSRS.

The script will download every rdl from SSRS maintaining the folder structure so that it is able to upload the files back into their original place.

There may be a better way of doing this, but we’re not PowerShell experts and this approach does work and has been used quite a few times now.

The script is hardcoded to convert from en-US to en-GB; I have highlighted the destination language to make finding it easy should you want to change it to another language.

There are two settings which will be prompted for when the script runs:

  • ServerName which is the name of the SSRS server.
  • fullFolderPath which is a folder on the local PC to which the reports will be downloaded.
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
$ServerName = Read-Host -Prompt 'Please input a server name' $fullFolderPath = Read-Host -Prompt 'Please input the folder path e.g. H:\SSRS Update\' #note this is tested on PowerShell v2 and SSRS 2008 R2 [void][System.Reflection.Assembly]::LoadWithPartialName("System.Xml.XmlDocument"); [void][System.Reflection.Assembly]::LoadWithPartialName("System.IO"); $ReportServerUri = "http://$($ServerName)/ReportServer/ReportService2005.asmx"; $Proxy = New-WebServiceProxy -Uri $ReportServerUri -Namespace SSRS.ReportingService2005 -UseDefaultCredential ; #check out all members of $Proxy #$Proxy | Get-Member #http://msdn.microsoft.com/en-us/library/aa225878(v=SQL.80).aspx #second parameter means recursive $items = $Proxy.ListChildren("/", $true) | ` select Type, Path, ID, Name | ` Where-Object {$_.type -eq "Report"}; #create a new folder where we will save the files #PowerShell datetime format codes http://technet.microsoft.com/en-us/library/ee692801.aspx #create a timestamped folder, format similar to 2011-Mar-28-0850PM $folderName = Get-Date -format "yyyy-MMM-dd-hhmmtt"; $fullFolderName = $fullFolderPath + $folderName; [System.IO.Directory]::CreateDirectory($fullFolderName) | out-null foreach($item in $items) { #need to figure out if it has a folder name $subfolderName = split-path $item.Path; $reportName = split-path $item.Path -Leaf; $fullSubfolderName = $fullFolderName + $subfolderName; if(-not(Test-Path $fullSubfolderName)) { #note this will create the full folder hierarchy [System.IO.Directory]::CreateDirectory($fullSubfolderName) | out-null } $rdlFile = New-Object System.Xml.XmlDocument; [byte[]] $reportDefinition = $null; $reportDefinition = $Proxy.GetReportDefinition($item.Path); #note here we're forcing the actual definition to be #stored as a byte array #if you take out the @() from the MemoryStream constructor, you'll #get an error [System.IO.MemoryStream] $memStream = New-Object System.IO.MemoryStream(@(,$reportDefinition)); $rdlFile.Load($memStream); $fullReportFileName = $fullSubfolderName + "\" + $item.Name + ".rdl"; #Write-Host $fullReportFileName; $rdlFile.Save( $fullReportFileName); } function ReplaceText($fileInfo) { if( $_.GetType().Name -ne 'FileInfo') { # i.e. reject DirectoryInfo and other types return } $old = 'en-US' $new = 'en-GB' (Get-Content $fileInfo.FullName) | % {$_ -replace $old, $new} | Set-Content -path $fileInfo.FullName "Processed: " + $fileInfo.FullName } function UploadReports ($reportServerName = $(throw "reportServerName is required."), $fromDirectory = $(throw "fromDirectory is required."), $serverPath = $(throw "serverPath is required.")) { Write-Output "Connecting to $reportServerName" $reportServerUri = "http://{0}/ReportServer/ReportService2005.asmx" -f $reportServerName $proxy = New-WebServiceProxy -Uri $reportServerUri -Namespace SSRS.ReportingService2005 -UseDefaultCredential Write-Output "Inspecting $fromDirectory" # coerce the return to be an array with the @ operator in case only one file $files = @(get-childitem $fromDirectory *.rdl |where-object {!($_.psiscontainer)}) $uploadedCount = 0 foreach ($fileInfo in $files) { $file = [System.IO.Path]::GetFileNameWithoutExtension($fileInfo.FullName) $percentDone = (($uploadedCount/$files.Count) * 100) Write-Progress -activity "Uploading to $reportServerName$serverPath" -status $file -percentComplete $percentDone Write-Output "%$percentDone : Uploading $file to $reportServerName$serverPath" $bytes = [System.IO.File]::ReadAllBytes($fileInfo.FullName) $warnings = $proxy.CreateReport($file, $serverPath, $true, $bytes, $null) if ($warnings) { foreach ($warn in $warnings) { Write-Warning $warn.Message } } $uploadedCount += 1 } }` cd $fullFolderName $files = Get-ChildItem . -recurse $files | % { ReplaceText( $_ ) } $UploadFiles = Get-ChildItem . -Recurse -Directory foreach($uploadFolder in $uploadFiles){ $uploadFolderPath = $uploadFolder.FullName.Replace($fullFolderName, "") UploadReports $ServerName "$($fullFolderName)$($uploadFolderPath)" "$($uploadFolderPath.Replace("\","/"))" }

PowerShell Snippets: Prompt for User Input

PowerShellThis post is part of the series on PowerShell Snippets.

The following PowerShell command will prompt the user to input some text which is then stored in the $ghTag parameter for later use:

$ghTag = Read-Host "Please enter the tag"

PowerShell Snippets: Get Numeric Value from String

PowerShellThis post is part of the series on PowerShell Snippets.

In the previous post, I showed how a single element could be retrieved from a GitHub release by executing curl and selecting the required element.

I quickly discovered that the element retrieved in this was contained some additional characters and I needed only the numeric ones. The PowerShell below will extract the numeric elements of the $id variable and return them in the $releaseID variable:

$releaseID = $id -replace "[^0-9]" , ''

PowerShell Snippets: Get One Value from GitHub Json

PowerShellThis post is part of the series on PowerShell Snippets.

While looking into uploading a release asset to a GitHub release, I discovered that to do this I needed the internal numeric id for a release and not just the id I’d given it. The element I needed from the GitHub json was id which can be retrieved using the below PowerShell which executes curl and then selects a single element:


$ghAuthorizationToken = "ghp_authorizationtoken"

$ghUser="username"
$ghRepo="repositoryname"
$ghTag="v1.4.2"

$URL= "https://api.github.com/repos/$ghUser/$ghRepo/releases/tags/$ghTag"

$Json=(curl.exe $URL)|ConvertFrom-json

$id=$Json| Select id

PowerShell Snippets: Use Curl

PowerShellThis post is part of the series on PowerShell Snippets.

The following PowerShell command will execute curl passing in the authorization token and json parameters defined above the curl statement.

The main difference between this and curl on a normal command line is that you need to do curl.exe which is a built in alias for the Invoke-WebRequest cmdlet:

$ghAuthorizationToken = "ghp_authorizationtoken"
$ghUser = "username"
$ghRepo = "repository name"

$json = "
    { \`"tag_name\`": \`"$ghTag\`", \`"target_commitish\`": \`"main\`", \`"name\`": \`"$ghTag\`", \`"body\`": \`"$ghTag release\`", \`"draft\`" :false, \`"prerelease\`": false, \`"generate_release_notes\`": false }
"

curl.exe -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token $ghAuthorizationToken" https://api.github.com/repos/$ghUser/$ghRepo/releases -d "$json"

The variables at the top need to be changed to those for your GitHub account and repository.

PowerShell Snippets: Format Json for Curl

PowerShellThis post is part of the series on PowerShell Snippets.

The following PowerShell shows the format required for use in Curl (which I will cover in the next post of this series). It took me a number of attempts to get the format correct; the backticks (`) are needed to escape the double quotes (") for PowerShell and the backslashes (\) to escape them for the curl command:

$json = "
    { \`"tag_name\`": \`"$ghTag\`", \`"target_commitish\`": \`"main\`", \`"name\`": \`"$ghTag\`", \`"body\`": \`"$ghTag release\`", \`"draft\`" :false, \`"prerelease\`": false, \`"generate_release_notes\`": false }
"

PowerShell Snippets: Run Application (Such as 7-zip)

PowerShellThis post is part of the series on PowerShell Snippets.

The following PowerShell command will execute a Windows application supplying a number of parameters; in this case I am using 7-zip to compress a single one of my ClassicPress plugins to a releases folder (part of this command came from a post I did on compressing all sub folders individually:

$releaseFileName = ".\Releases\$ghRepo.zip"

& "C:\Program Files\7-Zip\7z.exe" a "-xr!.git\" "-xr!*~" $releaseFileName "*"

PowerShell Snippets: Delete File

PowerShellThis post is part of the series on PowerShell Snippets.

The following PowerShell command will check if the named file exists in the current directory and, if so, delete it (replace the highlighted section with the name of the file to be deleted):

$FileName = "azrcrv-smtp.zip"

if (Test-Path $FileName) {
  Remove-Item $FileName
}