Powershell script- send email to all users that are outputted - sql

This is my code below-
I am new to Powershell so Im looking for a way to send an email to all the users that are outputted and also send an an email to myself with the CSv file of output?
get-module azuread
$Credential = Get-Credential
Connect-AzureAD -Credential $Credential
$dt = (Get-Date).AddDays(-90)
$Users = Get-AzureADUser -Top 100000 | Where {$_.UserPrincipalName -like "*gmail.com"} | Select UserPrincipalName,ObjectId
$Users | ForEach-Object {
Get-AzureADDevice -All:$true | Where {$_.ApproximateLastLogonTimeStamp -le $dt}
$user = $_
Get-AzureADUserRegisteredDevice -ObjectId $user.ObjectId | ForEach-Object {
$Result += New-Object PSObject -property #{
DeviceOwner = $user.UserPrincipalName
DeviceName = $_.DisplayName
DeviceOSType = $_.DeviceOSType
ApproximateLastLogonTimeStamp = $_.ApproximateLastLogonTimeStamp
IsCompliant = $_.IsCompliant
}
}
}
thANK YOU

Related

Azure DevOps API: Get all files (source and target) of Pull Request

I searched quite a bit, found several threads here (e.g. this, that, and more), but I could not find the answer to the following task:
Use the Azure DevOps API to retrieve the content changes (basically the file before and after) of all the files of a specific PR.
I can find a PR, can loop through changes, iterations, commits (in various combinations), but I have not been able to download both the first and the last version of each or the files (and there should be a way as I can view the before and after in a PR in DevOps).
Any hints where/how I can retrieve both versions of a file of a certain commit/change/iteration?
Many thanks in advance!
Cheers,
Udo
Thanks for all the hints. Looks like I managed to find a wat to pull it. Please feel free to correct my approach.
Here's the complete PowerShell file:
[CmdletBinding()]
param (
[int]
$pullRequestId,
[string]
$repoName
)
# --- your own values ---
$pat = 'your-personal access token for Azure DevOps'
$urlOrganization = 'your Azure DevOps organization'
$urlProject = 'your Azure DevOps project'
$basePath = "$($env:TEMP)/pullRequest/" # a location to store all the data
# --- your own values ---
if (!$repoName)
{
$userInput = Read-Host "Please enter the repository name"
if (!$userInput)
{
Write-Error "No repository name given."
exit
}
$repoName = $userInput
}
if (!$pullRequestId)
{
$userInput = Read-Host "Please enter the PullRequest ID for $($repoName)"
if (!$userInput)
{
Write-Error "No PullRequest ID given."
exit
}
$pullRequestId = $userInput
}
$prPath = "$($basePath)$($pullRequestId)"
$sourcePath = "$($basePath)$($pullRequestId)/before"
$targetPath = "$($basePath)$($pullRequestId)/after"
# --- helper methods ---
function CleanLocation([string]$toBeCreated)
{
RemoveLocation $toBeCreated
CreateLocation $toBeCreated
if (!(Test-Path $toBeCreated))
{
Write-Error "Path '$toBeCreated' could not be created"
}
}
function CreateLocation([string]$toBeCreated)
{
if (!(Test-Path $toBeCreated)) { New-Item -ErrorAction Ignore -ItemType directory -Path $toBeCreated > $null }
}
function RemoveLocation([string]$toBeDeleted)
{
if (Test-Path $toBeDeleted) { Remove-Item -Path $toBeDeleted -Recurse -Force }
}
function DeleteFile([string]$toBeDeleted)
{
if (Test-Path $toBeDeleted) { Remove-Item -Path $toBeDeleted -Force }
}
# --- helper methods ---
# --- Azure DevOps helper methods ---
function GetFromDevOps($url)
{
$patToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$repoHeader = #{ "Authorization" = "Basic $patToken" }
$response = $(Invoke-WebRequest $url -Headers $repoHeader)
if ($response.StatusCode -ne 200)
{
Write-Error "FAILED: $($response.StatusDescription)"
}
return $response
}
function JsonFromDevOps($url)
{
$response = GetFromDevOps $url
return ConvertFrom-Json -InputObject $response.Content
}
function DownloadFromDevOps($url, $filename)
{
$patToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$repoHeader = #{ "Authorization" = "Basic $patToken" }
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest $url -Headers $repoHeader -OutFile $filename
$ProgressPreference = 'Continue'
}
function DownloadAndSaveFile($itemUrl, $outputPath, $path, $overwrite)
{
$outFile = "$outputPath$($path)"
$fileExists = Test-Path $outFile
if (!$fileExists -or $overwrite)
{
$outPath = [System.IO.Path]::GetDirectoryName($outFile)
CreateLocation $outPath
if ($fileExists)
{
Write-Host " overwriting to $outputPath"
}
else
{
Write-Host " downloading to $outputPath"
}
DownloadFromDevOps $itemUrl $outFile
}
}
function DownloadFiles($changes, $beforePath, $beforeCommitId, $afterPath, $afterCommitId)
{
foreach ($change in $changes)
{
$item = $change.item
if ($item.isFolder)
{
continue;
}
$path = $item.path
$originalPath = $change.originalPath
if (!$path)
{
$path = $change.originalPath
}
$displayPath = $path ?? $originalPath
$changeType = $change.changeType
Write-Host "[$($changeType)] $($displayPath)"
if (($changeType -eq "edit, rename"))
{
$itemUrl = "$($urlRepository)/items?path=$($originalPath)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
DownloadAndSaveFile $itemUrl $beforePath $originalPath
}
# just get the source/before version
if ($changeType -eq "delete")
{
$itemUrl = "$($urlRepository)/items?path=$($originalPath)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
DownloadAndSaveFile $itemUrl $beforePath $originalPath
DeleteFile "$($afterPath)$($originalPath)"
}
if ($changeType -eq "edit")
{
$itemUrl = "$($urlRepository)/items?path=$($path)&versionDescriptor.version=$($beforeCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
DownloadAndSaveFile $itemUrl $beforePath $path
}
if (($changeType -eq "add") -or ($changeType -eq "edit") -or ($changeType -eq "edit, rename"))
{
$itemUrl = "$($urlRepository)/items?path=$($path)&versionDescriptor.version=$($afterCommitId)&versionDescriptor.versionOptions=0&versionDescriptor.versionType=2&download=true"
DownloadAndSaveFile $itemUrl $afterPath $path $true
}
$validChangeTypes = #('add', 'delete', 'edit', 'edit, rename')
if (!($validChangeTypes.Contains($changeType)))
{
Write-Warning "Unknown change type $($changeType)"
}
}
}
# --- Azure DevOps helper methods ---
$urlBase = "https://dev.azure.com/$($urlOrganization)/$($urlProject)/_apis"
$urlRepository = "$($urlBase)/git/repositories/$($repoName)"
$urlPullRequests = "$($urlRepository)/pullRequests"
$urlPullRequest = "$($urlPullRequests)/$($pullRequestId)"
$urlIterations = "$($urlPullRequest)/iterations"
CleanLocation $prPath
$iterations = JsonFromDevOps $urlIterations
foreach ($iteration in $iterations.value)
{
# the modified file
$srcId = $iteration.sourceRefCommit.commitId
# the original file
$comId = $iteration.commonRefCommit.commitId
$comId = $iteration.targetRefCommit.commitId
$urlIterationChanges = "$($urlIterations)/$($iteration.id)/changes"
$iterationChanges = JsonFromDevOps $urlIterationChanges
DownloadFiles $iterationChanges.changeEntries $sourcePath $comId $targetPath $srcId
}

Azure Runbook not deleting Files in Fileshare

I am trying to to use Azure Powershell Runbooks to delete files out of the Azure Fileshare. There are no errors returned, but the file is not deleted. The Automation Account has a Run As account setup that is not expired or anything and the script works if I run it from my local machine. Looking for some advise on this.
$ctx = New-AzureStorageContext -StorageAccountName "" -StorageAccountKey ""
$shareName = ""
$directoryPath = ".cloudconsole"
$DirIndex = 0
$day = 1
$startdate = (Get-Date).AddDays(-180)
$endDate = (Get-date).AddDays(-32)
$dirsToList = New-Object System.Collections.Generic.List[System.Object]
$shareroot = Get-AzureStorageFile -ShareName $shareName -Path $directoryPath -context $ctx
$dirsToList += $shareroot
While ($dirsToList.Count -gt $DirIndex)
{
$dir = $dirsToList[$DirIndex]
$DirIndex ++
$fileListItems = $dir | Get-AzureStorageFile
$dirsListOut = $fileListItems | where {$_.GetType().Name -eq "AzureStorageFileDirectory"}
$dirsToList += $dirsListOut
$files = $fileListItems | where {$_.GetType().Name -eq "AzureStorageFile"}
foreach($file in $files)
{
$task = $file.CloudFile.FetchAttributesAsync()
$task.Wait()
if ($file.CloudFile.Properties.LastModified -ge $startdate -and $file.CloudFile.Properties.LastModified -ge $endDate )
{
if ($file.CloudFile.Properties.LastModified.day -ne '01' )
{
$file | Remove-AzureStorageFile
}
}
if ($file.CloudFile.Properties.LastModified -lt $startdate)
{
$file | Remove-AzureStorageFile
}
}
}
BoxJumper: As kavyasaraboju-MT referred, below piece of script should help you.
$ctx = New-AzStorageContext -StorageAccountName $accountName -StorageAccountKey $key
$shareName = <shareName>
$startdate = (Get-Date).AddDays(-180)
$endDate = (Get-date).AddDays(-32)
$DirIndex = 0
$dirsToList = New-Object System.Collections.Generic.List[System.Object]
# Get share root Dir
$shareroot = Get-AzStorageFile -ShareName $shareName -Path . -context $ctx
$dirsToList += $shareroot
# List files recursively and remove file older than 14 days
While ($dirsToList.Count -gt $DirIndex)
{
$dir = $dirsToList[$DirIndex]
$DirIndex ++
$fileListItems = $dir | Get-AzStorageFile
$dirsListOut = $fileListItems | where {$_.GetType().Name -eq "AzureStorageFileDirectory"}
$dirsToList += $dirsListOut
$files = $fileListItems | where {$_.GetType().Name -eq "AzureStorageFile"}
foreach($file in $files)
{
# Fetch Attributes of each file and output
$task = $file.CloudFile.FetchAttributesAsync()
$task.Wait()
# remove file if it's modified between after last 180 days and before last 30 Days
if ($file.CloudFile.Properties.LastModified -lt (Get-Date).AddDays(-32) -and $file.CloudFile.Properties.LastModified -ge (Get-Date).AddDays(-180))
{
## print the file LMT
# $file | Select #{ Name = "Uri"; Expression = { $_.CloudFile.SnapshotQualifiedUri} }, #{ Name = "LastModified"; Expression = { $_.CloudFile.Properties.LastModified } }
# remove file
$file | Remove-AzStorageFile
}
}
#Debug log
# Write-Host $DirIndex $dirsToList.Length $dir.CloudFileDirectory.SnapshotQualifiedUri.ToString()
}

Efficient Script to get all Extended File Properties

I'm pretty new working with Powershell and i have some working code but I'm not sure how to get it into an efficient routine to return all of the extended file properties of some video files i have.
I have:
# The basic setup for the next steps
$path = 'C:\test\videotocheck.mp4'
$shell = New-Object -COMObject Shell.Application
$folder = Split-Path $path
$file = Split-Path $path -Leaf
$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)
# This command gets a list of all the extended attributes available for this file
0..500 | Foreach-Object { '{0} = {1}' -f $_, $shellfolder.GetDetailsOf($null, $_) }
# These commands get the individual attributes picked out of the list above
$shellfolder.GetDetailsOf($shellfile, 314)
$shellfolder.GetDetailsOf($shellfile, 316)
All i want to do is provide a filename and have it give me a list back of all of the attributes and their values (if they have one.)
Example:
I intend to use this in a SQL stored procedure. I can work with different types of output if that's easier.
I'm mostly interested in dimensions
Any guidance would be appreciated.
To get all of this extended metadate you could use the function below.
You can give it the path to a single file, or the path to a folder where the files are.
function Get-MetaData {
[CmdletBinding()]
[OutputType([Psobject[]])]
Param (
# Path can be the path to a folder or the full path and filename of a single file
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[string]$Path,
# Pattern is unused if Path is pointing to a single file
[Alias('Filter')]
[string]$Pattern = '*.*',
[Alias('Indices')]
[int[]]$Properties = 1..500,
# Recurse is unused if Path is pointing to a single file
[switch]$Recurse,
[switch]$IncludeEmptyProperties
)
$item = Get-Item -Path $Path -ErrorAction SilentlyContinue
if (!$item) { Write-Error "$Path could not be found."; return }
if (!$item.PSIsContainer) {
# it's a file
$files = #($item)
$Path = $item.DirectoryName
}
else {
# it's a folder
$files = Get-ChildItem -Path $Path -Filter $Pattern -File -Recurse:$Recurse
}
$shell = New-Object -ComObject "Shell.Application"
$objDir = $shell.NameSpace($Path)
foreach($file in $files) {
$objFile = $objDir.ParseName($file.Name)
$mediaFile = $objDir.Items()
foreach($index in $Properties) {
$name = $objDir.GetDetailsOf($mediaFile, $index)
if (![string]::IsNullOrWhiteSpace($name)) {
$value = $objDir.GetDetailsOf($objFile, $index)
if (![string]::IsNullOrWhiteSpace($value) -or $IncludeEmptyProperties) {
[PsCustomObject]#{
Path = $file.FullName
Index = $index
Property = $name
Value = $value
}
}
}
}
}
# clean-up Com objects
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objFile)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objDir)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
You can of course play around with the different parameters the function can take like -Pattern '*.mp4' to only list properties for mp4 files or add switch -IncludeEmptyProperties to also list properties that exist for that file type, but have no value for the specified file.
With parameter Properties you can give the function an array of int32 values of the property indices to return. If you leave that open, the function tries to get all properties from index 1 to index 500 (if available).
Most of the interesting property indices can be found at:
audio/video files: 0,1,2,3,4,5,9,11,12,13,14,15,16,17,18,19,20,21,22,26,27,28,36,164,165,194,213,220,223,237,243
font files:
0,1,2,3,4,5,20,21,25,33,34,164,165,166,196,310
image files:
0,1,2,3,4,5,9,11,31,164,165,174,175,176,177,178,194,196
Use it like this:
$result = Get-MetaData -Path '<pathToTheFile_OR_pathToTheFolder>'
# output to GridView
$result | Out-GridView
# output to CSV file
$result | Export-Csv -Path '<pathToTheOutput.csv>' -NoTypeInformation
Here's a simplified version similar to Theo's. It will accept file/folder paths or objects via pipeline or as parameter.
Function Get-FileMetaData {
[cmdletbinding()]
Param
(
[parameter(valuefrompipeline,ValueFromPipelineByPropertyName,Position=1,Mandatory)]
$InputObject
)
begin
{
$shell = New-Object -ComObject Shell.Application
}
process
{
foreach($object in $InputObject)
{
if($object -is [string])
{
try
{
$object = Get-Item $object -ErrorAction Stop
}
catch
{
Write-Warning "Error while processing $object : $($_.exception.message)"
break
}
}
try
{
Test-Path $object -ErrorAction Stop
}
catch
{
Write-Warning "Error while processing $($object.fullname) : $($_.exception.message)"
break
}
switch ($object)
{
{$_ -is [System.IO.DirectoryInfo]}{
write-host Processing folder $object.FullName -ForegroundColor Cyan
$currentfolder = $shell.namespace($object.FullName)
$items = $currentfolder.items()
}
{$_ -is [System.IO.FileInfo]}{
write-host Processing file $object.FullName -ForegroundColor Cyan
$parent = Split-Path $object
$currentfolder = $shell.namespace($parent)
$items = $currentfolder.ParseName((Split-Path $object -Leaf))
}
}
try
{
foreach($item in $items)
{
0..512 | ForEach-Object -Begin {$ht = [ordered]#{}}{
if($value = $currentfolder.GetDetailsOf($item,$_))
{
if($propname = $currentfolder.GetDetailsOf($null,$_))
{
$ht.Add($propname,$value)
}
}
} -End {[PSCustomObject]$ht}
}
}
catch
{
Write-Warning "Error while processing $($item.fullname) : $($_.exception.message)"
}
}
}
end
{
$shell = $null
}
}

PowerShell script with looping can not work after encryption

I have powershell script with looping. But After I encrypt the script. The looping is always running and never stop.
Anyone can help please. THank you
Function 101_Pr
{
Write-Host " 101_Pr"
}
Function CleanUp
{
Write-Host "CleanUp"
}
Function Image
{
$Stoploop = $false
[int]$Retrycount = "0"
do {
try {
$Get = "123AB"
$connectionString = "Server=$IP;uid=$UID;pwd=$Pswd;Database=$Database;Integrated Security=False;"
Write-Host $connectionString
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$query = "select Number='$Get'"
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = new-object "System.Data.DataTable"
$table.Load($result)
[array] $DB = $table.Number
Write-Host "Result: $DB"
if($null -ne $DB)
{
$Stoploop = $true
101_Pr
break
}
}
catch {
if ($Retrycount -gt 2)
{
Write-Host "Could not get after 3 retrys."
$Stoploop = $true
CleanUp
break
}
else{
Write-Host "Retry"
Start-Sleep -s 1
$Retrycount = $Retrycount + 1
}
}
}
While ($Stoploop -eq $false)
}
Image
The output is always print this Write-Host $connectionString
I use this script for encryption
ps2exe.ps1
anyone can help really appreciated. THank you

POLONIEX API Connect

I'm trying to connect to POLONIEX API using powershell. I've tried different variation of the following code without any luck. Could anyone take a look to see what I'm missing?
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$uri = 'https://poloniex.com/tradingApi'
$key = 'POLO-API-SECRET-KEY'
$secret= 'poloapisecret'
$nonce = [int][double]::Parse((Get-Date (get-date).touniversaltime() -UFormat %s))
$postParams = #{command="returnBalances";nonce="$nonce"}
### Encode URL and convert to raw bytes
#$utf8enc = New-Object System.Text.UTF8Encoding
#$postParams_bytes = $utf8enc.GetBytes($postParams)
$hmacsha = New-Object System.Security.Cryptography.HMACSHA512
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($secret)
$signature =
$hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($postParams))
$sign = [Convert]::ToBase64String($signature)
$headers2 = #{key="$key";sign="$sign"}
# $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
# $headers.Add("key",$key)
# $headers.Add("sign",$sign)
Invoke-WebRequest -Uri $uri -Method POST -Body $postParams -Headers $headers2 #| ConvertFrom-Json
BIG THANKS in advance for any help!!!
Well that was quite a ride; searched half the web, learned a lot and here is what I came up with. More functions may be adopted from https://pastebin.com/iuezwGRZ.
It would be great if you share your final script here also.
$PoloniexKey = "01234567-89ABCDEF-GHIJKLMN-OPQRSTUV"
$PoloniexSecret = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghij"
$TradingUri = 'https://poloniex.com/tradingApi'
$PublicUri = 'https://poloniex.com/public'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# source: https://stackoverflow.com/questions/40680882/trying-to-make-hmac-sha256-work-with-powershell-for-canvas-api
function Buffer($string) {
$c=#()
Foreach ($element in $string.toCharArray()) {$c+= [System.Convert]::ToSByte($element)}
return $c
}
# source: https://www.remkoweijnen.nl/blog/2013/04/05/convert-bin-to-hex-and-hex-to-bin-in-powershell/
function BinToHex {
param(
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true)
]
[Byte[]]$Bin)
# assume pipeline input if we don't have an array (surely there must be a better way)
if ($bin.Length -eq 1) {$bin = #($input)}
$return = -join ($Bin | foreach { "{0:X2}" -f $_ })
return $return.ToLower()
}
# source: https://gist.github.com/jokecamp/2c1a67b8f277797ecdb3
function HmacSHA512($Message, $Secret) {
$HMACSHA512 = new-object System.Security.Cryptography.HMACSHA512
$HMACSHA512.key = Buffer -string $Secret
$StringToHash = [System.Text.Encoding]::UTF8.GetBytes($Message)
$HashByteArray = $HMACSHA512.ComputeHash($StringToHash)
$hash = BinToHex $HashByteArray
return $hash;
}
function Invoke-PoloniexRequest($Request, $Uri=$TradingUri) {
$Nonce = ([int64](Get-Date (get-date).touniversaltime() -UFormat %s))*10
$Request.Add('nonce', $Nonce)
$RequestArray=#()
$Request.GetEnumerator() | %{$RequestArray += ($_.Name,$_.Value -join '=')}
$Body = $RequestArray -join '&'
$Sign = HmacSHA512 -Message $Body -Secret $PoloniexSecret
$Headers = #{
Key = $PoloniexKey
Sign = $Sign
}
Invoke-WebRequest -Uri $Uri -Method POST -Body $Body -Headers $Headers | ConvertFrom-Json
}
function Get-PoloniexBalances {
$request = #{command="returnBalances"}
return Invoke-PoloniexRequest -Request $request
}
$Balances = Get-PoloniexBalances