У меня есть функция, которая вставляет изображения в 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
}
}