如何访问正在运行的应用程序的应用程序清单?

时间:2013-11-20 15:21:14

标签: c# manifest

我需要找到一种方法来保证使用我的库的人在应用程序清单中将requestedExecutionLevel设置为最小highestAvailable,如下所示:

<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
  <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
</requestedPrivileges>

当他们没有正确设置清单时,我想抛出异常,以便开发人员知道这个需求,而无需阅读文档。

主要问题:是否可以访问此信息,如果是这样的话?

我已经考虑过检查此设置的结果,而不是检查此设置。设置为highestAvailable时,我希望管理员组的任何用户部分都以管理员身份运行。

这可以使用:

2 个答案:

答案 0 :(得分:7)

您的方法存在缺陷,使用您的库的开发人员会非常不喜欢它。问题是清单不是使进程升级的唯一方法。事实上,在调试代码时,几乎从未像现在这样,Visual Studio托管过程是您运行的EXE,并且具有活动清单,没有“highestAvailable”。开发人员将提升Visual Studio本身,他开始的程序继承安全令牌并且也会升级。

>这很难得到,如果进程没有提升,那么安全令牌就是普通用户之一。

您需要代码available here。如果IsUserInAdminGroup为true且IsProcessElevated为false,则抛出异常。

答案 1 :(得分:0)

作为Hans Passant points out in his answer,真正的基本问题 - 为什么在这种情况下你想检查清单 - 是:

如何检查当前用户是否可以使用提升的权限运行进程?

正如问题所示,以下内容可行:

var myPrincipal = new WindowsPrincipal( WindowsIdentity.GetCurrent() );
if ( !myPrincipal.IsInRole( WindowsBuiltInRole.Administrator ) &&
     IsUserInAdminGroup() )
{
    throw new NotSupportedException( "Some useful comments ..." );
}

主要问题是,你如何写IsUserInAdminGroup()code listed in the UAC self-elevation sample虽然有用,但不能解释发生了什么,以及为什么需要它。

Hans Passant回复in a comment “Windows模拟了一个非提升的进程,无法告诉.NET用户帐户实际上是一个管理员帐户。回过头来查询令牌pinvoke是链接代码中使用的解决方法。“

简而言之,您需要依赖P / Invoke 才能实现IsUserInAdminGroup(),其代码可以找到in the UAC sample

或许更有趣,是为什么?

为了找出I refactored the sample code and incorporated the function into my library。我认为结果更清楚一些。下面你可以找到大纲,评论可能比代码更相关,因为它取决于其他类等...

从Windows Vista开始,您有TOKEN_ELEVATION_TYPE所表示的不同令牌类型。虽然您可以通过.NET访问WindowsIdentity.Token,但这不是我们需要检查某人是否为管理员的令牌。这是有限令牌。它附加了一个链接的提升令牌,但这不会在.NET中公开。

下面几乎所有的(半伪)代码都会查找原始令牌是否附加了这样一个提升的令牌,并使用它来检查IsInRole()

// Default token's received aren't impersonation tokens,
// we are looking for an impersonation token.
bool isImpersonationToken = false;

// Open the access token of the current process.
SafeTokenHandle processToken;
if ( !AdvApi32.OpenProcessToken( ..., out processToken ) )
{
    MarshalHelper.ThrowLastWin32ErrorException();
}

// Starting from Vista linked tokens are supported which need to be checked.
if ( EnvironmentHelper.VistaOrHigher )
{
    // Determine token type: limited, elevated, or default.
    SafeUnmanagedMemoryHandle elevationTypeHandle = ...;
    if ( !AdvApi32.GetTokenInformation( ... elevationTypeHandle ) )
    {
        MarshalHelper.ThrowLastWin32ErrorException();
    }
    var tokenType = (AdvApi32.TokenElevationType)Marshal.ReadInt32( 
        elevationTypeHandle.DangerousGetHandle() );

    // If limited, get the linked elevated token for further check.
    if ( tokenType == AdvApi32.TokenElevationType.TokenElevationTypeLimited )
    {
        // Get the linked token.
        SafeUnmanagedMemoryHandle linkedTokenHandle = ...;
        if ( !AdvApi32.GetTokenInformation( ... linkedTokenHandle ) )
        {
            MarshalHelper.ThrowLastWin32ErrorException();
        }
        processToken = new SafeTokenHandle(
             Marshal.ReadIntPtr( linkedTokenHandle.DangerousGetHandle() ) );
        // Linked tokens are already impersonation tokens.
        isImpersonationToken = true;
    }
}

// We need an impersonation token in order
// to check whether it contains admin SID.
if ( !isImpersonationToken )
{
    SafeTokenHandle impersonatedToken;
    if ( !AdvApi32.DuplicateToken( ..., out impersonatedToken ) )
    {
        MarshalHelper.ThrowLastWin32ErrorException();
    }
    processToken = impersonatedToken;
}

// Check if the token to be checked contains admin SID.
var identity= new WindowsIdentity( processToken.DangerousGetHandle() );
var principal = new WindowsPrincipal( identity );
return principal.IsInRole( WindowsBuiltInRole.Administrator );