32

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 を配置しています) が、公開は同じエラーで失敗します。他のすべてのファイルは完全に公開されます。

何か案は?

4

5 に答える 5

27

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

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

前提条件:

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

注: CI サーバーから公開する場合、CI サーバーにも上記の更新が必要です。

発行プロファイルを編集する

VS で Web パブリッシュ プロファイルを作成すると、ダイアログの設定がProperties\PublishProfiles\.pubxml で終わるファイルとして保存されます。注:ファイルもあり.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.exeapp_offline.htm をドロップして、サイトをオフラインにするために使用します
  2. アプリの公開に使用msdeploy.exeします (_同期によって app_offline.htm ファイルが削除されないことを確認してください_)
  3. しばらく待ちます
  4. サイトを公開する
  5. msdeploy.exeapp_offline.htm を削除してアプリをオンラインにするために使用します

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

于 2015-01-06T03:42:31.060 に答える
8

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 もアンロードされます。

[DllImport("kernel32.dll", SetLastError = true)]
internal extern static bool FreeLibrary(IntPtr hModule);

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 を使用しているワーカー プロセスで実行されているのは、アプリケーションだけであると想定しています。アプリケーション プールは複数のアプリケーションをホストできるため、別のアプリケーションもそれらをロードしている場合、ファイル ロックは解放されません。これにより、展開が同じファイル ロック エラーで機能しなくなります。

于 2015-09-18T21:38:04.587 に答える