检测另一个进程是否以“管理员身份运行”启动

4
我们的应用程序需要通过COM接口与另一个程序通信。如果使用“以管理员身份运行”启动该程序,则接口将无法正常工作。希望能够检测此进程是否处于此状态并警告用户。有什么想法吗?
寻找.NET语言(C#或VB.NET)。
谢谢。

1
你的问题似乎是为什么COM不能跨越在不同层次运行的应用程序之间的桥梁,而不是如何检测它。你是否正确地保护了COM通道? - Remus Rusanu
COM 使得无法发现托管服务器的进程。这是非常计划中的,它允许各种托管技巧。你必须使用你对该进程的秘密知识。 - Hans Passant
2个回答

7
你可以尝试这样做:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Principal;
using System.Reflection;

namespace WindowsFormsApplication2
{

    public class ProcessHelper
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CloseHandle(IntPtr hObject);

        private const int STANDARD_RIGHTS_REQUIRED      = 0xF0000;
        private const int TOKEN_ASSIGN_PRIMARY           =0x1;
        private const int TOKEN_DUPLICATE                 = 0x2;
        private const int TOKEN_IMPERSONATE              = 0x4;
        private const int TOKEN_QUERY                     = 0x8;
        private const int TOKEN_QUERY_SOURCE             = 0x10;
        private const int TOKEN_ADJUST_GROUPS           = 0x40;
        private const int TOKEN_ADJUST_PRIVILEGES        = 0x20;
        private const int TOKEN_ADJUST_SESSIONID          = 0x100;
        private const int TOKEN_ADJUST_DEFAULT          = 0x80;
        private const int TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT);

        public static bool IsProcessOwnerAdmin(string processName)
        {
            Process proc = Process.GetProcessesByName(processName)[0];

            IntPtr ph = IntPtr.Zero;

            OpenProcessToken(proc.Handle, TOKEN_ALL_ACCESS, out ph);

            WindowsIdentity iden = new WindowsIdentity(ph);

            bool result = false;

            foreach (IdentityReference role in iden.Groups)
            {
                if (role.IsValidTargetType(typeof(SecurityIdentifier)))
                {
                    SecurityIdentifier sid = role as SecurityIdentifier;

                    if (sid.IsWellKnown(WellKnownSidType.AccountAdministratorSid) || sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid))
                    {
                        result = true;
                        break;
                    }
                }
            }

            CloseHandle(ph);

            return result;
        }
    }

    static class Program
    {
        [STAThread]
        static void Main()
        {
            bool isAdmin = ProcessHelper.IsProcessOwnerAdmin("outlook");
        }
    }
}

这也可能是一个好东西: Windows操作系统中已知的安全标识符。这应该是一个不错的起点 :-)

仍然是访问被拒绝。顺便说一下,我添加了私有常量int STANDARD_RIGHTS_REQUIRED = 0x000F0000; - Randy N.
@Randy N.:你可以尝试以管理员身份运行应用程序,看看是否有效吗?如果是的话,我建议在检查进程用户信息之前进行应用程序模拟,并在完成后取消模拟。明白了吗? - HABJAN
我也尝试了使用GetSecurityInfo而不是OpenProcessToken,但它也返回访问被拒绝。感谢您的帮助。 - Randy N.
好的,从我所看到的来看,使用这段代码唯一确定应用程序是否使用“以管理员身份运行”的方式启动的方法是,如果你收到“访问被拒绝”的错误。这意味着运行应用程序具有您的应用程序没有的权限(在本例中为ADMIN权限)。 - HABJAN
@Randy N.:抱歉,我无法帮助您更干净地解决这个问题。 - HABJAN
显示剩余3条评论

-2

可能有点晚了,但我为自己创建了这个(代码不太好...用了try和catch,但它能工作):

private void Msg_Click(object sender, RoutedEventArgs e)
    {
        //running at all
        if (Process.GetProcessesByName("OUTLOOK").Any())
        {
            try
            {
                var app = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Outlook.Application");
            }

            //running normally
            catch (InvalidCastException)
            {
              
            }

            //running as admin
            catch (System.Runtime.InteropServices.COMException)
            {

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }

    }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接