1

我有一个问题,起初似乎是许可。在 localhost 上工作得很好,但是当转到服务器时会发生错误:

[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
    ...
    ...
    ...
}

Microsoft.Office.Interop.Word 这个 dll 在服务器的 Bin 文件夹中,有没有人知道会发生什么?

谢谢你。

4

3 回答 3

4

虽然您不应该在服务器上使用 Office 互操作库。Microsoft 不推荐或不支持这种实现,但如果您请求惩罚以克服您的错误,您需要打开服务器上的 DCOM 配置并将身份设置为运行您的应用程序池的用户并授予他们访问启动和激活权限。同样,您不想在服务器上设置 Office 互操作库。

于 2012-04-11T14:39:22.153 回答
0

Application PoolsIIS 下,设置Identity字段以NetworkService在我的设置中解决此问题。

于 2015-01-07T07:36:51.373 回答
0

(虽然不建议在服务器中使用office interop,但有时我们不得不......)

该问题与安全性有关。ASP.NET 进程的用户身份没有使用 Office 应用程序的访问权限,并且该身份应仅具有运行应用程序所需的最低权限。您可以使用代码模拟在运行时提高权限,而无需在 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应该是有效的本地或域帐户。要测试 office 用户帐户是否正常工作,请使用此用户帐户凭据登录服务器并启动 MS word 应用程序。如果是第一次打开 Word,可能会出现一些设置相关的弹窗。解决它们,否则它们可能会在编程访问期间产生问题。

如果您将用户帐户凭据保存在配置文件中,请考虑对这些值进行加密。请参阅以下 SO Q&A:

如何加密 web.config 中的一项

在 web.config 中加密 appSettings

希望这可以帮助...

于 2012-04-11T18:31:44.467 回答