web-dev-qa-db-ja.com

VS2013パブリッシュWebデプロイメントタスクが失敗しましたファイルは使用中です

VS2013 Premiumを使用してサイトをWindows Server 2012に公開しています。SqlServerTypes\ x64\msvcr100.dllを除くすべてのファイルは正常に公開されます。

SqlServerTypes\x64\SqlServerSpatial110.dll

SqlServerTypes\x86\msvcr100.dll

SqlServerTypes\x86\SqlServerSpatial110.dll

公開しようとした上記のファイルごとにこの種のエラーが発生します。Webデプロイメントタスクが失敗しました。 (ファイル 'msvcr100.dll'は使用中です。詳細: http://go.Microsoft.com/fwlink/?LinkId=221672#ERROR_FILE_IN_USE

興味深いことに、これらのファイルは最初に公開され(サーバー上になかった場合)、その後上書きされなくなりました。 2つの異なるWebサーバーで試してみました。私はここでガイドに従いました: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx

...しかし、サイトをオフラインにできただけです(VSはapp_offline.htmを配置しています)が、同じエラーで公開に失敗します。他のすべてのファイルは完全に公開されます。

何か案は?

32
user3546827

公開中にアプリをオフラインにして、ファイルのロックを解除して更新できるようにすることができます。

これについてブログに書いた しばらく前。概説されたサポートは、Azure SDKとVisual Studio Updateの内部で出荷されました。正確なリリースは覚えていませんが、必要に応じて調べることができます。そのブログ投稿前後の更新は問題ありません。

前提条件:

  • VS 2012 + VSアップデート/ VS 2013 + VSアップデート/ VS2015
  • MSDeploy v3

注:CIサーバーから公開している場合、CIサーバーも上記の更新が必要になります

パブリッシュプロファイルを編集する

VSでは、Web公開プロファイルを作成すると、ダイアログの設定が。[pubxml]で終わるファイルとしてProperties\PublishProfiles\に保存されます。 注:.pubxml.userファイルもあります。このファイルは変更しないでください

.pubxmlファイルでアプリをオフラインにするには、次のプロパティを追加します。

<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>

ノート

ASP.NETが必要

これがMSDeploy側で実装されている方法は、app_offline.htmファイルがWebサイト/アプリのルートにドロップされることです。そこからasp.netランタイムがそれを検出し、アプリをオフラインにします。このため、Webサイト/アプリでasp.netが有効になっていない場合、この機能は機能しません。

うまくいかない場合

この実装により、公開が開始される前にアプリが完全にオフラインにならない場合があります。最初にapp_offline.htmファイルがドロップされ、次にMSDeployがファイルの公開を開始します。 ASP.NETがファイルを検出して実際にオフラインにするのを待ちません。このため、まだファイルロックに遭遇する場合があります。デフォルトではVSは再試行を有効にするため、通常、アプリは再試行の1つ中にオフラインになり、すべて正常です。場合によっては、ASP.NETの応答に時間がかかることがあります。それはもう少しトリッキーです。

<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>を追加し、アプリがすぐにオフラインにならない場合は、公開を開始する前にアプリをオフラインにすることをお勧めします。これをリモートで行う方法はいくつかありますが、それはセットアップによって異なります。 MSDeployアクセスしか持っていない場合は、次のシーケンスを試すことができます。

  1. msdeploy.exeを使用して、app_offline.htmをドロップし、サイトをオフラインにします
  2. msdeploy.exeを使用してアプリを公開します(_同期によってapp_offline.htmファイルが削除されないようにしてください_)
  3. しばらく待つ
  4. サイトを公開する
  5. msdeploy.exeを使用して、app_offline.htmを削除し、アプリをオンラインにします

これを行う方法については、 http://sedodream.com/2012/01/08/howtotakeyourwebappofflineduringpublishing.aspx でブログに書いています。そのブログ投稿に欠けている唯一のものは、サイトが実際にオフラインになるのを待つ遅延です。プロジェクトのビルド/公開プロセスに統合する代わりに、msdeploy.exeを直接呼び出すだけのスクリプトを作成することもできます。

26

http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksumで解決策の理由を見つけました.aspx は元のポスターでは機能しませんでした。回避策があります。

EnableMSDeployAppOfflineアプローチの問題は、アプリケーションをホストするアプリドメインのみをリサイクルすることです。アプリドメインが存在するアプリプールワーカープロセス(w3wp.exe)はリサイクルされません。

アプリドメインを破棄して再作成しても、問題のSQL Server Spatial dllには影響しません。これらのDLLは、相互運用のLoadLibray呼び出しを介して手動で読み込まれるアンマネージコードです。したがって、dllはアプリドメインの範囲外に住んでいます。

アプリプールプロセスがそれらに課しているファイルロックを解放するには、アプリプールをリサイクルするか、メモリから手動でDLLをアンロードする必要があります。

Microsoft.SqlServer.Types nugetパッケージは、SqlServerTypes.Utilitiesと呼ばれるSpatial dllをロードするために使用されるクラスを出荷します。 LoadNativeAssembliesメソッドを変更して、アプリドメインがアンロードされたときにアンマネージdllをアンロードできます。この変更により、msdeployがapp_offline.htmをコピーするときに、アプリドメインがアンロードされ、マネージdllもアンロードされます。

private static IntPtr _msvcrPtr = IntPtr.Zero;
private static IntPtr _spatialPtr = IntPtr.Zero;

public static void LoadNativeAssemblies(string rootApplicationPath)
{
    if (_msvcrPtr != IntPtr.Zero || _spatialPtr != IntPtr.Zero)
        throw new Exception("LoadNativeAssemblies already called.");

    var nativeBinaryPath = IntPtr.Size > 4
        ? Path.Combine(rootApplicationPath, @"SqlServerTypes\x64\")
        : Path.Combine(rootApplicationPath, @"SqlServerTypes\x86\");

    _msvcrPtr = LoadNativeAssembly(nativeBinaryPath, "msvcr100.dll");
    _spatialPtr = LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial110.dll");

    AppDomain.CurrentDomain.DomainUnload += (sender, e) =>
    {
        if (_msvcrPtr != IntPtr.Zero)
        {
            FreeLibrary(_msvcrPtr);
            _msvcrPtr = IntPtr.Zero;
        }

        if (_spatialPtr != IntPtr.Zero)
        {
            FreeLibrary(_spatialPtr);
            _spatialPtr = IntPtr.Zero;
         }
    };
}

このアプローチには注意点が1つあります。これは、アプリケーションがSpatial dllを使用しているワーカープロセスで実行されている唯一のアプリケーションであることを前提としています。アプリプールは複数のアプリケーションをホストできるため、別のアプリケーションもそれらをロードした場合、ファイルロックは解放されません。これにより、同じファイルがロックされたエラーでデプロイが機能しなくなります。

7
Paul

私が行う最も簡単なことは、これらのDLLをCopyLocalと同じようにすることです。これらのdllがプログラムファイルフォルダーから引き出されていると思います。それらをcopylocal trueとしてマークして、展開を試みます。ローカルマシンで実行中のすべてのIISローカルプロセスを停止するようにしてください。

1
qamar

IISおよびファイルロックに関する既知の問題があります(なぜそれらがまだ解決されないのか私にはわかりません)。

ただし、これらのファイルを再デプロイする必要があるかどうかについては、質問しますか?

私はファイル名を認識し、それらがシステムファイルであることを思い出します。システムファイルは、サーバー上に既に存在しているか、単に再展開する必要はありません。

IISに関してはあまり経験がありませんが、以前この問題に遭遇したことがあり、経験豊富な同僚の何人かから、これは既知のIISの問題と言った通りだと言われましたそして私はあなたの質問への答えは次のとおりであると信じています:

  1. 不要なファイルを展開しないでください。
  2. 再試行
  3. ウェブサイトをリセット
  4. 再試行
  5. iisreset
1
DOOMDUDEMX

ファイルロックを取得している、新しい手間のかかるクラウドバックアップサービスが実行されていないことに注意してください。また、エクスプローラーやDLL検査ツール)で開いているものもありません。

MSがこの問題に対してより良い対策を講じていないのは、とんでもないことだと思います。 10回のうち9回はうまく機能していることがわかりましたが、トラフィックが増加すると、10回に1回になることがあります。

私は問題を解決するつもりです:

  • 2つのアプリケーションMySite.AおよびMySite.B、一度に1つだけ実行されます。
  • その後、常に休止状態のサイトに展開します。
  • 展開中に問題が発生しても、サイト全体がダウンすることはありません。
  • 展開後に大きな問題が発生した場合は、簡単に元に戻すことができます。

どのように実装するかはよくわかりませんが、これが私がやるべきことだと思います。

0
Simon_Weaver