【问题标题】:Mutex opened in Delphi application checked in C# console application在 C# 控制台应用程序中检查的 Delphi 应用程序中打开的互斥锁
【发布时间】:2018-06-19 13:03:17
【问题描述】:

我正在启动一个 Delphi 应用程序并为它创建一个互斥锁,如下所示:

var
  AMutex: THandle;

function OpenMutex(const AMutexName: String): Boolean;
begin

  { Assume the Windows Mutext is already open }
  Result := False;

  { Is the Mutex already open? }
  if AMutex <> 0 then
    exit;

  { Try to create Windows Mutex }
  if CreateProgramMutex( AMutexName , AMutex) then
    Result := True
  else
    AMutex := 0;
end;

 function CreateProgramMutex( AMutexName: string; var AMutex: THandle ): boolean;
begin
    { Assume the new program mutex was created successfully. }
    Result := true;

    { Attempt to create a new mutex. }
    AMutex := CreateMutex(nil, False, PChar(AMutexName));

    { If we at least got a handle to the mutex... }
    if (AMutex <> 0) then
    begin

      if GetLastError = ERROR_ALREADY_EXISTS then begin
        { Close the handle, since it already exists. }
        CloseHandle(AMutex);

        { Set the return to show that it was already running. }
        Result := false;
      end;
    end else
      Result := false;
end;

我正在尝试从 C#(作为初学者)找出我的应用程序是否已经在控制台应用程序中运行:

using System;
using System.Threading;

namespace ConsoleApplication1
{
    class OneAtATimePlease
    {
        private static Mutex _mutex;

        private static bool IsSingleInstance()
        {
            _mutex = new Mutex(false, "my mutex name");

            // keep the mutex reference alive until the normal 
            //termination of the program
            GC.KeepAlive(_mutex);

            try
            {
                return _mutex.WaitOne(0, false);
            }
            catch (AbandonedMutexException)
            {
                // if one thread acquires a Mutex object 
                //that another thread has abandoned 
                //by exiting without releasing it

                _mutex.ReleaseMutex();
                return _mutex.WaitOne(0, false);
            }
        }
        static void Main()
        {
            if (!IsSingleInstance())
                Console.WriteLine("already running");
            Console.ReadLine();

        }
    }
}

即使 Delphi 应用程序正在运行,IsSingleInstance 也会返回 true。使用相同的 Delphi 代码检查 Delphi 控制台应用程序中的互斥锁是有效的。我确信这很明显,但我无法弄清楚我做错了什么。

PS:一切都在同一个 Windows 用户会话下完成

【问题讨论】:

  • 我们看不到您的代码。除了您之外,没有人知道CreateProgramMutex 背后的内容。或者AMutex 是什么。 minimal reproducible example.
  • 我添加了 Delphi 实现的缺失部分。
  • 您是否创建了全局互斥锁?您还需要添加一个安全描述符,以便其他进程可以访问它...
  • @whosrdaddy - 不。所有代码都在问题中。我明白这一点,但为什么我从另一个控制台 Delphi 应用程序看到我的互斥锁具有相同的代码,但不能从 c# 控制台应用程序做到这一点?以及为什么它应该是全球性的,因为我在同一个会话中使用它。全局性将在服务器的所有会话中可用,我不希望这样
  • 不用担心 :) 我只是想说。如果您的 Delphi 应用程序从未获得互斥锁的所有权,则它的状态保持信号状态(直到某个其他线程获得它的所有权,这可能是不好的情况)。这就是为什么您的监控应用程序总是从WaitOne 电话中收到积极的结果。

标签: c# .net delphi c#-4.0 delphi-10.1-berlin


【解决方案1】:

您说您的目标是检查外部应用程序是否正在运行(通过使用命名互斥锁)。好吧,对于这种情况,您不应尝试在应用程序中创建给定名称的互斥对象,而只能尝试打开此类对象。原因很简单,如果那个外来的应用程序使用这样的互斥锁来检查它是否自己运行,你实际上会为你的应用窃取这个互斥锁,而那个外来的应用程序永远不会启动。

为了您的目的,请使用TryOpenExisting 类函数。例如:

using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Mutex mutex;

            if (Mutex.TryOpenExisting("My unique mutex name", out mutex)) {
                try {
                    // with the used TryOpenExisting overload you can work with
                    // the mutex object here; you can wait for it or release
                    Console.WriteLine("Application is running!");
                }
                finally {
                    mutex.Close();
                }
            }
            else {
                Console.WriteLine("Application is NOT running!");
            }
            Console.ReadLine();
        }
    }
}

【讨论】:

    【解决方案2】:

    我认为您需要检查互斥锁是否存在或已创建。

    Mutex appMutex = new Mutex(true, "MyMutex", out exclusive);
    if (!exclusive)
    {
      //Instance already existed
    }
    

    【讨论】:

    • 我试过了。我总是得到相同的结果,即使应用程序是否正在运行。
    • 您在测试时是否以同一用户身份登录?
    • 是的。是同一个用户会话。在另一个测试控制台应用程序中使用相同的 Delphi 代码是有效的。我无法完成的是让它在 C# 控制台应用程序中工作。
    • @RBA,这是正确答案和this is what C# returns in this parameter
    • @Victoria - 感谢您的参考,您是否设法制作了一个小示例?因为我不能,我也不知道为什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多