0

I want to run a background job in my PowerShell-Script to read all file icons from a specific folder into a [System.Windows.Forms.ImageList].

$JobScript = {
    param([String] $Path)
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    
    $Files = [System.IO.DirectoryInfo]::new($Path).GetFiles()
    [System.Windows.Forms.ImageList] $ImgList = [System.Windows.Forms.ImageList]::new()
    $Files.ForEach({
        $Extension = [System.IO.FileInfo]::new($_.FullName).Extension
        if ($Extension -notin $ImgList.Images.Keys)
        {
            $ImgList.Images.Add($Extension, [System.Drawing.Icon]::ExtractAssociatedIcon($_.FullName))
        }
        
    })
    $ImgList
}

$Job = Start-Job -ScriptBlock $JobScript -ArgumentList "C:\Windows"
#Do other stuff
Wait-Job $Job
Receive-Job $Job

The code generates plenty of errors, stating that neither [System.Drawing.Icon] nor [System.Windows.Forms.ImageList] can be found. When I run the code without a job it works just fine. Strangely the System.IO-namespace is working alright.

I guess I need to use add-type inside the script block, but how do I add these system types with it?

EDIT: I updated the code with the help of Mathias' comment.

GuidoT
  • 280
  • 1
  • 12
  • 2
    `Add-Type -AssemblyName System.Windows.Forms` – Mathias R. Jessen Apr 22 '21 at 10:17
  • Thanks alot! But it throws a 'The assembly "System.Drawing.Icon" could not be found.' error. System.Windows.Forms seems to work tho. Edit: I made a mistake when adding the type, it works now. But it throws alot of exceptions now, saying: ExtractAssociatedIcon - FileNotFoundException But the files do exist actually. – GuidoT Apr 22 '21 at 10:31
  • 1
    You need the containing assembly name, not the name of a specific type: `Add-Type -AssemblyName System.Drawing` – Mathias R. Jessen Apr 22 '21 at 10:32
  • It works now. :-) I also found the bug regarding the FileNotFoundExceptions... I had to get the FullName-property from the Files-iterator. – GuidoT Apr 22 '21 at 10:43
  • I noticed this solution does not work e.g. if you try to pass a System.Drawing.Icon to a job like $JobScript = {param([System.Drawing.Icon] $Ico); #...} since the add-type was not executed at that moment... How could you solve this case please? I know I can just use System.Object as a workaround but I would like to know... – GuidoT Apr 22 '21 at 13:13
  • Nevermind. Passing any kind of object to Start-Job will only pass a "crippled" copy. The solution can be found here and that's how I had to do it for my actual project in the end: https://stackoverflow.com/questions/15382728/passing-native-object-to-background-jobs – GuidoT Apr 22 '21 at 15:18

0 Answers0