PowerShell saves clipboard pictures and constructs a MarkDown statement

target

Recently learning to write documents with MarkDown, I hate passing pictures.Prepare to build your own wheel with PowerShell, but also search ahead and find a lot of Big Brother's documents.

The whole process to do is

  1. Copy Clipboard Picture with Mouse
  2. Enter program processing logic
  3. Processing clipboard pictures, saving cost local files (png or jpg)
  4. Upload to a map bed to get a connection to the map bed
  5. Construct the link to the map bed into the format required by MarkDown and stuff it back into the clipboard.
  6. Go back to the MarkDown editor and clip directly.

The goal is phase 2 content, completely scripted.

Realization

PowerShell is easy to create and modify files. The key point here is to use the.net method to manipulate pictures directly.

$img = [Windows.Clipboard]::GetImage()

Based on this keyword, let's take a look
Clipboard Class And there's a specific way to do that

GetImage() Returns a BitmapSource object from the Clipboard that contains data in the Bitmap format.

Not only can you get, but also set here. Not only pictures, but also text and audio can be operated. It is a complete set of schemes for the clipboard.The original output format is PNG, I want to try how to output JPG

picture

Just now we have finalized the contents of the clipboard. Next, we need to save the clipboard data as a picture.

Code

This can be learned

ImageCodecInfo.GetImageEncoders Method

Clipboard Save PNG

#Clipboard saves png directly
Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()
if ($null -eq $img ) {
  Write-Host "Clipboard no map"
  Exit
}
$fcb = New-Object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$filename = ((Get-Date -f s) -replace '[-T:]', '')
$file = "c:/img/{0}.jpg" -f $filename
Write-Host ("`n Find Pictures. {0}x{1} Pixels, saved to{2}`n" -f $img.PixelWidth, $img.PixelHeight, $file)
$stream = [IO.File]::Open($file, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb))
$encoder.Save($stream)
# $stream.Dispose()

Various styles, not limited to PowerShell

{
    Bitmap bmp1 = new Bitmap(typeof(Button), "Button.bmp");
    bmp1.Save(@"c:\button.png", ImageFormat.Png);
}
#Store pictures relatively easily
#https://stackoverflow.com/questions/41665/bmp-to-jpg-png-in-c-sharp
#Advanced Storage Pictures
#https://stackoverflow.com/questions/1484759/quality-of-a-saved-jpg-in-c-sharp
#Official examples
#https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.imagecodecinfo.getimageencoders?view=netframework-4.8

PNG Conversion JPG

A trick used here is Add-Type-AssemblyName system.drawing

    Add-Type -AssemblyName system.drawing
    $Source="C:\img\tt2.png"
    $imageFormat = "System.Drawing.Imaging.ImageFormat" -as [type]
    $image = [drawing.image]::FromFile($Source)
    # Create a new image
    $NewImage = [System.Drawing.Bitmap]::new($Image.Width,$Image.Height)
    $NewImage.SetResolution($Image.HorizontalResolution,$Image.VerticalResolution)
    #Add graphics from new images
    $Graphics = [System.Drawing.Graphics]::FromImage($NewImage)
    $Graphics.Clear([System.Drawing.Color]::White) # Set the color to white
    $Graphics.DrawImageUnscaled($image,0,0) # Add the contents of $image
    #storage
    $NewImage.Save("c:\img\vvv.jpg",$imageFormat::Jpeg)

Read an IMG, resize, and write

Add-Type -AssemblyName System.Drawing 
$img = New-Object System.Drawing.Bitmap(96, 96) 
([System.Drawing.Graphics]::FromImage($img)).DrawImage([System.Drawing.Image]::FromFile((Get-Item C:\img\20191104135629.jpg)), 0, 0, 128, 128) 
$jpegCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | where {$_.MimeType -eq 'image/jpeg'} $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1) 
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter([System.Drawing.Imaging.Encoder]::Quality, 90) 
$img.Save("c:\img\bouska2.jpg", $jpegCodecInfo, $encoderParams) 
$img.Dispose() 

Transfer files to github using GIT

github is a money-Free computer bed that allows you to upload and download files using git.

  • Configure local git
    git config --global user.name "User name"
    git config --global user.email "email"
    cd ~/.ssh
    ssh-keygen -t rsa -C "email"
    #This step above is to generate a certificate to communicate with github.
  • Configure github receive key

open Here , find SSH and GPG keys in the right menu bar, select new SSH key, enter title, the contents of the key below is the native ssh key, which is the public key just generated, paste the contents of id_rsa.pub directly, and click add SSH key below to complete.

  • Copy Key

Enter the command cat id_rsa.pub, and it will come out like the following, and copy it out, which is the key
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRyubAWD7PfF+baIYAYVpdtTag7YZYdmCNz2mkoMjxkP6aN5C/Rnxxxxxxxxxxxxxxxxxxxxx5sSNV42co5S4Tc5W3eBB9bPBIoObqZ/g8JkCVrEIgUXTO1rn9p7h5erQ0/TcC/tIQ+HVxVx+mV7Y/wcYY05+Bbm8Cv60= a9y@live.cn

  • Create directory locally C:\gitupdate

git remote add origin https://github.com/kukisama/kukisama.github.io Add a local directory

git add c:/gitupdate/picupdate/tt.txt Upload local file

Git commit-m "for a description"

git push origin master pull back

git pull origin master upload

The preconditions are almost ready, so you can see the full code.

The clipboard saves the png directly, passes it to github, and references the address of the github page

#Clipboard saves png directly
Add-Type -Assembly PresentationCore
$img = [Windows.Clipboard]::GetImage()
if ($null -eq $img ) {
  Write-Host "Clipboard no map"
}
$rootpath="C:/kukisama.github.io/picupdate/"
$fcb = New-Object Windows.Media.Imaging.FormatConvertedBitmap($img, [Windows.Media.PixelFormats]::Rgb24, $null, 0)
$filename = ((Get-Date -f s) -replace '[-T:]', '')
$file = "$rootpath{0}.png" -f $filename
Write-Host ("`n Find Pictures. {0}x{1} Pixels, saved to{2}`n" -f $img.PixelWidth, $img.PixelHeight, $file)
$stream = [IO.File]::Open($file, "OpenOrCreate")
$encoder = New-Object Windows.Media.Imaging.PngBitmapEncoder
$encoder.Frames.Add([Windows.Media.Imaging.BitmapFrame]::Create($fcb))
$encoder.Save($stream)
$stream.Dispose()
$rootpath="C:/kukisama.github.io/picupdate/"
cd $rootpath
cd ..
$lastfile=(ls $rootpath |sort LastWriteTime  -Descending)[0].name
$MARKDOWNpic=New-Object System.Collections.ArrayList
$MARKDOWNpic.add('![image](http://github.ny9s.com/picupdate/'+$lastfile+')')|out-null
$MARKDOWNpic.Add(' ')|out-null
$MARKDOWNpic|Set-Clipboard
Write-Host "Pot-friends, now available in MarkDown Copy the text address in the editor"
git add $rootpath$lastfile
git commit -m $lastfile
git push -u origin master|Out-Null -ErrorAction SilentlyContinue
#git  rm -r C:/kukisama.github.io/picupdate/

Spiritual Transition

Functional logic is almost finished, but all of a sudden I found such an article Shen Tie

When I read the post, this logic already exists in 2015...
Here's an original Lifeline, Set-Clipboard and Get-Clipboard
So it only takes two steps to save the file

$PNGfile=Get-Clipboard -Format Image
$PNGfile.Save($file)

So the modified logic is like this

$PNGfile=Get-Clipboard -Format Image
if ($PNGfile)
{
$rootpath="C:/kukisama.github.io/picupdate/"
$internetURL="http://github.ny9s.com/picupdate/"
$filename = ((Get-Date -f s) -replace '[-T:]', '')
$file = "$rootpath{0}.png" -f $filename
$PNGfile.Save($file)

cd $rootpath;cd ..
$MARKDOWNpic=New-Object System.Collections.ArrayList

#$MARKDOWNpic.add('![image]('+$interneturl+$filename+'.png'+')')
#The above address is the github page address, but in fact, it refreshes very slowly, so I take the time address of the file directly
$MARKDOWNpic.add('![image]('+'https://github.com/kukisama/kukisama.github.io/blob/master/picupdate/'+$filename+'.png'+'?raw=true)')
$MARKDOWNpic.Add(' ')
$MARKDOWNpic|Set-Clipboard
Write-Host "Pot-friends, now available in MarkDown Copy the text address in the editor"
git add $file 
git commit -m $filename 
git push  
}

antic

There's also a trick: for screen characters that are output to objects, you can first convert them to strings and then output them to the clipboard

dir | Out-String | Set-Clipboard 

Upload using FTP

The graph bed of github page is really unstable in China.The initial idea here is to use the best FTP to save your pictures and set up an FTP server yourself, assuming the name is xxx.ny9s.com
What you actually need to do for the corresponding web site, ny9s.com/pic, is pass the picture to FTP and generate the corresponding web-side string.Modify the script again.

Start with Ubuntu 16.04 Install ftp Server Go configure it

sudo apt-get install vsftpd
 Create user directory sudo mkdir picupdate
 Create user sudo useradd-d/var/www/html/picupdate-s/bin/bash uftp
sudo mkdir picupdate
sudo vi /etc/vsftpd.conf
 #Edit vsftpd.conf file

userlist_deny=NO
userlist_enable=YES
 #Users allowed to log on
userlist_file=/etc/allowed_users
seccomp_sandbox=NO
 #Default ftp download directory
local_root=/home/uftp/
local_enable=YES
 #Set up file upload
write_enable=YES
 #Use utf8
utf8_filesystem=YES
 Add users who are allowed to log on
sudo gedit /etc/allowed_users

Save after modifications, and then restart the service
sudo /etc/init.d/vsftpd start
sudo /etc/init.d/vsftpd stop
sudo /etc/init.d/vsftpd restart

 If the flowers are in passive mode,
Open xxx/vsftpd/vsftpd.conf and add at the end:

pasv_enable=YES //Turn on PASV mode
 pasv_min_port=40000 //min port number
 pasv_max_port=40000 //max port number
pasv_promiscuous=YES

Permissions under reconfiguration
sudo chown uftp:uftp /var/www/html/picupdate/

FTP Upload File Logic

# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]::Create("ftp://localhost/me.png")
$ftp = [System.Net.FtpWebRequest]$ftp
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential("anonymous","anonymous@localhost")
$ftp.UseBinary = $true
$ftp.UsePassive = $true
# read in the file to upload as a byte array
$content = [System.IO.File]::ReadAllBytes("C:\me.png")
$ftp.ContentLength = $content.Length
# get the request stream, and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content, 0, $content.Length)
# be sure to clean up after ourselves
$rs.Close()
$rs.Dispose()
sudo vi /etc/vsftpd.conf
sudo vi /etc/services
sudo /etc/init.d/vsftpd restart

After vsftpd starts, the default ftp port is 21. Now I want to change the ftp port to 801, so that the user's upload and download will not be affected.
1. Edit the/etc/vsftpd/vsftpd.conf file and add this line to the configuration file: listen_port=801
 2. Edit/etc/services file to include 
Change ftp 21/tcp to ftp 801/tcp 
Change ftp 21/udp to ftp 801/udp
 3. Execute/etc/init.d/vsftpd restart to restart the vsftpd service.After the boot is complete, you can use the netstat-ntpl | grep vsftpd command to see the system implementation
 Listening vsftpd has port 801
 4. Use lftp 192.168.0.1:801(192.168.0.1 is the address of the vsftpd server) so that you can access the ftp server.

Open Firewall
ufw enable
 Close Firewall
ufw disable

However, the above question, although it seems that the steps should be detailed, is that the configuration of my environment failed...

Posh SSH

Spend a lot of time on FTP and start looking for solutions.After testing, the easiest way is to install the Posh-SSH module to upload and download files using SSH.This module is github Can be downloaded to.

You can also install it directly using Install-Module-Name Posh-SSH-RequiredVersion 2.0.2, which I think has the following advantages:

  1. The server only needs to open the SSH port, and this port can work as well as mapping to other ports without using 22.
  2. No active and passive mode, no accounts, no ports or anything like FTP
  3. The file is not big as a whole, only more than 2M, and only 1.7M after deleting the help file, whether it is downloaded directly or made into an offline package.
    4. Big Brother's code is well encapsulated and only one command is needed to upload and download files.Writing on your own is almost the limit.

Code Examples

$cred=Get-Credential 
#Agree to KEY, download files remotely
Get-SCPFile -ComputerName "ny9s.com" -Port 12121 -Credential $cred  -RemoteFile "/home/kukisama/IOid.jpg" -LocalFile 'C:\img\ppp.jpg' -AcceptKey
#upload
 Set-SCPFile -ComputerName "ny9s.com" -Port 12121 -Credential $cred  -Remotepath "/home/kukisama" -LocalFile 'C:\img\ppp.jpg'

What modules can clean up


If installed online, the module will be located in
C:\Program Files\WindowsPowerShell\Modules\Posh-SSH If not, deleting it directly is equivalent to uninstalling.
The overall directory has 2.26MB and 500K help files. After testing, it found that deletion did not affect (en-US directory).

Password Encryption and Decryption Logic

In order to connect SSH silently, a password logic is used to place the required $cred encryption in a local folder, which is easier to use

#Step 1. Keep the password encrypted until c:\xxx.txt.
$mysecret="xxxxxx" #Put your password here
$mysecret|ConvertTo-SecureString -AsPlainText -Force |ConvertFrom-SecureString|Out-File C:\picupdate\pass.txt -Encoding utf8
#Step 2. Convert the ciphertext password to a format that the powershell can use
$securestring=(Get-Content C:\picupdate\pass.txt).ToString() | ConvertTo-SecureString
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($secureString)
$serverpass = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) 
$Password = ConvertTo-SecureString $serverpass -AsPlainText –Force
#Step 3. Use
$UserName = "admin"   #Define Administrator Account Name
$cred = New-Object System.Management.Automation.PSCredential($UserName,$Password) 

Overall code, PNG format

$PNGfile=Get-Clipboard -Format Image
if ($PNGfile)
{$start=Get-Date
$rootpath="C:/picupdate/"
$internetURL="http://ny9s.com/picupdate/"
$filename = ((Get-Date -f s) -replace '[-T:]', '')
$file = "$rootpath{0}.png" -f $filename
$PNGfile.Save($file)
cd $rootpath 
$MARKDOWNpic=New-Object System.Collections.ArrayList
$MARKDOWNpic.add('![image]('+$internetURL+$filename+'.png)')
$MARKDOWNpic.Add(' ')
$MARKDOWNpic|Set-Clipboard
Write-Host "Pot-friends, now available in MarkDown Copy the text address in the editor"

Import-Module D:\Posh-SSH\Posh-SSH.psd1 #Notice the module, I am not installing it here for use in the system
$securestring=(Get-Content C:\picupdate\pass.txt).ToString() | ConvertTo-SecureString
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($secureString)
$serverpass = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) 
$Password = ConvertTo-SecureString $serverpass -AsPlainText –Force
$UserName = "kukisama"   #Define Administrator Account Name
$cred = New-Object System.Management.Automation.PSCredential($UserName,$Password) 

#upload
Set-SCPFile -ComputerName "ny9s.com" -Port 62222 -Credential $cred  -Remotepath "/var/www/html/picupdate" -LocalFile $($rootpath+$filename+'.png')

$end=Get-Date
echo $('Time consumed'+($end-$start).TotalSeconds)
 }

Optimizable Items

Given how pictures take a few seconds to upload, it's logical to generate the strings MarkDown needs and upload them regularly, such as once in a minute or once in ten minutes.This will be a better experience.

Of course, after uploading, there should also be some flag bit detection, such as no upload after successful upload, record upload time, what it takes

Tags: ASP.NET ftp github vsftpd git

Posted on Thu, 07 Nov 2019 16:45:36 -0500 by titel