1

最初は許可のように見える問題があります。ローカルホストでは問題なく動作しますが、サーバーに移動するとエラーが発生します:

[UnauthorizedAccessException: CLSID {000209FF-0000-0000-C000-000000000046} のコンポーネントの COM クラス ファクトリを取得できませんでした。次のエラーが原因です: 80070005.]

IIS7
を使用しています。iis ユーザーに許可を与えましたが、役に立たなかったので、コードに「try catch」を広げたところ、Microsoft.Office.Interop.Word のインスタンスを作成しようとした瞬間にエラーが関連していることがわかりました。

using Word = Microsoft.Office.Interop.Word;

private bool Exemple(SqlDataReader dbReader, string strFilePath)
{ 
    Word.Application oApp = new Word.Application ();   // error here
    ...
    ...
    ...
}

サーバーの Bin フォルダーにある Microsoft.Office.Interop.Word この dll に、何が起こっているのか誰にもわかりませんか?

ありがとうございました。

4

3 に答える 3

4

サーバー上で Office 相互運用ライブラリを使用しないでください。マイクロソフトはそのような実装を推奨またはサポートしていませんが、エラーを回避するために罰を求めている場合は、サーバーで DCOM 構成を開き、アプリ プールを実行しているユーザーに ID を設定して付与する必要があります。許可を起動してアクティブ化するためのアクセス。繰り返しますが、サーバー上に Office 相互運用ライブラリをセットアップする必要はありません。

于 2012-04-11T14:39:22.153 に答える
0

(サーバーでオフィス相互運用を使用することはお勧めしませんが、必要になる場合もあります...)

この問題はセキュリティに関連しています。ASP.NET プロセスのユーザー ID には、office アプリを使用するためのアクセス権がありません。ID には、アプリケーションを実行するために必要な最小限のアクセス許可のみが必要です。コードの偽装を使用して、web.config で偽装を設定したり、ASP.NET ユーザー アカウントに高い権限のアカウントを使用したりせずに、実行時にアクセス許可を上げることができます。サーバーで使用しましたが、このアプローチが気に入っています。

詳細については、 Googleで検索できます。http://support.microsoft.com/kb/306158のコードは次のとおりです。

public class CodeImpersonate
{
    /// <summary>
    /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on by a terminal server, 
    /// remote shell, or similar process. This logon type has the additional expense of caching logon information for disconnected operations; therefore,
    /// it is inappropriate for some client/server applications, such as a mail server.
    /// </summary>
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    /// <summary>
    /// Use the standard logon provider for the system. The default security provider is negotiate, 
    /// unless you pass NULL for the domain name and the user name is not in UPN format. In this case, the default provider is NTLM.
    /// Windows 2000: The default security provider is NTLM.
    /// </summary>
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    WindowsImpersonationContext impersonationContext;

    [DllImport("advapi32.dll")]
    public static extern int LogonUserA(String lpszUserName,
                                        String lpszDomain,
                                        String lpszPassword,
                                        int dwLogonType,
                                        int dwLogonProvider,
                                        ref IntPtr phToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);      

    public bool ImpersonateValidUser(String userName, String domain, String password)
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf())
        {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
            {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    if (impersonationContext != null)
                    {
                        CloseHandle(token);
                        CloseHandle(tokenDuplicate);
                        return true;
                    }
                }
            }
        }
        if (token != IntPtr.Zero)
            CloseHandle(token);
        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
        return false;
    }

    public void UndoImpersonation()
    {
        if (impersonationContext != null)
            impersonationContext.Undo();
    }

}

上記のコードをファイルにコピーします。使用例を次に示します。

CodeImpersonate codeImpersonate = null;
try
{
    codeImpersonate = new CodeImpersonate();
    var isLoggedIn = codeImpersonate.ImpersonateValidUser(AppConfigs.OfficeUser, AppConfigs.OfficeUeerDomnia, AppConfigs.OfficeUserPass);

    if (isLoggedIn)
    {
        //Do your office work....
    }
    else
        throw new InvalidOperationException("Login failed for office user.");
}
finally
{
    if (codeImpersonate != null)
        codeImpersonate.UndoImpersonation();
    codeImpersonate = null;
}

上記のコードを複数の場所で使用するためのファサードを次に示します。

public class ImpersonateServices
{
    public ImpersonateServices(String userName, String domain, String password)
    {
        this.UserName = userName;
        this.Domain = domain;
        this.Password = password;
    }

    public string UserName { get; private set; }

    public string Domain { get; private set; }

    public string Password { get; private set; }

    public void Execute(Action privilegedAction)
    {
        CodeImpersonate codeImpersonate = null;
        try
        {
            codeImpersonate = new CodeImpersonate();
            var isLoggedIn = codeImpersonate.ImpersonateValidUser(this.UserName, this.Domain, this.Password);

            if (isLoggedIn){
                privilegedAction();
            }
            else
                throw new InvalidOperationException("Login failed for office user.");
        }
        finally
        {
            if (codeImpersonate != null)
                codeImpersonate.UndoImpersonation();
            codeImpersonate = null;
        }
    }
}

次のように使用します。

var impersonateServices = new ImpersonateServices(AppConfigs.OfficeUser, 
                                              AppConfigs.OfficeUserDomain, 
                                              AppConfigs.OfficeUserPass);
impersonateServices.Execute(() => { 
    //Do your Office work...
});

office-Userは、有効なローカル アカウントまたはドメイン アカウントである必要があります。オフィス ユーザー アカウントの動作をテストするには、このユーザー アカウント資格情報を使用してサーバーにログインし、MS Word アプリケーションを起動します。Word を初めて開いた場合、設定関連のポップアップが表示されることがあります。解決しないと、プログラムによるアクセス中に問題が発生する可能性があります。

ユーザー アカウントの資格情報を構成ファイルに保持する場合は、値を暗号化することを検討してください。以下の SO Q&A を参照してください。

web.config の 1 つのエントリを暗号化する方法

web.config での appSettings の暗号化

お役に立てれば...

于 2012-04-11T18:31:44.467 に答える
0

Application PoolsIIS で、フィールドを設定しIdentityNetworkServiceセットアップでこの問題を解決しました。

于 2015-01-07T07:36:51.373 に答える