peterleb
Goto Top

Von VBS nach Powershell (Verwendung der InternetExplorer.Application)

Hallo Mädels und Jungs,

vor einiger Zeit hatte ich mir mal (auch mit Eurer Hilfe) ein Script zusammengebastelt,
welches mir den Namen des aktuellen Wallpapers und eine verkleinerte Vorschau mithilfe der InternetExplorer.Application anzeigt, sowie fragt, ob ich das Bild bearbeiten will oder nicht.
Das sieht so aus:

Option Explicit
 'On Error Resume Next  

 const HKEY_CURRENT_USER = &H80000001 
 Dim objWshShell, objShellApp, oReg, strKeyPath, strValueName, strValue, objExplorer, Text, PictureName', strComputer  
 Dim nWidth, nHeight
 Dim iValues()
 Dim i, result
 Dim objFSO, objFile
 Dim objImage
  
 'strComputer = "."  
 Set objWshShell = CreateObject("WScript.Shell")  
 Set objShellApp = CreateObject("Shell.Application")  
 Set objExplorer = CreateObject("InternetExplorer.Application")  
  
 Function ShowImage(Source)
	Set objFSO = CreateObject("Scripting.FileSystemObject")  
	Set objFile = objFSO.GetFile(Source)
	
	Set objImage = CreateObject("WIA.ImageFile")  
	objImage.LoadFile Source
	nWidth = objImage.Width
	nHeight = objImage.Height
	Set objImage = Nothing
    
	If Len(objFSO.GetFileName(objFile)) > 30 Then
		PictureName = Left(objFSO.GetFileName(objFile), 30) & "..."  
		Else
		PictureName = objFSO.GetFileName(objFile)
	End If
	With objExplorer
    .Navigate "about:blank"  
    .Visible = 1
    .Toolbar=False
    .Statusbar=False
    .Top=200
    .Left=150
    .Height = nHeight / 1.92
    .Width = nWidth / 1.92
    .Document.Title = PictureName & "    Abmessungen: " & nWidth & " x " &  nHeight  
    .Document.Body.InnerHTML = "<img src='" & Source & "' height=100% width=100%>"  
	End With
 End Function
  
strKeyPath = "Control Panel\Desktop"  
'Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")  
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")  
strValueName = "WallPaper"  
oReg.GetStringValue HKEY_CURRENT_USER, strKeyPath, strValueName, strValue

If inStr(1, strValue, "TranscodedWallpaper", 0) > 0 Then  
	strValueName = "TranscodedImageCache"  
	oReg.GetBinaryValue HKEY_CURRENT_USER, strKeyPath, strValueName, iValues
	strValue = ""  
	For i = 24 to uBound(iValues)
		If iValues(i) > 31 Then  'The numbers from 0 to 31 represents nonprintable ASCII codes  
		strValue = strValue & chr(iValues(i))
		End If
	Next
End If
Text = "Dateiname  : " & strValue  

ShowImage strValue

result = Msgbox(Text, vbYesNo, "Dateiname im Clipboard - Bild Bearbeiten?")  
If result = vbYes Then
	objShellApp.ShellExecute strValue, "", "", "open", 1  
End If

objWshShell.Run "cmd.exe /c echo " & strValue & " | clip",0,False  
objExplorer.Quit

Nun ist InternetExplorer obsolet und Edge geht nicht mit VBS/VBA.

Zur Umsetzung der Bildanzeige fand ich eine feine Geschichte mit Powershell hier:
PictureView

param(
    [string]$PicturePath
)
# Usage: .\scriptname.ps1 c:\users\limi\pictures\northkoreaatnight.jpg
$PicturePath = "D:\Bilder\DesktopBackground\18_1080.jpg"  

if (!$PicturePath) {
    "`nAchtung, kein Bild übergeben!`n"  
    "Verwendung:`n$PSCommandPath [-PicturePath] voller_Pfad_zur_Bilddatei`n"  
    break
}

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function display([System.Drawing.Image]$img) {
    $w_form = 400 # form width
    $h_form = 250 # form height

    $b = [int]$img.Size.Width
    $h = [int]$img.Size.Height
    $b_thumb = $b
    $h_thumb = $h
    # portrait picture higher than 500px or landscape picture wider than 700px?
    # Neu: einfach halbe Bildgröße
    if ( ($b -gt $h) -and ($b -gt 700) ) {
        $b_thumb = $b / 2 #700
        $h_thumb = $h / 2 #[int](700 * $h / $b)
        $imgthumb = $img.GetThumbnailImage($b_thumb, $h_thumb, $null, 0) # create bitmap with 700px width
    }
    elseif ( ($b -le $h) -and ($h -gt 500) ) {
        $b_thumb =$b / 2 # [int](500 * $b / $h)
        $h_thumb =$h / 2 # 500
        $imgthumb = $img.GetThumbnailImage($b_thumb, $h_thumb, $null, 0) # create bitmap with 500px heigth
    }
    else {
        $imgthumb=$img
    }

    $form = New-Object Windows.Forms.Form

    $form.Text = $PicturePath #"Picture"  
    $form.Size = New-Object System.Drawing.Size($w_form,$h_form) # minimal size
    $form.StartPosition = "CenterScreen"  
    $form.AutoSize = $True
    $form.AutoSizeMode = "GrowOnly" # or "GrowAndShrink"  
    $form.Topmost = $True

    $font_normal = New-Object System.Drawing.Font("Tahoma",12,[Drawing.FontStyle]::Regular)  
    $font_bold = New-Object System.Drawing.Font("Tahoma",12,[Drawing.FontStyle]::Regular) #Bold)  

    $PictureBox = New-Object Windows.Forms.PictureBox
    $PictureBox.Location = New-Object System.Drawing.Point(5,35)
    $PictureBox.Size = New-Object System.Drawing.Size($b_thumb, $h_thumb)
    $PictureBox.Image = $imgthumb;
    $form.Controls.Add($PictureBox)

    $LabelDescription = New-Object Windows.Forms.Label
    $LabelDescription.Location = New-Object System.Drawing.Point(5,5)
    #$LabelDescription.Size = New-Object System.Drawing.Size(375,25)
    $LabelDescription.Font = $font_bold;
    $LabelDescription.Text = "Originalgröße: $b x $h, Displaygröße: $b_thumb x $h_thumb"  
    $LabelDescription.AutoSize = $True
    $form.Controls.Add($LabelDescription)

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Size = New-Object System.Drawing.Size(75,45)
    # OKButton centered under the picture
    $OKButton.Location = New-Object System.Drawing.Point( (($form.Size.Width - $OKButton.Size.Width) / 2),(50+$h_thumb) )
    $OKButton.Text = "OK"  
    $OKButton.Font = $font_bold
    $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $form.Controls.Add($OKButton)
    $form.AcceptButton = $OKButton

    return $form.ShowDialog()
}

# read image file to byte array
try {
    $img = [System.IO.File]::ReadAllBytes("$PicturePath")  
}
catch {
    "Error reading file. Please give me the full path to the image file.`nExiting ..."  
    break
}

$ms = New-Object System.IO.MemoryStream # i need some memory
$ms.Write($img, 0, $img.Length) # image bytes to memory stream

# convert image to Windows System Bitmap
try {
    $img = [System.Drawing.Image]::FromStream($ms,$true,$true)
}
catch {
    "Error loading image.`nExiting ..."  
    $ms.Dispose() # free memory
    break
}
$ms.Dispose() # free memory

display($img)

Habe schon ein bisschen damit herumgespielt und zum Testen eine Konstante als Parameter benutzt.
Das funktionier auch gut.
Nun möchte ich das Auslesen des Wallpapers und Weiterverarbeiten auch mit Powershell ausführen,
bin aber damit noch zu wenig bewandert.

Gibt es jemanden von Euch, der Lust und Zeit hat, mir bei der Umsetzung zu helfen?

Viele liebe Grüße
Peter

Content-ID: 1937326515

Url: https://administrator.de/contentid/1937326515

Ausgedruckt am: 19.11.2024 um 04:11 Uhr

1915348599
1915348599 17.02.2022 um 17:52:12 Uhr
Goto Top
Nun möchte ich das Auslesen des Wallpapers und Weiterverarbeiten auch mit Powershell ausführen,
$wallpaper = Get-ItemPropertyValue "HKCU:\Control Panel\Desktop" -Name Wallpaper  
PeterleB
PeterleB 17.02.2022 aktualisiert um 22:43:31 Uhr
Goto Top
Hallo,
so einfach ist es nicht, denke ich.
Angezeigt wird das "C:\Users\XXXXX\AppData\Roaming\Microsoft\Windows\Themes\TranscodedWallpaper".
der tatsächliche Name muß aus dem "TranscodedImageCache" herausgefiltert werden.

Oder macht das "Get-ItemPropertyValue"?

Gruß
Peter
PeterleB
PeterleB 18.02.2022 um 07:06:39 Uhr
Goto Top
Hallo,
hab's getestet.

Get-ItemPropertyValue liefert genau diesen Wert: "C:\Users\XXXXX\AppData\Roaming\Microsoft\Windows\Themes\TranscodedWallpaper"

Gruß
Peter
PeterleB
PeterleB 18.02.2022 um 07:45:17 Uhr
Goto Top
Hi,
was gefunden:

$TIC=(Get-ItemProperty 'HKCU:\Control Panel\Desktop' TranscodedImageCache -ErrorAction Stop).TranscodedImageCache  

[System.Text.Encoding]::Unicode.GetString($TIC) -replace '(.+)([A-Z]:[0-9a-zA-Z\\])+','$2'  

Funktioniert!
Gruß
Peter
1915348599
1915348599 18.02.2022 aktualisiert um 07:50:37 Uhr
Goto Top
PeterleB
PeterleB 18.02.2022 um 10:58:30 Uhr
Goto Top
Hi,
mit "Textkultur ohne Hirn" hat das wohl wenig zu tun. Das ist doch für mich auf jeden Fall ein Lernvorgang und kein bloßes Abschreiben.
Dann bräuchten wir auch dieses Forum nicht, oder?

Gruß
Peter
PeterleB
PeterleB 18.02.2022 aktualisiert um 20:00:32 Uhr
Goto Top
Hallo,
mein Projekt ist fast fertig:

# Initialize counters
  $Path_Start_Delta=24  #The offset at which the image path starts
  $Path_End_Delta=-1    #The offset at which the image path ends... is still unknown

# First, access Windows Registry and get the property containing wallpaper path
  try {
    $TranscodedImageCache=(Get-ItemProperty 'HKCU:\Control Panel\Desktop' TranscodedImageCache -ErrorAction Stop).TranscodedImageCache  
  }
  catch [System.Management.Automation.ItemNotFoundException],[System.Management.Automation.PSArgumentException]  {
    $result=[System.Windows.Forms.MessageBox]::Show("Windows scheint zu diesem Zeitpunkt keine Aufzeichnungen über ein Hintergrundbild zu haben.`r`r"+$Error.Exception.Message,"Script","OK","Error");  
    break;
  }
# Decode the property containing the path
  # First, let's assume the path ends at the last byte of $TranscodedImageCache  
  $Path_End_Delta=$TranscodedImageCache.length-1
  
  # A sequence of 0x00 0x00 marks the end of string. Find it.
  # The array that we are searching contains a UTF-16 string. Each character is a little-endian WORD,
  # so we can search the array's even indexes only.  
  for ($i = $Path_Start_Delta; $i -lt ($TranscodedImageCache.length); $i += 2) {
    if ($TranscodedImageCache[($i+2)..($i+3)] -eq 0) {
      $Path_End_Delta=$i + 1;
      Break;
    }
  }

  # Convert the bytes holding the wallpaper path to a Unicode string
  $UnicodeObject=New-Object System.Text.UnicodeEncoding
  $WallpaperSource=$UnicodeObject.GetString($TranscodedImageCache[$Path_Start_Delta..$Path_End_Delta]);

$PicturePath = $WallpaperSource
Set-Clipboard $PicturePath

if (!$PicturePath) {
    "`nAchtung, kein Bild übergeben!`n"  
    "Verwendung:`n$PSCommandPath [-PicturePath] voller_Pfad_zur_Bilddatei`n"  
    break
}

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function display([System.Drawing.Image]$img) {
    $w_form = 400 # form width
    $h_form = 250 # form height

    $b = [int]$img.Size.Width
    $h = [int]$img.Size.Height
    # Neu: einfach halbe Bildgröße
    $b_thumb = [int] ($b / 1.9)
    $h_thumb = [int] ($h / 1.9)
    $imgthumb = $img.GetThumbnailImage($b_thumb, $h_thumb, $null, 0) # create bitmap with half px width
    

    $form = New-Object Windows.Forms.Form

    $form.Text = $PicturePath #"Picture"  
    $form.Size = New-Object System.Drawing.Size($w_form,$h_form) # minimal size
    $form.StartPosition = "CenterScreen"  
    $form.AutoSize = $True
    $form.AutoSizeMode = "GrowOnly" # or "GrowAndShrink"  
    $form.Topmost = $True

    $font_normal = New-Object System.Drawing.Font("Tahoma",12,[Drawing.FontStyle]::Regular)  
    $font_bold = New-Object System.Drawing.Font("Tahoma",12,[Drawing.FontStyle]::Bold)  

    $PictureBox = New-Object Windows.Forms.PictureBox
    $PictureBox.Location = New-Object System.Drawing.Point(5,35)
    $PictureBox.Size = New-Object System.Drawing.Size($b_thumb, $h_thumb)
    $PictureBox.Image = $imgthumb;
    $form.Controls.Add($PictureBox)

    $LabelDescription = New-Object Windows.Forms.Label
    $LabelDescription.Location = New-Object System.Drawing.Point(5,5)
    $LabelDescription.Font = $font_normal;
    $LabelDescription.Text = "Bildname: " + [System.IO.Path]::GetFileNameWithoutExtension($PicturePath) + "   Originalgröße: $b x $h, Displaygröße: $b_thumb x $h_thumb"  
    $LabelDescription.AutoSize = $True
    $form.Controls.Add($LabelDescription)

    $LabelQuestion = New-Object Windows.Forms.Label
    $LabelQuestion.Location = New-Object System.Drawing.Point(5,(50+$h_thumb))
    $LabelQuestion.Font = $font_normal;
    $LabelQuestion.Text = "Pfad in der Zwischenablage. Bild mit ... bearbeiten?"  
    $LabelQuestion.AutoSize = $True
    $form.Controls.Add($LabelQuestion)

    $NoButton = New-Object System.Windows.Forms.Button
    $NoButton.Size = New-Object System.Drawing.Size(60,40)
    $NoButton.Location = New-Object System.Drawing.Point( ($form.Size.Width - 120),(40+$h_thumb) )
    $NoButton.Text = "Nein"  
    $NoButton.Font = $font_bold
    $NoButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $form.Controls.Add($NoButton)
    $form.AcceptButton = $NoButton

    $YesButton = New-Object System.Windows.Forms.Button
    $YesButton.Size = New-Object System.Drawing.Size(60,40)
    $YesButton.Location = New-Object System.Drawing.Point( ($form.Size.Width - 200),(40+$h_thumb) )
    $YesButton.Text = "Ja"  
    $YesButton.Font = $font_bold
    $YesButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $YesButton.Add_Click({Start-Process -FilePath $PicturePath})
    $form.Controls.Add($YesButton)
    $form.AcceptButton = $YesButton

    return $form.ShowDialog()
}

# read image file to byte array
try {
    $img = [System.IO.File]::ReadAllBytes("$PicturePath")  
}
catch {
    "Fehler beim Lesen der Datei. Bitte vollständigen Pfad angeben.`nBeenden ..."  
    break
}

$ms = New-Object System.IO.MemoryStream # i need some memory
$ms.Write($img, 0, $img.Length) # image bytes to memory stream

# convert image to Windows System Bitmap
try {
    $img = [System.Drawing.Image]::FromStream($ms,$true,$true)
}
catch {
    "Fehler beim Laden des Bildes.`nBeenden ..."  
    $ms.Dispose() # free memory
    break
}
$ms.Dispose() # free memory

display($img)

Wüßte noch gern, wie ich die Default-Verknüpfung (Standard-App) für JPG aus der Registry lese.

Schöne zeit allen.
Peter
PeterleB
Lösung PeterleB 22.02.2022 aktualisiert um 14:00:40 Uhr
Goto Top
Hallo,

das Script ist jetzt fertig, muss es nochmal bei anderen Bildschirmgrößen testen.
Die Standard-App kann ich so auslesen:

function GetFTA ($Extension) {
    $assocFile = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice"-ErrorAction SilentlyContinue).ProgId  
    New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT  | Out-Null
    $appLink = (Get-ItemProperty "HKCR:\$assocFile\shell\command"-ErrorAction SilentlyContinue).'(default)'  
    Remove-PSDrive -Name HKCR
    $appLink = $appLink.Substring(0,$appLink.Length-6)
    $appLink = $appLink.TrimStart("""")  
    $prodDescr = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($appLink).FileDescription
    Return $prodDescr
}

Und hier nochmal das ganze ps1-File:
DesktopPictureName.ps1

Gruß
Peter