1

テーブルを開いて Excel から Word にコピーするスクリプトを書いていますが、実行ごとに結果が異なります。最初はうまく機能しますが、数回実行すると、迷惑な赤いテキストが表示され始めます (特に、「呼び出しは呼び出し先によって拒否されました」と、$wordObject.Selection.TypeParagraph のような選択オブジェクトのメソッドは $wordObject.Selection が null 値になるため実行できません)。表現。

それらを閉じた後に ReleaseComObject を試みましたが、それでも問題が発生します

これは、同じセクションで 2 つの ComObject を使用しているからですか? 私のスクリプト構造は次のようなものです:

$Excel = New-Object -ComObject excel.application 
$Excel.visible = $false

$Workbook = $excel.Workbooks.open($pathEx)
$range = $workbook.activesheet.usedrange
$cop = $range.Copy()

$wd = new-object -comObject Word.application
$wd.visible = $true
$doc = $wd.documents.open($pathWd)
$wdSelection = $wd.Selection
$a = $wdSelection.Endkey(6,0)
$wdSelection.typeparagraph()
$wd.Selection.paste()

閉じて終了します。

$workbook.close($false)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
Remove-Variable workbook, excel
$doc.saveAs()
$wd.Quit()

ここにエラーがあります ここ に画像の説明を入力してください

何か案が?

*更新: 私のラップトップではなく、オフィスの PC ではスクリプトがエラーなしで実行されるのは奇妙です =.=

4

1 に答える 1

0

エラー メッセージ「呼び出しは呼び出し先によって拒否されました」はエラー コードに対応しますRPC_E_SERVERCALL_RETRYLATER 0x8001010A。コードの名前には、解決策の手がかりが既に含まれています。COM サーバー (つまり、Office アプリケーション) がビジー状態のため、現時点では呼び出しに応答できませんが、後で再試行できます。

再試行は、 「方法: 'Application is Busy' エラーと 'Call was Rejected By Callee' エラーを修正する」IOleMessageFilterで説明されているように実装することで処理できます。

ただし、PowerShell スクリプト内にいるため、このインターフェイスの実装は簡単ではありません。それにもかかわらず、それは可能です(@MarkRuckerのすばらしい答えに感謝します):

param([String]$pathEx, [String]$pathWd)

$source = @" 

namespace EnvDteUtils
{ 
    using System; 
    using System.Runtime.InteropServices; 

    public class MessageFilter : IOleMessageFilter 
    { 
        // Class containing the IOleMessageFilter 
        // thread error-handling functions. 

        // Start the filter. 
        public static void Register() 
        { 
            IOleMessageFilter newFilter = new MessageFilter();  
            IOleMessageFilter oldFilter = null;  
            CoRegisterMessageFilter(newFilter, out oldFilter); 
        } 

        // Done with the filter, close it. 
        public static void Revoke() 
        { 
            IOleMessageFilter oldFilter = null;  
            CoRegisterMessageFilter(null, out oldFilter); 
        } 

        // 
        // IOleMessageFilter functions. 
        // Handle incoming thread requests. 
        int IOleMessageFilter.HandleInComingCall(int dwCallType,  
          System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr  
          lpInterfaceInfo)  
        { 
            //Return the flag SERVERCALL_ISHANDLED. 
            return 0; 
        } 

        // Thread call was rejected, so try again. 
        int IOleMessageFilter.RetryRejectedCall(System.IntPtr  
          hTaskCallee, int dwTickCount, int dwRejectType) 
        { 
            if (dwRejectType == 2) 
            // flag = SERVERCALL_RETRYLATER. 
            { 
                // Retry the thread call immediately if return >=0 &  
                // <100. 
                return 99; 
            } 
            // Too busy; cancel call. 
            return -1; 
        } 

        int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,  
          int dwTickCount, int dwPendingType) 
        { 
            //Return the flag PENDINGMSG_WAITDEFPROCESS. 
            return 2;  
        } 

        // Implement the IOleMessageFilter interface. 
        [DllImport("Ole32.dll")] 
        private static extern int  
          CoRegisterMessageFilter(IOleMessageFilter newFilter, out  
          IOleMessageFilter oldFilter); 
    } 

    [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),  
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
    interface IOleMessageFilter  
    { 
        [PreserveSig] 
        int HandleInComingCall(  
            int dwCallType,  
            IntPtr hTaskCaller,  
            int dwTickCount,  
            IntPtr lpInterfaceInfo); 

        [PreserveSig] 
        int RetryRejectedCall(  
            IntPtr hTaskCallee,  
            int dwTickCount, 
            int dwRejectType); 

        [PreserveSig] 
        int MessagePending(  
            IntPtr hTaskCallee,  
            int dwTickCount, 
            int dwPendingType); 
    } 
} 
"@ 

Add-Type -TypeDefinition $source      

[EnvDTEUtils.MessageFilter]::Register()

$Excel = New-Object -ComObject excel.application 
$Excel.visible = $false

$Workbook = $excel.Workbooks.open($pathEx)
$range = $workbook.activesheet.usedrange
$cop = $range.Copy()

$wd = new-object -comObject Word.application
$wd.visible = $true
$doc = $wd.documents.open($pathWd)
$wdSelection = $wd.Selection
$a = $wdSelection.Endkey(6,0)
$wdSelection.typeparagraph()
$wd.Selection.paste()
于 2015-12-08T08:37:08.497 に答える