Downloading Images with PowerShell script - shell

I normally use a PowerShell script to download bulk CSV of images, but I have a new URL that displays the images very oddly. Could I modify this script to allow for these image URLs?
Example URLs:
https://www.example.com/core/media/media.nl?id=12&c=23&h=b944f2f81326d0bb
https://www.example.com/core/media/media.nl?id=15&c=42&h=7ed23c91f3574fc9
and the current script...
[Reflection.Assembly]::LoadFile(
'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll') | Out-Null
$FileName = "C:\Temp\test.txt";
$Loc = "C:\Temp\Images\"
$ImageName = ""
$wc = New-Object System.Net.WebClient
$content = Get-Content $FileName
foreach ($line in $content) {
$Image = $Loc + $line.Substring($line.LastIndexOf("/") + 1)
$url = $line
Write-Host $url
Write-Host $Image
$wc.DownloadFile($url, $Image)
}
Write-Jost "Finished successfully."

A file name on Windows can't contain ?, *, ", \ characters, so filter them out:
$Image = $Loc + ($line.Substring($line.LastIndexOf("/") + 1) -replace '[?*"\\]', '_')
To get the real redirected file name from a dynamic URL process the Content-Disposition header:
$tmp = [IO.Path]::GetTempFileName()
$wc.DownloadFile($url, $tmp)
$Image = "$($wc.ResponseHeaders['Content-Disposition'])" -replace '^.*?filename=', ''
if (!$Image) {
$Image = $line.Substring($line.LastIndexOf("/") + 1) -replace '[?*"\\]', '_'
}
Move $tmp (Join-Path $Loc $Image)

Related

Powershell to Audit Folder Permissions Showing Group Membership

Background: I've been using Netwrix to audit permissions to network shares for a few years now and It's only ever worked smoothly 1 time..... So I've decided to move on to just an automated powershell script. I've run into a block. When I try to parse out the group members, it doesn't like the network name in front of the group name (TBANK). Then I also need to take the next step of just showing the name instead of the whole output of get-adgroupmember. Any help would be greatly appreciated as I'm very to to scripting with powershell. Current script below:
$OutFile = "C:\users\user1\Desktop\test.csv" # Insert folder path where you want to save your file and its name
$Header = "Folder Path,IdentityReference, Members,AccessControlType,IsInherited,InheritanceFlags,PropagationFlags"
$FileExist = Test-Path $OutFile
If ($FileExist -eq $True) {Del $OutFile}
Add-Content -Value $Header -Path $OutFile
$Folder = "\\server1.tbank.com\share1"
$ACLs = get-acl $Folder | ForEach-Object { $_.Access }
Foreach ($ACL in $ACLs){
$ID = $ACL.IdentityReference
$ID = $ID -replace 'TBANK\' , ''
$ACType = $ACL.AccessControlType
$ACInher = $ACL.IsInherited
$ACInherFlags = $ACL.InheritanceFlags
$ACProp = $ACL.PropagationFlags
$Members = get-adgroupmember $ID.
$OutInfo = $Folder + "," + $ID + "," + $Members + "," + $ACType + "," + $ACInher + "," + $ACInherFlags + "," + $ACProp
Add-Content -Value $OutInfo -Path $OutFile
}
First of all, there is a way better way to output a CSV file than by trying to write each row yourself (with the risk of missing out required quotes), called Export-Csv.
To use that cmdlet, you wil need to create an array of objects which is not hard to do.
$OutFile = "C:\users\user1\Desktop\test.csv" # Insert folder path where you want to save your file and its name
$Folder = "\\server1.tbank.com\share1"
# get the Acl.Access for the folder, loop through and collect PSObjects in variable $result
$result = (Get-Acl -Path $Folder).Access | ForEach-Object {
# -replace uses regex, so you need to anchor to the beginning of
# the string with '^' and escape the backslash by doubling it
$id = $_.IdentityReference -replace '^TBANK\\' # remove the starting string "TBANK\"
# Get-ADGroupMember can return users, groups, and computers. If you only want users, do this:
# $members = (Get-ADGroupMember -Identity $id | Where-Object { $_.objectClass -eq 'user'}).name -join ', '
$members = (Get-ADGroupMember -Identity $id).name -join ', '
# output an onbject with all properties you need
[PsCustomObject]#{
'Folder Path' = $Folder
'IdentityReference' = $id
'Members' = $members
'AccessControlType' = $_.AccessControlType
'IsInherited' = $_.IsInherited
'InheritanceFlags' = $_.InheritanceFlags -join ', '
'PropagationFlags' = $_.PropagationFlags -join ', '
}
}
# output on screen
$result | Format-List
# output to CSV file
$result | Export-Csv -Path $OutFile -Force -UseCulture -NoTypeInformation
I've added a lot of inline comments to hopefully make things clear for you.
The -UseCulture switch in the Export-Csv line makes sure the field delimiter that is used matches what is set in your system as list separator. This helps when opening the csv file in Excel.
P.S> the Get-ADGroupMember cmdlet also has a switch called -Recursive. With that, it will also get the members from groups inside groups

Powershell locking first and last files and I cannot delete them without close powershell ISE

So I have a Powershell ISE ( tried running as administrator and w/o ) and it is created dummy .mdf file , 50 of them
Problem is that it holds onto the 1st and last , so copying or deleting them is not working ...
This is my script
param(
$amount = 50 # $(throw "Please give an amount of files to be created")
, $size = 5 # $(throw "Please give a the size of the files")
, $folder = "C:\dev\powershell\oldlocation" # $(throw "Please give an output folder wehere the files need to be created")
, $name = 'db' # $null
, $extension = '.mdf' # $null .mdf / .ldf
)
CLS
# Check for input
if(Test-Path $folder)
{
if($name -eq $null)
{
Write-Host "No filename given. Using default setting 'dummy'" -ForegroundColor Yellow
$name = 'dummy'
}
if($extension -eq $null)
{
Write-Host "No filename extension given. Using default setting '.txt'" -ForegroundColor Yellow
$extension = 'txt'
}
elseif($extension -contains '.')
{
$extension = $extension.Substring(($extension.LastIndexOf(".") + 1), ($extension.Length - 1))
}
for($i = 1; $i -le $amount; $i++)
{
$path = $folder + '\' + $name + '_' + $i + '.' + $extension
$file = [io.file]::Create($path)
$file.SetLength($size)
$file.Close
sleep 0.5
}
}
else{
Write-Host "The folder $folder doesn't exist" -ForegroundColor Red
Exit(0)
}
When () are omitted on a method, it returns the Overload Definitions. So the line where you are trying to close the file just needs ().
$file.Close()
If you see OverloadDefinitions ever returned, that's what to look for.

send mail after successfull powershell script execution

So I created the script below:
$target = "c:\$(get-date -F 'yyyy-MM')"
if (!(Test-Path $target)) {md $target}
gci 'c:\test\' -Filter *.xml -recurse | ?{!$_.PSIsContainer -and $_.CreationTime -ge (get-date "01.$((get-date).Month)")} | copy-item -Destination $target -Force
Could somebody point me to the right direction of how to send a email to a specific address after this script was successfully executed ?
As arco444 noted in his comment, send-mailmessage will allow you to send email from any machine running Powershell v2 or higher, as long as you have an accessible SMTP server.
you can try below solution in PowerShell
$EmailFrom = "someone1#company.com"
$EmailTo = "someone2#company.com"
$ccUsers="someone3#company.com"
$SMTPServer = "smtp.office365.com"
$port=587
$smtp = New-Object Net.Mail.SmtpClient($SMTPServer,$port)
$smtp.EnableSsl = "true"
$smtp.Credentials =New-Object System.Net.NetworkCredential($userName, $password);
$msg = New-Object Net.Mail.MailMessage
$msg.From = $EmailFrom
$msg.To.Add($EmailTo)
$msg.CC.Add($ccUsers)
$msg.IsBodyHTML = $true
$msg.Subject = "Test Subject";
#if you want to send some html in your email
$html = "<html><body><table width='100%'><tr bgcolor='#CCCCCC'><td height='25' align='center'> <font face='tahoma' color='#003399' size='4'><strong>Test Email from PowerShell</strong></font></td> </tr> </table></body></html>" $msg.Body = $html; $smtp.Send($msg);
If your using outlook, here is a example
[system.reflection.assembly]::loadwithpartialname("Microsoft.office.interop.outlook")
$OL=New-Object -ComObject OUTLOOK.APPLICATION
$ns =$OL.GETNAMESPACE("MAPI")
$mail =$ol.createitem(0)
$mail.recipients.add("something#live.nl")
$mail.CC=("something#ziggo.nl")
$MAIL.Subject= "$shortname"
#gets a signature
$mail.htmlbody= get-content $env:appdata\Microsoft\Signatures\*.txt
#for attachments..
$mail.Attachments.Add($file.FullName)
$lines=get-content $filename
$lines+=get-content $env:appdata\Microsoft\Signatures\*.txt
clear-variable text
foreach ($line in $lines)
{
$text += $line + "`r`n"
}
$mail.body= $text
$mail.display()

How to name downloaded file?

My boss has asked me to create a function/Script to download files off a website and place them in a folder:
Add-Type -AssemblyName Microsoft.Visualbasic
$url = "http://www.rarlab.com/rar/wrar521.exe"
$output = "C:\Users\****\Downloads\test\1"
$object = New-Object Net.WebClient
$object.DownloadFile($url, $output)
#######################################
$start_time = Get-Date
Write-Output "Time Taken((Get-Date).Subtract($start_time).Seconds) second(s)"
This is the current code I've got. Basically, what I need it to do is automatically name the file or resolve the name from the server with out me having to put $output = "C:\Users\****\Downloads\test\test.txt" or something.
Use Split-Path to split the filename from the URL, and Join-Path to join it to the folder path:
$url = 'http://www.rarlab.com/rar/wrar521.exe'
$filename = Split-Path -Leaf $url
$output = Join-Path 'C:\Users\****\Downloads\test\1' $filename
(New-Object Net.WebClient).DownloadFile($url, $output)

Checking if registry value is equal to 1 is not working correctly

I have slopped together bits of PowerShell to remote query a list of machines, stored in a .csv file, for a registry value. If the registry key's value is equal to '1', the script should then create a text file using the machine's name as the name of the text file.
Everything works great. The script runs happily without any errors. The problem is that when I go back and remotely check a targeted registry value, I find that the value isn't 1. The script is simply creating a file for every line in the .csv.
What am I doing wrong?
EDIT*** I found a problem I had a typo in the $key variable for the registry path. 7/17/2013 2:21p
$File = Import-Csv 'c:\temp\machines.csv'
foreach ($line in $file)
{
$machinename = $line.machinename
trap [Exception] {continue}
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$MachineName)
$key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon"
$regkey = ""
$regkey = $reg.opensubkey($key)
$keyValue = ""
$keyValue = $regKey.GetValue('AutoAdminLogon')
if ($keyValue = "1")
{
try
{
$textFile = New-Item -Path "c:\temp\autologin" -Name $MachineName -ItemType "File"
}
catch
{
$msg = $_
$msg
}
}
$Results = $MachineName , $keyValue
Write-host $Results
#Output Below Here:
}
In PowerShell = is an assignment operator, not a comparison operator. Change this line:
if ($keyValue = "1")
into this:
if ($keyValue -eq "1")
For more information see Get-Help about_Operators.
You're making this way too complicated, BTW. Something like this should suffice:
$keyname = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon'
Import-Csv 'C:\temp\machines.csv' | % {
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",
$_.machinename)
$key = $reg.OpenSubkey($keyname)
$value = $key.GetValue('AutoAdminLogon')
if ($value -eq "1") {
$filename = Join-Path "c:\temp\autologin" $_.machinename
try {
touch $filename
$textFile = Get-Item $filename
} catch {
$_
}
}
Write-Host ($_.machinename , $value)
}

Resources