Increment package number using powershell - powershell

I have a script to push a package to Octopus which works. I want to push the package a number of times say 10. But to do this I need to increment the package number by 1 each time. I cant upload the same package number twice. The pushing to Octopus works but im not sure where to start with the increment of the package from MyTestPackage.1.1.0.zip to MyTestPackage.1.1.1.zip. The 0 at before the .zip will need to increment by 1 each time.
I was think of a for loop to upload package 10 times?? Any help would be great
function PushPackage {
param(
$OctopusUri,
$ApiKey,
$Package
)
try{
Write-Host "Pushing $Package to Octopus"
Start-Process -NoNewWindow -FilePath $OctopusExePath
& $OctopusExePath push --package $Package --server $OctopusUri --apiKey $ApiKey --logLevel 'verbose'
Write-Host "Pushing $Package to Octopus - Success"
}
catch{
Write-Host "PUSH PACKAGE Exception--------- $_"
}
}
$OctopusUri = "https://MyOctopusTest.local"
$ApiKey = "API-CRW9JBMJGUTEUEYEYUE"
$Package = "C:\temp\OctoTest1\MyTestPackage.1.1.0.zip"
PushPackage $OctopusUri $ApiKey $Package

Related

Powershell: Issue while calling a powershell script from another powershell script

I have a powershell script A.ps1 as below:
param([switch] $p1, [switch] $p2)
if ($p1.IsPresent)
{
$p1 = 2
& $B -onboardingId "" -p1 $p1.IsPresent $message = "Deployment In Progress" -connectionString $connectionString
}
elseif ($p2.IsPresent)
{
$p2 = 3
& $B -onboardingId "" -p2 $p2.IsPresent $message = "Deployment In Progress" -connectionString $connectionString
}
The script A.ps1 is calling B.ps1 from itself. Both the scripts are placed in the same path. But I am getting the error below when I try to call script:
The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object.
I tried -ArgumentList but it did not work out for me.
I tried to resolve the issue by referring online but I was not able to resolve it. Can I please get help on this?
Thank you.

Pushing package to Octopus Deploy using powershell script

I am new to Powershell and I am writing a script to push a package to Octopus Deploy.
#Function to push packages to Octopus Deploy
function Push-Package {
param(
$OctopusUri,
$ApiKey,
$Package
)
try{
Write-Host "Pushing $($Package.Fullname) to Octopus"
.\Octo.exe 'push' --package $Package.Fullname --server $OctopusUri --apiKey $ApiKey --logLevel 'verbose'
Write-Host "Pushing $($Package.Fullname) to Octopus - Success"
}
catch{
Write-Host "PUSH PACKAGE Exception--------- $_"
}
}
$OctopusUri = "https://MyTestOctopus.local"
$ApiKey = "API-3Z3NRPNLUTS6ULA2KDALWG6A3HA"
$PackageFolder = "c:\temp\OctoTest"
Push-Package "https://MyTestOctopus.local" "API-3Z3NRPNLUTS6ULA2KDALWG6A3HA" "C:\temp\OctoTest\MyTestPackage.1.1.0.zip"
I am getting an error:
PUSH PACKAGE Exception--------- The term '.\Octo.exe' is not recognized as the name of a cmdlet, function, script file, or operable program
I am not sure what I am doing wrong above. Any help would be great.

downloading and Installing msi from sharefile

I am trying to put together a powershell script to download firefox msi from sharefile and silently install.
I finally got the download part to work. However, installing does not. When I navigate to the folders where I downloaded firefox msi to (C:\, C:\users\public, and my desktop) I get the following errors:
This app can't run on your PC
This installation package could not be opened. Contact the application vendor to verify this is a valid windows installer package.
I downloaded the exe from mozilla site and msi from front motion.
The share the software is in is open to everyone on network.
I get same errors for both exe and msi.
This is my current script:
#Download and Run MSI package for Automated install
$uri = "https://sharefile.com/app/#/home/shared/foe0295b-0fbf-4ad9-ad73-fc18d26ba705/FirefoxInstaller.msi"
$out = "c:\FireFoxInstaller.msi"
Invoke-WebRequest -uri $uri -OutFile $out
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i $out /quiet /norestart /l c:\installlog.txt"
To grab the latest version of Firefox, try the following (replacing the Outfile to your own valid location);
Invoke-WebRequest -Uri "https://download.mozilla.org/?product=firefox-msi-latest-ssl&os=win64&lang=en-GB" -Outfile c:\temp\firefox.msi
To install, I use;
start /wait msiexec /i C:\temp\Firefox.msi /quiet
Recently I had a similar issue, where I wanted to deploy HipChat to the whole company. The major difference is that I check if the software is already installed before downloading and trying to install it again, it's very simple and compatible with Windows 7 and 10:
$file = 'HipChat-4.29.5.1662-win32.msi'
$link = "https://s3.amazonaws.com/hipchat-ops/hipchat4/windows/$file"
$soft_name = 'Hipchat'
$find = Get-WmiObject -Class Win32_Product -Filter "Name = `'$soft_name`'"
if ($find -eq $null) {
$tmp = "$env:TEMP\$file"
$client = New-Object System.Net.WebClient
$client.DownloadFile($link, $tmp)
msiexec /i $tmp /qn
del $tmp
echo "Tried installing $soft_name"
} else {
echo "ERROR: $soft_name is already installed."
echo $find
exit 1
}
exit 0
As you stated you have an MSI of your choice, but I justed used the MSI from Frontmotion
This worked when I did it, but let me know if it worked for you.
#Download and Run MSI package for Automated install
$uri = "http://hicap.frontmotion.com.s3.amazonaws.com/Firefox/Firefox-53.0.3/Firefox-53.0.3-en-US.msi"
$out = "c:\FireFoxInstaller.msi"
Function Download_MSI_FireFox_Installer{
Invoke-WebRequest -uri $uri -OutFile $out
$msifile = Get-ChildItem -Path $out -File -Filter '*.ms*'
write-host "FireFox MSI $msifile "
}
Function Install_FireFox{
$FileExists = Test-Path $msifile -IsValid
$DataStamp = get-date -Format yyyyMMddTHHmmss
$logFile = '{0}-{1}.log' -f $msifile.fullname,$DataStamp
$MSIArguments = #(
"/i"
('"{0}"' -f $msifile.fullname)
"/qn"
"/norestart"
"/L*v"
$logFile
)
If ($FileExists -eq $True)
{
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -passthru | wait-process
write-host "Finished msi "$msifile
}
Else {Write-Host "File doesn't exists"}
}
Download_MSI_FireFox_Installer
Install_FireFox
I think the $msifile assignment needs to be moved outside the Download_MSI_FireFox_Installer function, otherwise, I get an error that the path is null in the InstallFireFox function.

What's the easiest way to get a package from nuget.org into a private nuget server?

We're looking at running a private NuGet server. I know products like ProGet have functions to get packages from NuGet and put them into a private feed. We're more interested in a bare bones approach if possible. I built and deployed a NuGet server using NuGet.Server and Visual Studio. I can put nupkg files into my packages folder and install from my private server into a Visual Studio project. I've had to manually download the NuGet packages and then copy the nupkg files. Is this the only way? It seems some NuGet packages aren't fully downloadable as stand-alone packages. I was able to get one by creating a dummy app, installing the package from nuget.org and then copying the nupkg file but that seems hokey.
Anyone running a private NuGet server that has a cleaner way to "copy" packages from nuget.org into their private server?
TIA
Running into the same issue in the past, i used this Blog Post by Jon Galloway
It contains a script that works "out of the box" (double checked it now on Win7)
Pay attention to the variables as the default script repository is Microsoft's and limit itself to 500 nuget packages.
Also, when downloading the packages ive noticed they are saved in ".Version.nupkg" and not containing the full package name (Happens in Nuget Offical Repository https://www.nuget.org/api/v2/)
EDIT:
Following your need to choose spesific nuget packages, ive added a few lines for filtering the packages
param(
[parameter(Mandatory=$TRUE,Position=0)]
$PackageFilterBy
)
# --- settings ---
$feedUrlBase = "http://go.microsoft.com/fwlink/?LinkID=206669"
# the rest will be params when converting to funclet
$latest = $true
$overwrite = $false
$top = 500 #use $top = $null to grab all
$destinationDirectory = join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal"
# --- locals ---
$webClient = New-Object System.Net.WebClient
# --- functions ---
# download entries on a page, recursively called for page continuations
function DownloadEntries {
param ([string]$feedUrl)
$feed = [xml]$webClient.DownloadString($feedUrl)
$entries =#()
$filter = $PackageFilterBy.Split(',')
foreach($item in $filter ){
$feed.feed.entry | %{if($_.id -match "$item"){$entries += $_}}
}
$progress = 0
foreach ($entry in $entries) {
$url = $entry.content.src
$fileName = $entry.properties.id + "." + $entry.properties.version + ".nupkg"
$saveFileName = join-path $destinationDirectory $fileName
$pagepercent = ((++$progress)/$entries.Length*100)
if ((-not $overwrite) -and (Test-Path -path $saveFileName))
{
write-progress -activity "$fileName already downloaded" `
-status "$pagepercent% of current page complete" `
-percentcomplete $pagepercent
continue
}
write-progress -activity "Downloading $fileName" `
-status "$pagepercent% of current page complete" `
-percentcomplete $pagepercent
[int]$trials = 0
do {
try {
$trials +=1
$webClient.DownloadFile($url, $saveFileName)
break
} catch [System.Net.WebException] {
write-host "Problem downloading $url `tTrial $trials `
`n`tException: " $_.Exception.Message
}
}
while ($trials -lt 3)
}
$link = $feed.feed.link | where { $_.rel.startsWith("next") } | select href
if ($link -ne $null) {
# if using a paged url with a $skiptoken like
# http:// ... /Packages?$skiptoken='EnyimMemcached-log4net','2.7'
# remember that you need to escape the $ in powershell with `
return $link.href
}
return $null
}
# the NuGet feed uses a fwlink which redirects
# using this to follow the redirect
function GetPackageUrl {
param ([string]$feedUrlBase)
$resp = [xml]$webClient.DownloadString($feedUrlBase)
return $resp.service.GetAttribute("xml:base")
}
# --- do the actual work ---
# if dest dir doesn't exist, create it
if (!(Test-Path -path $destinationDirectory)) {
New-Item $destinationDirectory -type directory
}
# set up feed URL
$serviceBase = GetPackageUrl($feedUrlBase)
$feedUrl = $serviceBase + "Packages"
if($latest) {
$feedUrl = $feedUrl + "?`$filter=IsLatestVersion eq true"
if($top -ne $null) {
$feedUrl = $feedUrl + "&`$orderby=DownloadCount desc&`$top=$top"
}
}
while($feedUrl -ne $null) {
$feedUrl = DownloadEntries $feedUrl
}
Using the script will be something like this: .\Script.ps1 jquery,Microsoft

Powershell: Call functions outside scriptblock

I was reading this post about getting functions passed into a scriptblock for use with jobs:
Powershell start-job -scriptblock cannot recognize the function defined in the same file?
I get how that works by passing the function in as variable and it works for the simple example. What about a real world solution though, is there a more elegant way of handling this?
I have script I'm using to deploy changes to vendor software. It reads an xml that tells it how to navigate the environment and performs the various tasks, ie: map drives, stop services, call a perl installation script. I would like to provide a parameter to the script to allow it to run concurrently, this way if the perl script takes 5 minutes (not uncommon) and you're rolling out to 11 servers you're not waiting for the script to run for an hour.
I'm just going to post some snippets since the full script is a little lengthy. A log function:
function Log
{
Param(
[parameter(ValueFromPipeline=$true)]
$InputObject,
[parameter()]
[alias("v")]
$verbosity = $debug
)
$messageIndex = [array]::IndexOf($verbosityArray, $verbosity)
$verbosityIndex = [array]::IndexOf($verbosityArray, $loggingVerbosity)
if($messageIndex -ge $VerbosityIndex)
{
switch($verbosity)
{
$debug {Write-Host $verbosity ": " $InputObject}
$info {Write-Host $verbosity ": " $InputObject}
$warn {Write-Host $verbosity ": " $InputObject -ForegroundColor yellow}
$error {Write-Host $verbosity ": " $InputObject -ForegroundColor red}
}
}
}
Here's another function that calls the log function:
function ExecuteRollout
{
param(
[parameter(Mandatory=$true)]
[alias("ses")]
$session,
[parameter(Mandatory=$true)]
$command
)
#invoke command
Invoke-Command -session $session -ScriptBlock {$res = cmd /v /k `"$args[0]`"} -args $command
#get the return code from the remote session
$res = Invoke-Command -session $session {$res}
Log ("Command Output: "+$res)
$res = [string] $res
$exitCode = $res.substring($res.IndexOf("ExitCode:"), 10)
$exitCode = $exitCode.substring(9,1)
Log ("Exit code: "+$exitCode)
return $exitCode
}
And lastly a snippet from my main so you can get an idea of what's going on. $target.Destinations.Destination will contain all the servers and relevant information about them that the deployment will go to. I removed some variable setup and logging to make this more compact so yes you'll see variables referenced that are never defined:
#Execute concurrently
$target.Destinations.Destination | %{
$ScriptBlock = {
$destination = $args[0]
Log -v $info ("Starting remote session on: "+$destination.Server)
$session = New-PSSession -computerName $destination.Server
$InitializeRemote -session $session -destination $destination
#Gets a little tricky here, we need to keep the cmd session so it doesn't lose the sys vars set by env.bat
#String everything together with &'s
$cmdString = $destDrive + ": & call "+$lesDestDir+"data\env.bat & cd "+$rolloutDir+" & perl ..\JDH-rollout-2010.pl "+$rollout+" NC,r:\les & echo ExitCode:!errorlevel!"
Log ("cmdString: "+$cmdString)
Log -v $info ("Please wait, executing the rollout now...")
$exitCode = $ExecuteRollout -session $session -command $cmdString
Log ("ExitCode: "+$exitCode)
#respond to return code from rollout script
$HandleExitCode -session $session -destination $destination -exitCode $exitCode
$CleanUpRemote -session $session -destination $destination
}
Start-Job $ScriptBlock -Args $_
}
So if i go with the approach in the link I'd be converting all my functions to variables and passing them in to the script block. Currently, my log function will by default log in DEBUG unless the verbosity parameter is explicitly passed as a different verbosity. If I convert my functins to variables however powershell doesn't seem to like this syntax:
$Log ("Print this to the log")
So I think I'd need to use the parameter all the time now:
$Log ("Print this to the log" -v $debug
So bottom line it looks like I just need to pass all my functions as variables to the script block and change some formatting when I call them. It's not a huge effort, but I'd like to know if there's a better way before I start hacking my script up. Thanks for the input and for looking, I know this is quite a long post.
I started another post about passing parameters to functions stored as variables, the answer to that also resolves this issue. That post can be found here:
Powershell: passing parameters to functions stored in variables
The short answer is you can use the initializationscript parameter of Start-Job to feed all your functions in if you wrap them in a block and store that in a variable.
Example:
# concurrency
$func = {
function Logx
{
param(
[parameter(ValueFromPipeline=$true)]
$msg
)
Write-Host ("OUT:"+$msg)
}
}
# Execution starts here
cls
$colors = #("red","blue","green")
$colors | %{
$scriptBlock =
{
Logx $args[0]
Start-Sleep 9
}
Write-Host "Processing: " $_
Start-Job -InitializationScript $func -scriptblock $scriptBlock -args $_
}
Get-Job
while(Get-Job -State "Running")
{
write-host "Running..."
Start-Sleep 2
}
# Output
Get-Job | Receive-Job
# Cleanup jobs
Remove-Job *