7

C#で記述されたドキュメントレベルのワークブック/テンプレートを作成し、VSTOインストーラーを使用してコードをデプロイしています。プロジェクトをインストールした後、スプレッドシートの全機能を使用できますが、インストールしたシートをインストールフォルダー外の別のパスに保存またはコピーすると、次のエラーが発生します。

ええとああ!

次の完全な詳細で:

Name: 
From: file:///C:/Users/Kronos/Desktop/ExcelTemplate1.vsto

************** Exception Text **************
System.Deployment.Application.DeploymentDownloadException: Downloading file:///C:/Users/Kronos/Desktop/ExcelTemplate1.vsto did not succeed. ---> System.Net.WebException: Could not find file 'C:\Users\Kronos\Desktop\ExcelTemplate1.vsto'. ---> System.Net.WebException: Could not find file 'C:\Users\Kronos\Desktop\ExcelTemplate1.vsto'. ---> System.IO.FileNotFoundException: Could not find file 'C:\Users\Kronos\Desktop\ExcelTemplate1.vsto'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync)
   at System.Net.FileWebStream..ctor(FileWebRequest request, String path, FileMode mode, FileAccess access, FileShare sharing, Int32 length, Boolean async)
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, FileAccess access, Boolean asyncHint)
   --- End of inner exception stack trace ---
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, FileAccess access, Boolean asyncHint)
   at System.Net.FileWebRequest.GetResponseCallback(Object state)
   --- End of inner exception stack trace ---
   at System.Net.FileWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.Net.FileWebRequest.GetResponse()
   at System.Deployment.Application.SystemNetDownloader.DownloadSingleFile(DownloadQueueItem next)
   --- End of inner exception stack trace ---
   at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.GetManifests(TimeSpan timeout)
   at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()

これは、Excelスプレッドシートがインストールされたパスに存在しなくなったため.VSTO、ファイルが適切に参照されていないことが原因であることが.manifestわかりました。調査.DLLを行った後、ファイル内のコピー/保存されたExcelファイルを次のように変更することで、これを手動で修正できます。custom.xml.xlsx

name="_AssemblyLocation"><vt:lpwstr>ExcelTemplate1.vsto|ca022788-e7c0-41d8-b8ae-2c0ba9edbbf8|vstolocal

これに:

name="_AssemblyLocation"><vt:lpwstr>file://c:/<path to install dir>/ExcelTemplate1.vsto|ca022788-e7c0-41d8-b8ae-2c0ba9edbbf8|vstolocal

これは私の顧客にとって実行可能な解決策ではないので、C#コードまたは(より好ましくは)インストーラーを使用して上記の変更を行うにはどうすればよいですか?

注:カスタムインストールアクション(このMSDNチュートリアルに従って)を作成しようとしました。ここで、次のように設定されていCustomActionDataます。

/assemblyLocation="[TARGETDIR]ExcelWorkbookProject.dll"/deploymentManifestLocation="[TARGETDIR]ExcelWorkbookProject.vsto"/documentLocation="[TARGETDIR]ExcelWorkbookProject.xlsx"

無駄に。

4

2 に答える 2

8

参照したMSDNの記事で概説されている指示に従う必要があります。ただし、これは少し紛らわしく、記事にエラーがあります。うまくいけば、これは明確にするのに役立ちます:

記事で提供されているものと同様のユーザースクリプトを定義する必要があります

記事の中には、プロジェクトの例を含むダウンロード可能なファイルがあります。そこからCustom Actions、そのcsプロジェクトの出力に対して自分を参照できます。CSクラスライブラリである新しいプロジェクトを作成し、問題の解決に固有の次のユーザースクリプトをコピーします。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using Microsoft.VisualStudio.Tools.Applications;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using System.IO;
using System.Windows.Forms;

namespace AddCustomizationCustomAction
{
    [RunInstaller(true)]
    public partial class AddCustomization : System.Configuration.Install.Installer
    {
        //Note: you'll have to get the Guid from your specific project in order for it to work.  The MSDN article show you how.
        static readonly Guid SolutionID = new Guid("20cb4d1d-3d14-43c9-93a8-7ebf98f50da5");

        public override void Install(IDictionary stateSaver)
        {
            string[] nonpublicCachedDataMembers = null;


            // Use the following for debugging during the install
            //string parameters = "Parameters in Context.Paramters:";
            //foreach (DictionaryEntry parameter in Context.Parameters)
            //{
            //    parameters = parameters + "\n" + parameter.Key + ":" + parameter.Value;
            //}

            //MessageBox.Show(parameters);

            //MessageBox.Show("total items in parameters: " + Context.Parameters.Count);
            //MessageBox.Show("Document Manifest Location:" + Context.Parameters["deploymentManifestLocation"]);

            Uri deploymentManifestLocation = null;
            if (Uri.TryCreate(
                Context.Parameters["deploymentManifestLocation"],
                UriKind.RelativeOrAbsolute,
                out deploymentManifestLocation) == false)
            {
                throw new InstallException(
                    "The location of the deployment manifest " +
                    "is missing or invalid.");
            }
            string documentLocation =
                Context.Parameters["documentLocation"];
            if (String.IsNullOrEmpty(documentLocation))
            {
                throw new InstallException(
                    "The location of the document is missing.");
            }
            string assemblyLocation =
                Context.Parameters["assemblyLocation"];
            if (String.IsNullOrEmpty(assemblyLocation))
            {
                throw new InstallException(
                    "The location of the assembly is missing.");
            }

            // use the following for debugging
            MessageBox.Show(documentLocation);

            if (ServerDocument.IsCustomized(documentLocation))
            {
                ServerDocument.RemoveCustomization(documentLocation);
            }
            ServerDocument.AddCustomization(
                documentLocation,
                assemblyLocation,
                SolutionID,
                deploymentManifestLocation,
                false,
                out nonpublicCachedDataMembers);
            stateSaver.Add("documentlocation", documentLocation);
            base.Install(stateSaver);
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
        }

        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
        }

    }
}

これは、インストーラーのインストール手順をオーバーライドします。base.Install(stateSaver)は残りのコードを呼び出して、通常どおりインストールを続行します。

MSDN記事のエラー:

この記事ではCustomActionData、カスタムアクションのインストールに以下を使用するように指示されています。

/assemblyLocation="[TARGETDIR]<YourProjectName>.dll"/deploymentManifestLocation="[TARGETDIR]<YourProjectName>.vsto"/documentLocation="[TARGETDIR]<YourProjectName>.xltx"

ただし、これである必要があります(パラメータ間のスペースに注意してください)。

/assemblyLocation="[TARGETDIR]<YourProjectName>.dll" /deploymentManifestLocation="[TARGETDIR]<YourProjectName>.vsto" /documentLocation="[TARGETDIR]<YourProejctName>.xltx"

これで問題は解決するはずですが、インストーラーはデバッグではなくリリースを指しているため、インストーラーを再構築する前に、Excelプロジェクトへの変更をリリースビルドに再構築してください。

于 2012-07-18T21:50:46.843 に答える
0

ジェームズ・メルツの答えは的確ですが、それも少し時代遅れです(ただし、髪を抜いた1日後に私を救っただけです)。Visual Studioの新しいバージョンでは、アプリケーションビルドのこの部分の手順はここに移動しました。私はあなたがそれらを読むことを提案します、あるいはあなたは以下の私のクリフノートバージョンを読むことができます:

既存のソリューションで新しいプロジェクトとして構築する必要がある新しいコンソールアプリケーション。次のProgram.csようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Microsoft.VisualStudio.Tools.Applications;

namespace SetExcelDocumentProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            string assemblyLocation = "";
            Guid solutionID = new Guid();
            Uri deploymentManifestLocation = null;
            string documentLocation = "";
            string[] nonpublicCachedDataMembers = null;

            for (int i = 0; i <= args.Count() - 1; i++)
            {
                Console.WriteLine(args[i]);
                string[] oArugment = args[i].Split('=');

                switch (oArugment[0])
                {
                    case "/assemblyLocation":
                        assemblyLocation = oArugment[1];
                        break;
                    case "/deploymentManifestLocation":
                        if (!Uri.TryCreate(oArugment[1], UriKind.Absolute, out deploymentManifestLocation))
                        {
                            Console.WriteLine("Error creating URI");
                        }
                        break;
                    case "/documentLocation":
                        documentLocation = oArugment[1];
                        break;
                    case "/solutionID":
                        solutionID = Guid.Parse(oArugment[1]);
                        break;
                }
            }
            try
            {
                ServerDocument.RemoveCustomization(documentLocation);
                ServerDocument.AddCustomization(documentLocation, assemblyLocation,
                                            solutionID, deploymentManifestLocation,
                                            true, out nonpublicCachedDataMembers);

            }
            catch (System.IO.FileNotFoundException)
            {
                Console.WriteLine("The specified document does not exist.");
            }
            catch (System.IO.IOException)
            {
                Console.WriteLine("The specified document is read-only.");
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine("The customization could not be removed.\n" +
                    ex.Message);
            }
            catch (DocumentNotCustomizedException ex)
            {
                Console.WriteLine("The document could not be customized.\n" +
                    ex.Message);
            }
        }
    }
}

InstallShield Setupからパラメーターを渡すため、これを変更する必要はありません。

これには、新しいプロジェクトで2つの参照が必要です。

  • Microsoft.VisualStudio.Tools.Applications.Runtime
  • Microsoft.VisualStudio.Tools.Applications.ServerDocument

ここで、インストールの完了後にこの新しいアプリケーションを呼び出し、パラメーターを渡します(この指示リンクにもあります)。その新しいプロジェクトからのプライマリ出力をInstallShield「アプリケーションファイル」に追加します。

次に、Install Shieldの[カスタムアクション]に移動し、[インストール中のカスタムアクション]セクションの[セットアップ完了後の成功ダイアログ]をダブルクリックします。これは、インストールが完了したら、vbscript、jscript、または実行可能ファイルを実行できる場所です。ここでは、パラメータを渡して新しいコンソールアプリケーション実行可能ファイルを実行します。

新しいカスタムアクションで、[ソースの場所]プロパティのリストで、[製品とともにインストール]を選択し、VSTOアプリケーションをインストール先にインストールする新しいプロジェクトのプライマリ出力ファイルを参照します。

次に、[コマンドライン]プロパティボックスに、コンソールアプリケーションの実行に必要な引数のリストを入力します。

/assemblyLocation="[INSTALLDIR]ExcelWorkbook.dll" /deploymentManifestLocation="[INSTALLDIR]ExcelWorkbook.vsto" /documentLocation="[INSTALLDIR]ExcelWorkbook.xlsx" /solutionID="Your Solution ID"

これらは、dll、vsto、ワークブック、およびソリューションID用に変更する必要があります。ソリューションIDは、ファイル内にあり.csprojます(ファイルエクスプローラーで見つけて、メモ帳で開きます)。

今、あなたは金色です。アプリケーションが正常にインストールされると、このコンソールアプリケーションが起動しmanifestLocation、ワークブックの相対パスではなく、インストールパスに変更されます。

インストールしている人が自分のコンピュータの管理者権限を持っておらず、Program Filesディレクトリにインストールしている場合、この手順を実行する前にインストールして実行できたが、その後は実行できなかったことがわかります。これは、ブックがその場所で読み取り専用であるためです。その場合、アプリケーションをインストールするために別の場所を選択する必要があります(AppDataLocalが適切な選択です)。

于 2019-02-21T23:12:31.457 に答える