在C#中检查当前用户的程序是否正在运行

问题描述 投票:0回答:4

我需要检查程序(

xyz.exe
)是否正在运行,但仅限于当前用户。无论使用什么方法都不需要提升权限,并且必须运行速度快(因此 WMI 已被淘汰)。

Process.GetProcessesByName("xyz")
返回所有登录用户的“xyz”结果...但我只关心当前用户。

想法?

c# .net process
4个回答
11
投票

使用当前进程

SessionId
来过滤进程列表:

    public static bool IsProcessRunningSameSession(string processName)
    {
        var currentSessionID = Process.GetCurrentProcess().SessionId;
        return Process.GetProcessesByName(processName).Where(p => p.SessionId == currentSessionID).Any();
    }

0
投票

我在这里找到了答案: http://dotbay.blogspot.com/2009/06/finding-owner-of-process-in-c.html

我会复制/粘贴它,以防博客过时。

////
        // 'WindowsIdentity' Extension Method Demo: 
        //   Enumerate all running processes with their associated Windows Identity
        ////

        foreach (var p in Process.GetProcesses())
        {
            string processName;

            try
            {
                processName = p.WindowsIdentity().Name;

            }
            catch (Exception ex)
            {

                processName = ex.Message; // Probably "Access is denied"
            }

            Console.WriteLine(p.ProcessName + " (" + processName + ")");
        }

这是对应的类:

//-----------------------------------------------------------------------
// <copyright file="ProcessExtensions.cs" company="DockOfTheBay">
//     http://www.dotbay.be
// </copyright>
// <summary>Defines the ProcessExtensions class.</summary>
//-----------------------------------------------------------------------

namespace DockOfTheBay
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Security.Principal;

    /// <summary>
    /// Extension Methods for the System.Diagnostics.Process Class.
    /// </summary>
    public static class ProcessExtensions
    {
        /// <summary>
        /// Required to query an access token.
        /// </summary>
        private static uint TOKEN_QUERY = 0x0008;

        /// <summary>
        /// Returns the WindowsIdentity associated to a Process
        /// </summary>
        /// <param name="process">The Windows Process.</param>
        /// <returns>The WindowsIdentity of the Process.</returns>
        /// <remarks>Be prepared for 'Access Denied' Exceptions</remarks>
        public static WindowsIdentity WindowsIdentity(this Process process)
        {
            IntPtr ph = IntPtr.Zero;
            WindowsIdentity wi = null;
            try
            {
                OpenProcessToken(process.Handle, TOKEN_QUERY, out ph);
                wi = new WindowsIdentity(ph);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (ph != IntPtr.Zero)
                {
                    CloseHandle(ph);
                }
            }

            return wi;
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr hObject);
    }
}

0
投票

这是完整的程序。它是一个命令行 C# 应用程序。很丑而且没有评论。但它有效。你向它提供一个 EXE 的名称(包括路径),它会检查它是否已经在运行,如果没有,则启动它。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;


namespace SingleRun
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = "";
            var prog = "";
            if (args.Length == 0) {
                MessageBox.Show("Please include a program to start.\n\nExample: \nSingleRun.exe \"C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe\"", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                System.Environment.Exit(1);
            }else{
                path = args[0];
                if (!File.Exists(path)) {
                    MessageBox.Show("\"" + path + "\" does not exist.\nPlease check the location.\nAnything with spaces in it needs to be inside double-quotes.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    System.Environment.Exit(1);
                }else{
                    var splits = path.Split('\\');
                    prog = splits[splits.Length - 1];
                    foreach (var p in Process.GetProcessesByName(prog.Replace(".exe",""))) {
                        string processOwner;
                        try {
                            processOwner = p.WindowsIdentity().Name;
                        }
                        catch (Exception ex) {
                            processOwner = ex.Message; // Probably "Access is denied"
                        }
                        if (processOwner.Contains(Environment.UserName)) {
                            MessageBox.Show("Program already running with PID " + p.Id, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            System.Environment.Exit(1);
                        }
                    }
                    Process newProcess = Process.Start(path);
                    Console.WriteLine("Launching " + prog + " with PID: " + newProcess.Id);
                }
            }
        }
    }

    /// <summary>
    /// Extension Methods for the System.Diagnostics.Process Class.
    /// </summary>
    public static class ProcessExtensions {
        /// <summary>
        /// Required to query an access token.
        /// </summary>
        private static uint TOKEN_QUERY = 0x0008;

        /// <summary>
        /// Returns the WindowsIdentity associated to a Process
        /// </summary>
        /// <param name="process">The Windows Process.</param>
        /// <returns>The WindowsIdentity of the Process.</returns>
        /// <remarks>Be prepared for 'Access Denied' Exceptions</remarks>
        public static WindowsIdentity WindowsIdentity(this Process process) {
            IntPtr ph = IntPtr.Zero;
            WindowsIdentity wi = null;
            try {
                OpenProcessToken(process.Handle, TOKEN_QUERY, out ph);
                wi = new WindowsIdentity(ph);
            }
            catch (Exception) {
                throw;
            }
            finally {
                if (ph != IntPtr.Zero) {
                    CloseHandle(ph);
                }
            }

            return wi;
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr hObject);
    }
}

0
投票

上面的代码运行良好。但是,如果您只想知道当前用户是否看到打开的应用程序:如果该进程不是来自当前用户,则如果您尝试获取句柄,则已经出现异常。 因此,您可以使用此扩展做得更简单:

    public static bool ProcessAccessibleForCurrentUser(this Process process)
    {
        try
        {
            var ptr = process.Handle;
            return true;
        }
        catch
        {
            return false;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.