Использование SetImage внутри threadjob - PullRequest
2 голосов
/ 11 февраля 2020

У меня есть функция, которая вставляет изображения в PPT и включает в себя код:

$file = get-item($pic);
$img = [System.Drawing.Image]::Fromfile($file);



[System.Windows.Forms.Clipboard]::SetImage($img);


$slide = $pp1.Slides.Item($targetslide)

Start-Sleep -Seconds 5

$shape = $Slide.Shapes.PasteSpecial($ppPasteJPG,$false,$null,$null,$null,$null)

Однако я создал функцию, которая использует эту функцию, и поместил ее в скрипт действия threadjob. Теперь, когда он активирован, он выдает ошибку:

Exception calling "SetImage" with "1" argument(s): "Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."
At C:\...\PicInsertPPT.ps1:17 char:1
+ [System.Windows.Forms.Clipboard]::SetImage($img);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ThreadStateException

Чем я могу заменить эту строку тем, что она будет работать как одна задача в потоке с несколькими параллельными задачами?

Я думаю о пытаюсь применить:

CommandBars.ExecuteMso("PictureInsertFromFile")

Но я не совсем уверен, как контролировать, какое изображение вставляется таким образом.

Редактировать: мой код задания потока:

Function ThreadMaster{



param ($folder)




$global:folder = $folder



  # Use the system's temp folder in this example.
  $global:dir = $folder

  # Define the tasks as an array of custom objects that specify the dir.
  # and file name pattern to monitor as well as the action script block to 
  # handle the events.
  $tasks = # array of custom objects to describe the 
    [pscustomobject] @{
      DirToMonitor = $dir
      FileNamePattern = '*.csv'
      Action = {
        $path = $EventArgs.FullPath
        $name = $EventArgs.Name
        $changeType = $EventArgs.ChangeType
        $timeStamp = $EventArgs.TimeGenerated




         Write-Host -NoNewLine "`nINFO: Event 1 raised:`n$($EventArgs | Format-List | Out-String)"



        Import-Module C:\...Report1V1.ps1


       $Actionpath = Split-Path $Path



        write-host $Actionpath " Ready for Report1"



       Report1 $Actionpath

       write-host $Actionpath "Report1 Generated"



        "`nEvent 1 output: " + $EventArgs.Fullpath

}
      }
    },
    [pscustomobject] @{
      DirToMonitor = $dir
      FileNamePattern = '*4.4_10X*'
      Action = {
        $path = $Event.SourceEventArgs.FullPath
        $name = $Event.SourceEventArgs.Name
        $changeType = $Event.SourceEventArgs.ChangeType
        $timeStamp = $Event.TimeGenerated

        Write-Host -NoNewLine "`nINFO: Event 2 raised:`n$($EventArgs | Format-List | Out-String)"


        Import-Module C:\...\Report2V1.ps1





      $Actionpath = Split-Path $Path




      $Actionpath = Split-Path $Actionpath








      write-host $Actionpath " Ready for Report2"



      Report2 $Actionpath


      write-host "Report2 Generated" 



        "`nEvent 2 output: " + $EventArgs.Fullpath


      }  
    } 
}
  # Start a separate thread job for each action task.
  $threadJobs = $tasks | ForEach-Object {

    Start-ThreadJob -ArgumentList $_ {

      param([pscustomobject] $task)

      # Create and initialize a thread-specific watcher.
      # Note: To keep system load low, it's generally better to use a *shared* 
      #       watcher, if feasible. You can define it in the caller's scope
      #       and access here via $using:watcher
      $watcher = [System.IO.FileSystemWatcher] [ordered] @{
        Path   = $task.DirToMonitor
        Filter = $task.FileNamePattern
        IncludeSubdirectories = $true
        EnableRaisingEvents = $true # start watching.
        InternalBufferSize = 65536
      }

      # Subscribe to the watcher's Created events, which returns an event job.
      # This indefinitely running job receives the output from the -Action script
      # block whenever the latter is called after an event fires.
      $eventJob = Register-ObjectEvent -ea stop $watcher Created -Action $task.Action

      Write-Host "`nINFO: Watching $($task.DirToMonitor) for creation of $($task.FileNamePattern) files..."

      # Indefinitely wait for output from the action blocks and relay it.
      try {
        while ($true) {
          Receive-Job $eventJob
          Start-Sleep -Milliseconds 500  # sleep a little
        }
      }
      finally { 
         # !! This doesn't print, presumably because this is killed by the
         # !! *caller* being killed, which then doesn't relay the output anymore.
        Write-Host "Cleaning up thread for task $($task.FileNamePattern)..."
        # Dispose of the watcher.
        $watcher.Dispose()
        # Remove the event job (and with it the event subscription).
        $eventJob | Remove-Job -Force 
      }

    }

  }  


  Write-Host "Starting tasks...`nUse Ctrl-C to stop."

  # Indefinitely wait for and display output from the thread jobs.
  # Use Ctrl+C to stop.
  $dtStart = [datetime]::UtcNow
  while ($true) {

    # Receive thread job output, if any.
    $threadJobs | Receive-Job

    # Sleep a little.
    Write-Host . -NoNewline
    Start-Sleep -Milliseconds 500


  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...