Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以使用互斥锁的管理员身份重新启动应用程序_C#_.net_Mutex - Fatal编程技术网

C# 以使用互斥锁的管理员身份重新启动应用程序

C# 以使用互斥锁的管理员身份重新启动应用程序,c#,.net,mutex,C#,.net,Mutex,我有一个应用程序,它使用互斥来停止同时运行的多个实例,并接受运行实例的命令行输入 我在应用程序中有一个功能,询问用户是否希望在需要时以管理员身份重新启动。例如,他们启用的功能可能需要管理员权限 互斥对象类如下所示: namespace SingleInstanceClassLibrary { /// <summary> /// Enforces single instance for an application. /// </summary> public class

我有一个应用程序,它使用互斥来停止同时运行的多个实例,并接受运行实例的命令行输入

我在应用程序中有一个功能,询问用户是否希望在需要时以管理员身份重新启动。例如,他们启用的功能可能需要管理员权限

互斥对象类如下所示:

namespace SingleInstanceClassLibrary
{
/// <summary>
/// Enforces single instance for an application.
/// </summary>
public class SingleInstance : IDisposable
{
    private Mutex mutex = null;
    private Boolean ownsMutex = false;
    private Guid identifier = Guid.Empty;

    /// <summary>
    /// Enforces single instance for an application.
    /// </summary>
    /// <param name="identifier">An identifier unique to this application.       </param>

    public SingleInstance(Guid identifier)
    {
        this.identifier = identifier;
        mutex = new Mutex(true, identifier.ToString(), out ownsMutex);
    }

    /// <summary>
    /// Indicates whether this is the first instance of this application.
    /// </summary>
    public Boolean IsFirstInstance
    { get { return ownsMutex; } }

    /// <summary>
    /// Passes the given arguments to the first running instance of the     application.
    /// </summary>
    /// <param name="arguments">The arguments to pass.</param>
    /// <returns>Return true if the operation succeded, false otherwise.    </returns>

    public Boolean PassArgumentsToFirstInstance(String[] arguments)
    {
        if (IsFirstInstance)
            throw new InvalidOperationException("This is the first instance.");

        try
        {
            using (NamedPipeClientStream client = new NamedPipeClientStream(identifier.ToString()))
            using (StreamWriter writer = new StreamWriter(client))
            {
                client.Connect(200);

                foreach (String argument in arguments)
                    writer.WriteLine(argument);
            }
            return true;
        }
        catch (TimeoutException)
        { } //Couldn't connect to server
        catch (IOException)
        { } //Pipe was broken

        return false;
    }

    /// <summary>
    /// Listens for arguments being passed from successive instances of the applicaiton.
    /// </summary>
    public void ListenForArgumentsFromSuccessiveInstances()
    {
        if (!IsFirstInstance)
            throw new InvalidOperationException("This is not the first instance.");
        ThreadPool.QueueUserWorkItem(new WaitCallback(ListenForArguments));
    }

    /// <summary>
    /// Listens for arguments on a named pipe.
    /// </summary>
    /// <param name="state">State object required by WaitCallback delegate.</param>
    private void ListenForArguments(Object state)
    {
        try
        {
            using (NamedPipeServerStream server = new NamedPipeServerStream(identifier.ToString()))
            using (StreamReader reader = new StreamReader(server))
            {
                server.WaitForConnection();

                List<String> arguments = new List<String>();
                while (server.IsConnected)
                    arguments.Add(reader.ReadLine());

                ThreadPool.QueueUserWorkItem(new WaitCallback(CallOnArgumentsReceived), arguments.ToArray());
            }
        }
        catch (IOException)
        { } //Pipe was broken
        finally
        {
            ListenForArguments(null);
        }
    }

    /// <summary>
    /// Calls the OnArgumentsReceived method casting the state Object to String[].
    /// </summary>
    /// <param name="state">The arguments to pass.</param>
    private void CallOnArgumentsReceived(Object state)
    {
        OnArgumentsReceived((String[])state);
    }
    /// <summary>
    /// Event raised when arguments are received from successive instances.
    /// </summary>
    public event EventHandler<ArgumentsReceivedEventArgs> ArgumentsReceived;
    /// <summary>
    /// Fires the ArgumentsReceived event.
    /// </summary>
    /// <param name="arguments">The arguments to pass with the ArgumentsReceivedEventArgs.</param>
    private void OnArgumentsReceived(String[] arguments)
    {
        if (ArgumentsReceived != null)
            ArgumentsReceived(this, new ArgumentsReceivedEventArgs() { Args = arguments });
    }

    #region IDisposable
    private Boolean disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (mutex != null && ownsMutex)
            {
                mutex.ReleaseMutex();
                mutex = null;
            }
            disposed = true;
        }
    }

    ~SingleInstance()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}
private static void Main()
    {
        Guid guid = new Guid("{6EAE2E61-E7EE-42bf-8EBE-BAB890C5410F}");



        //SingleInstance ensures only 1 instance of the app runs at one time. If another instance is started
        //it will be closed. If the 2nd instance included arguments these will be passed to 
        //the singleInstance_ArgumentsReceived event for originally running process
        using (SingleInstance singleInstance = new SingleInstance(guid))
        {
            //MessageBox.Show(Environment.GetCommandLineArgs().ToString());
            //if (Environment.GetCommandLineArgs().Contains("RunAsAdmin"))

                //MessageBox.Show("YES");

            if (singleInstance.IsFirstInstance || Environment.GetCommandLineArgs().Contains("RunAsAdmin"))
            {                 
                singleInstance.ArgumentsReceived += singleInstance_ArgumentsReceived;
                singleInstance.ListenForArgumentsFromSuccessiveInstances();

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                // Show the system tray icon.                   
                //using (ProcessIcon pi = new ProcessIcon())
                using (ProcessIcon pi = new ProcessIcon())
                {
                    //Use to pass instance of ProcessIcon to LyncPresenceSwitcher
                    lyncPresenceSwitcher.processIcon = pi;

                    //Pass Lync instance
                    pi.lync = lyncClientController;

                    pi.Display();

                    // Make sure the application runs!
                    Application.Run();
                }
            }
            else
                singleInstance.PassArgumentsToFirstInstance(Environment.GetCommandLineArgs());
        }
    }

    //Process arguments past with app execution
    private static void singleInstance_ArgumentsReceived(object sender, ArgumentsReceivedEventArgs e)
    {
        if (settingsBox == null)
            return;

        foreach (String arg in e.Args)
        {
            //if arguments include OpenSettings open SettingsBox
            if (arg == "OpenSettings")
            {
                settingsBox.ShowDialog();
            }

            if (arg == "RunAsAdmin")
            {
                //singleInstance.Dispose();

            }

        }
    }
应用程序检查设置是否需要管理员访问权限,并在需要时提示用户以管理员身份重新启动。要重新启动应用程序,请运行以下命令:

 if (!IsRunAsAdmin())
        {
            // Launch itself as administrator
            ProcessStartInfo proc = new ProcessStartInfo();
            proc.UseShellExecute = true;
            proc.WorkingDirectory = Environment.CurrentDirectory;
            proc.FileName = Application.ExecutablePath;
            proc.Verb = "runas";
            proc.Arguments = "RunAsAdmin";

            try
            {

                Process.Start(proc);
                System.Environment.Exit(2);

                return true;

            }
            catch
            {
                // The user refused the elevation.
                // Do nothing and return directly ...
                return false;
            }
问题是一个新实例启动后由于互斥而关闭。然后,当我关闭原始实例时,我得到以下结果:

所以我想我可以向正在运行的实例传递一个参数,告诉它允许生成一个新实例,然后关闭原始实例。问题是我想不出如何使它工作

如有任何帮助,我们将不胜感激:

p、 我是C级新手


谢谢

解决方案是在重新启动应用程序之前销毁互斥锁:

mutex.Dispose();

互斥锁是在非公共程序中调用的,因此当前无法从尝试以管理员身份重新启动的类中访问它。从程序中公开它可以吗?我试着公开它,但它说代码不是启发式的不可访问的Program.singleInstance.Dispose;