Azure Devops - PowerShell task on self-hosted agent - azure-devops

I have an Azure Devops deployment pipeline setup which is building and I am able to deploy to a self hosted virtual machine with no issue.
I have the following powershell script that correctly clears down my destination directory leaving 2 folders that are not part of source control
Get-ChildItem -Path 'C:\inetpub\wwwroot\testDeploy\' -Recurse -exclude "pod","photos" |
Select -ExpandProperty FullName |
Where {$_ -notlike '*\pod\*' -and $_ -notlike '*\photos\*'} |
sort length -Descending |
Remove-Item -force
I have tried adding a "PowerShell Script" task but i'm don;t know how to get the PowerShell script in to a folder that the task can access i.e. $(System.DefaultWorkingDirectory). Can anyone advise how I should be either generating the file or where to store it in my repo that is then accessible by the self-hosted Windows agent

Agree with Shayki, you can create a powershell(.ps1) file in repos and paste your script in it to achieve that. And then, use powershell task to execute the script which in ps1 file.
But, as you said that you want it be maintained within the repos easily. Need made some change on your script:
Param(
[string]$RootPath,
[string]$File1,
[string]$File2,
[string]$NonLike1,
[string]$NonLike2
)
Get-ChildItem -Path $RootPath -Recurse -include $File1,$File2 |
Select -ExpandProperty FullName |
Where {$_ -notlike $NonLike1 -and $_ -notlike $NonLike2} |
sort length -Descending |
Remove-Item -Recurse -force
The first change is, you need to replace the hard code with variable. Pass the value with task, this is a good way to maintain your script.
The second which also the important change is add -Recurse after Remove-Item, or you will get the error showed below while the value of $RootPath is hard code, such as 'C:\Users\'.
Remove-Item : Windows PowerShell is in NonInteractive mode. Read and
Prompt functionality is not available.
And then, you can add task in your build pipeline. Add the Script path where the .ps1 file located and input the Arguments with the value:
If you want to access $(System.DefaultWorkingDirectory), pass it to $RootPath.
Hope my sample can help you achieve what you want.

Related

Using PDQ to Automate PowerShell or CMD to find and delete registry entries

We recently started using PDQ inventory and Deploy. We have some user endpoints that have corrupted agents from a different program. The fix for this corruption includes finding and deleting a registry key pertaining to that file. I am able to use both CMD and PowerShell in PDQ as steps to automate this process. I'm kind of at a loss since the registry value is different per asset.
How can I automate the function of finding the registry key and then deleting the registry key it finds?
So far I've tied the following command to a variable:
$RegKey = Get-ChildItem -Path HKLM:\SOFTWARE\Classes\Installer\Products -Recurse |
ForEach-Object { Get-ItemProperty $_.PSPath } |
Where-Object { $_ -like "*Rapid7 Insight Agent*" } |
Select-Object PSPath
Similarly, in CMD the manual commands are:
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\ /f "Rapid7 Insight Agent" /s
Reg Delete (with the value the previous reg query posts back)
Every provider that supports the Get-ChildItem cmdlet, also supports the Remove-Item cmdlet:
Get-ChildItem "HKLM:\SOFTWARE\Classes\Installer\Products" -Recurse |
Where-Object { $_.PSChildName -like "*Rapid7 Insight Agent*" } |
Remove-Item -Recurse

"PowerShell on Target Machines" task fails with an error in TFS 2017\Azure Dev Ops

I am trying to run a PowerShell script present on one of the azure server using the "PowerShell on Target Machines" Task in my TFS build definition, but the task fails with the below error.
System.Management.Automation.RuntimeException: The running command
stopped because the preference variable "ErrorActionPreference" or
common parameter is set to Stop: The specified path, file name, or
both are too long. The fully qualified file name must be less than 260
characters, and the directory name must be less than 248 characters.
--->
I have copied the script in F drive but it still gives path too long error, not able to find any solution for the same.
Does anyone know what would be the reason?
Added script code as well for reference,
GetLatestDebugOutput.ps1
$DebugBuildOutput = "F:\Drops\econNextGen\SecurityScan\19.0"
$Dest = "F:\Drops\econNextGen\SecurityScan\Debug Build Output"
Remove-Item "$Dest\*" -Recurse -Force
#Code to Copy Common-App Debug Build
$Dir= $DebugBuildOutput + "\econNextGen-Common-App-Debug\"
$Latest = Get-ChildItem -Path $Dir | Sort-Object LastAccessTime -Descending | Select-Object -First 1
$FolderPath= $Dir +$Latest.Name
Copy-Item -Path $FolderPath $Dest –Recurse -force
#Code to Copy Main-App Debug Build
$Dir= $DebugBuildOutput + "\econNextGen-MAIN-APP-Debug\"
$Latest = Get-ChildItem -Path $Dir | Sort-Object LastAccessTime -Descending | Select-Object -First 1
$FolderPath= $Dir +$Latest.Name
Copy-Item -Path $FolderPath $Dest –Recurse -force
First suggest you directly RDP to remote target machine and check if you are able to run the same script in it. This will narrow down if the issue related to your tfs build definition and environment.
For environment, make sure you have met all prerequisites of this PowerShell on Target Machines task. And you have qualified powershell version installed.
Actually the error message is pretty straight forward, and so is the key point you should pay attention to: make sure you're not using paths that are too long or using an invalidly path. If apply for all folder and files.
Besides, try starting the build with diagnostics\debug enabled with system.debug=true and see if you can get any meaningful output for future troubleshooting.

Powershell: Recursively search a drive or directory for a file type in a specific time frame of creation

I am trying to incorporate Powershell into my everyday workflow so I can move up from a Desktop Support guy to a Systems Admin. One question that I encountered when helping a coworker was how to search for a lost or forgotten file saved in an unknown directory. The pipeline I came up with was:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Out-File pdfs.txt
This code performed exactly how I wanted but now I want to extend this command and make it more efficient. Especially since my company has clients with very messy file management.
What I want to do with this pipeline:
Recursively search for a specific file-type that was created in a specified time-frame. Lets say the oldest file allowed in this search is a file from two days ago.
Save the file to a text file with the columns containing the Filename, FullName(Path), and sorted by the created time in descending order.
What I have so far:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Select-Object Name, FullName | Out-File *pdfs.txt
I really need help on how to create a filter for the time that the file was created. I think I need to use the Where-Object cmdlet right after the dir pipe and before the Select Object pipe but I don't know how to set that up. This is what I wrote: Where-Object {$_.CreationTime <
You're on the right track, to get the files from a specific file creation date range, you can pipe the dir command results to:
Where-Object {$_.CreationTime -ge "06/20/2017" -and $_.CreationTime -le "06/22/2017"}
If you want something more repeatable where you don't have to hard-code the dates everytime and just want to search for files from up to 2 days ago you can set variables:
$today = (Get-Date)
$daysago = (Get-Date).AddDays(-2)
then plugin the variables:
Where-Object {$_.CreationTime -ge $daysago -and $_.CreationTime -le $today}
I'm not near my Windows PC to test this but I think it should work!
See if this helps
dir c:\ -Recurse -Filter *.ps1 -ErrorAction SilentlyContinue -Force | select LastWriteTime,Name | Where-Object {$_.LastWriteTime -ge [DateTime]::Now.AddDays(-2) } | Out-File Temp.txt

Automating MS Updates with Powershell

I am trying to Automate my Microsoft update process based on the KB/MSU packages I download. I have a WMIC csv file that I am able to install based on simple If else statement. I would like to use the list extract just the "KBXXXXX" from the downloaded files and compare it to the list of installed KBs and discover what is missing.
KB install List (WMIC output):
KB123456
KB234567
KB345678
Downloaded KB file list format $KBUpdateList:
Name
WINDOWS6.1-KB2533552-X64.MSU
WINDOWS6.1-KB2533552-X86.MSU
WINDOWS6.1-KB2539635-X64.MSU
Windows6.1-KB958488-v6001-x64.MSU
Here is what I have that is not working to pull KB number:
PowerShell script to list the MSU files under the selected folder:
$Dir = get-childitem $folder -recurse
$KBUpdateList = $Dir | where {$_.extension -eq ".msu"}
$KBUpdatenames = $KBUpdateList | format-table name
$KBNumberonly = $KBUpdateList.split("-")[1]
The split fails and I can't find a fix. I just want to return the KBXXXX number so I can run my foreach statement that follows. Thank You
This should suffice for what you are looking for.
$KBUpdatenames = get-childitem $folder -recurse -Filter "*.msu" | Select-Object -Expand Name
$KBNumberonly = $KBUpdatenames | ForEach-Object{$_.split("-")[1]}
Use Get-ChildItem to get the files of type ".msu". Using -Filter is more efficient than Where-Object in most case where you are just looking for extensions. Then we expand just the names of the files with Select-Object
As for the Format-Table in your code I will refer you to an answer about Format-Taco that I enjoy.

Delete Directories based on time modified

I am using Powershell scripts to deploy the codebase on our remote servers.
One Major part of the script copies the current release to the server. Now I just need to keep the last two releases on the remote server and delete all others.
I Need to keep the latest two releases
Eg:
In the remote server, I have
//server001/Application/
Build_1_0_0_19
Build_1_0_0_18
Build_1_0_0_17
Build_1_0_0_16
I need to clear Builds _17 and _16 while deploying _19.
We can sort out the directories according to the time modified and the last two will come on top. Rest all are not required.
Can this be done through Powershell Scripts ?
P.S. The builds are not always in sequential order
You can do something like this:
#requires -version 2
Get-ChildItem //server001/Application/|
Sort-Object CreationTime -Descending|
Select-Object -Skip 2|
Remove-Item -Recurse -Confirm
Just remove the -Confirm switch once you are sure that it does what you want.
Here is a v1 compatible method:
$dirs = #(Get-ChildItem //server001/Application/)
$dirs|
Sort-Object CreationTime -Descending|
Select-Object -Last ($dirs.Count - 2)|
Remove-Item -Recurse -Confirm