Help us understand the problem. What is going on with this article?

VS2017でOfficeToPDFをコンパイル&実行してみた

Visual Studio 2017 (15.9.4) Community版を利用して、OfficeToPDFをビルドしたので、その時のメモを残します。

別のPCのVS2017 (15.9.26)で試したところ、コンパイル時にエラーになったので、その対策を加筆しています。

環境

  • 【ビルド環境】Windows 10 Pro 1803 (64bit) / 2004 (64bit)
    • PowerShell 5.1
  • Visual Studio 2017 Community (15.9.4) / (15.9.26)
    • 【ワークロード】.Netデスクトップ開発
    • 【ワークロード】Office/Sharepoint開発
    • 【機能拡張】Github Extension for Visual Studio
  • 【実行環境】Windows7 32bit

GithubのREADME.mdにもありますが、Windows7では、Visual Studio 2010 Tools for Office Runtime2007 Microsoft Office Add-in: Microsoft Save as PDF or XPSを導入しておく必要があります。

Windows10で実行する場合には、Windows7で必要だったパッケージの導入は必要ないはずです。

概要

他の部署からCD-Rで保存用に資料をもらったところ、サブディレクトリ(sub directory)に様々なワード(.doc)、パワーポイント(.ppt)が配置されていました。

過去に、保存されていたppt95形式のファイルが開けない問題があったりしたので、現在はポリシーとしてPDFファイルにした上でM-DISCに保存するようにしています。

バッチ的にMicrosoft Officeで作成されたファイルをPDFに変換したかったので、いろいろ探したところCodePlex Archiveにofficetopdfを見つけて試してみようと思いました。

Cognidoxが作成し、Githubで現在は公開されているとのことなのですが、バイナルは配布されていない様子だったのでVisual Studio2017を使ってビルドしてみることにしました。

Visual Studio 2017 (VS2017) の導入

公式サイトからダウンロードしたインストーラーを起動し、VS2017を導入します。

VS2017の構成

インストール時に選択する構成は、事後でもメニューからVisual Studio Installerを起動することで行なえます。
image.png

.Netデスクトップ と Office開発用コンポーネントの選択

開発対象を選択する画面が表示されるので、.Netデスクトップ開発とOffice Developer Tools for Visual Studioをインストールするために、Office/Sharepoint開発を選択します。

image.png

image.png

Githubに対応した機能拡張のインストール

機能拡張はInstallerではなく、通常のVS2017のツールメニューから操作をします。

image.png

Githubからコードをダウンロードする方法はいろいろありますが、VS2017上でコードをGithubからcloneできるように拡張機能を導入します。

VS2017の拡張機能を探す時には、左側のペイン(pane)でオンラインを選択してから、検索ウィンドウでキーワードを入力します。

Github Extension for Visual Studioはダウンロード数が上位にあるので、すぐに見つけられるはずです。

image.png

インストールした後はVS2017のウィンドウを全て閉じて終了するとインストールが始まります。

image.png

コードのダウンロード(Clone)

Githubからソースコードをcloneし、VS2017で認識できるようにしていきます。

VS2017を起動し、ファイルメニューからソース管理から開くを選択し、チームエクスプローラーを起動します。

image.png

チームエクスプローラーが起動するので、コンセントのアイコンを選択します。

image.png

画面下のローカルGitリポジトリの複製メニューからGithubのURLと適当な空のディレクトリを選択します。

image.png

登録されたOfficeToPDFをダブルクリックするか、コンセントアイコンの隣りにあるホームアイコンをクリックし、チームエクスプローラーのホームを表示します。

image.png

画面下に認識されたソリューションが表示されるため、OfficeToPDF.slnをクリックします。

image.png

ビルド

ソリューションを開いた後は、ビルドメニューから、"OfficeToPDFのビルド"を選択し、実行ファイルを生成します。

ビルド時のエラー

VS2017 (15.9.26)でビルドすると次のようなエラーメッセージが出力されました。

errorメッセージ
重大度レベル  コード   説明  プロジェクト  ファイル    行 抑制状態
警告      タイプ ライブラリ "MSHTML" のラッパー アセンブリが見つかりません。次のことを確認してください。(1) COM コンポーネントが正しく登録されている。(2) ターゲット プラットフォームのビットが COM コンポーネントと同じである。たとえば、COM コンポーネントが 32 ビットの場合、64 ビットのターゲット プラットフォームは使用できません。    OfficeToPDF         

対応方法は、ソリューションエクスプローラーの参照を確認すると、MSHTMLに警告マークが付いているのが分かります。

image.png

VS2019では問題がなかったので調べてみると、当初は一旦削除し、Microsoft.mshtml.dllを参照に追加すれば良いと思っていたのですが、regasmを再度実行するのが適切な対応策だと考え直しました。

詳細は下記のブログに記載されていて、他にも同様の記述があるようです。

管理者権限で起動したPowerShellやコマンドプロンプト内部で、Microsoft.mshtml.dllのあるディレクトリに移動し、regasmを実行します。

以下は失敗例です。

一般ユーザーでの実行結果
PS C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a> regasm .\Microsoft.mshtml.dll
Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.9136
Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.

RegAsm : error RA0000 : An error occurred while writing the registration information to the registry. You must have administrative credentials to perform this task.  Contact your system administrator for assistance

以下は成功例です。

管理者権限での実行結果
C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a>regasm Microsoft.mshtml.dll
Microsoft (R) .NET Framework Assembly Registration Utility 2.0.50727.9136
Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.

Types registered successfully

VS2017を再起動すれば、MSHTMLについてエラーはなくなります。

32bitオブジェクトの生成

業務用のPCにはまだWindows7(32bit)のものがあるので、32bitの実行ファイルも生成します。
ターゲットをReleaseに、リリースにx86を選択した上で、ビルドメニューからOfficeToPDFのビルドを選択します。

image.png

出力ペイン(pane)をみると
生成されたOfficeToPDF.exeファイルをコピーするなどし、ターゲットのマシンで利用します。

OfficeToPDFの実行例

単純な例としてはトップディレクトリにOfficeToPDF.exeファイルをコピーしたとして、次のように配下のフォルダに含まれる.docxファイルをPDFファイルに変換します。

PS \> ls -R *.docx | ForEach-Object { .\OfficeToPDF.exe $_ }

実用的な実行例

既にPDFファイルが存在している場合には処理を飛ばすような処理を加えるには次のような方法が考えられます。

convtest1.ps1
ls -R *.docx | ForEach-Object { 
  $pdfpath = ($_.FullName) -Replace ($_.Extension + '$'), '.pdf' 
  if (Test-Path $pdfpath -PathType Leaf) {
    echo ($pdfpath + " skipping...")
  } else {
    echo ($pdfpath+ " converting...")
    .\OfficeToPDF.exe $_
  }
}

複数の拡張子に対応する

前述のconvtest1.ps1では、拡張子がどんなものでも対応できるようにしているので、次のようにカンマで区切って複数のパターンを記述することができます。

ls -R "*.docx","*.pptx" | ForEach-Object {

PowerShellスクリプトの開発・デバッグについて

UNIXのShellスクリプトでは変数の実体は常に文字列ですが、PowerShellスクリプトでは、実体は常にオブジェクトなので変数に格納されているオブジェクトの型に注目します。

型を調べる方法としては、GetType()があるので、今回の例では次のようなスクリプトの断片を実行していました。

PS E:\> ls -R *.docx | ForEach-Object { $_.GetType() ; $_.FullName.GetType() }
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     FileInfo                                 System.IO.FileSystemInfo
True     True     String                                   System.Object

Windows7標準のPowerShell2.0では ls -R -include *.docxのように明示的に-includeを追加する必要がありました。

これでlsの実行結果から渡されるオブジェクトがSystem.IO.FileSystemInfoクラスのものだと分かります。
あとはAPIリファレンスでメソッドを調べたり、文字列に落し込んで基本的な操作で解決するようにしました。

OfficeToPDF実行時の注意点

  1. WordやExcelといったOfficeアプリを全て閉じて利用しないと、処理が止まったりPDFの生成に失敗する場合があります。
  2. NAS等のネットワークドライブを対象とする場合には、.ps1ファイルを直接実行するためには、ExecutionPolicyをUnristricted (もしくはBypass)に変更する必要があります。

以上

YasuhiroABE
元エンジニアの大学教員@会津大学。ここに投稿している内容は、個人的な動機・責任で編集しているもので、勤務先・業務とは関係ありません。なお、LGTM(評価)・ストックされた記事は、その都度、可能な範囲で見直すようにしています。
https://www.yadiary.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away