我有两个程序A.exe和B.exeA.exe执行CreateSemaphore(nil,0,5,'1122334455'); //创建一个信号机那么系统里现在有一个 1122334455 的信号机,我用工具已经看到了.
我如何用B.exe来关闭这个1122334455信号机呢?我用工具可以关闭...
我用了ReleaseSemaphore和CloseHandle都不行呢,请给代码另外必须是两个程序,A:创建信号,B:关闭信号,我知道同一个进程是可以关闭的!

解决方案 »

  1.   

    任何进程都可以用opensemaphore来得到一个已经存在的信号量的句柄,具体参数可以看看msdn。
    你在b.exe先用这个函数得到信号量的句柄然后在用releasesemaphore释放。
      

  2.   

    我不太明白你说的这个“关闭”是什么意思?是删除信号量这个对象吗?还是其他的什么意思?
    如果你指的是删除信号量对象的话,你就得用CloseHandle关闭信号量的所有句柄。它的所有句柄都关闭以后,对象自己也会删除。所以你需要在b中枚举所有内核对象然后找到你需要关闭的。
    关于枚举内核对象的大多是vc的需要自己翻译成delphi。以下两个各自参考下:
    http://topic.csdn.net/u/20100209/22/43678cfa-0716-4936-96eb-2300a22ed533.html
    http://topic.csdn.net/u/20100331/05/b19406e0-20d3-44a6-bae2-e91b637eb8bc.html
      

  3.   

    是的,删除这个信号量,让这个信号量'1122334455'不存在.我还以为可以跨进程直接删除呢,还要枚举所有内核对象...
    VC的实在看不懂,求会的列一下代码,DELPHI的
      

  4.   

    有个笨方法:
    在A放个时钟,用来判断运行的条件是否而在,如:外部一个文件或一个外部的变量,用B来改变外部文件或变量。A就会自动响应了。      如我在A运行时自动建立一个名字为C.txt的文件,然后在A的时钟里判断C是否存在,如C不存在就退出。
    在B程序中只要删除C.txt就可以了。抛砖引玉。
      

  5.   

    信号量是可以跨进程同步的
    LZ还是把代码贴出来吧,这么猜没谱了,不过你的ReleaseSemaphore执行成功了么?
    If the function succeeds, the return value is nonzero.
    If the function fails, the return value is zero. To get extended error information, call GetLastError.
      

  6.   

    例子可以看这里
    http://www.cnblogs.com/del/archive/2011/07/19/1390747.html
      

  7.   

    楼主是想删除信号量这个内核对象,ReleaseSemaphore只是将信号量计数增加了而已并没有关闭信号量。
      

  8.   

    ReleaseSemaphore实际上是减少引用计数,呵呵,另外我给他的那个例子链接里最后一句写了啊
    “4、最后, 作为系统内核对象, 要用 CloseHandle 关闭.”
    而这个方法不用我贴代码了吧,就一个参数,囧.............
      

  9.   

    BOOL WINAPI CloseHandle(
      __in  HANDLE hObject
    );另外,之所以LZ关闭不成功,我觉得应该先检查下在另一个进程里获取是否成功,然后判断closehandle的返回值,查看下错误代码,所以开始我才说把代码贴出来看下嘛,这么猜不靠谱啊
      

  10.   

    B进程里获取成功了也仅仅是内核对象计数增加1,CloseHandle获取到的句柄只是让内核对象计数减1,内核对象计数为0的时候才会被删除。
    A进程调用CreateSemaphore成功后,信号量内核对象计数应该已经是1了,然后B.exe去获取信号量句柄成功后,内核对象计数为2,在B.exe中调用CloseHandle成功内核对象计数又变为1,所以才会出现删除不成功,除非把A.exe中也调用CloseHandle或是结束A进程,要么就是枚举内核对象根据名称找到需要关闭的,然后CloseHandle关闭它。
    我想楼主用的那个工具就应该是枚举指定进程中的内核对象。
      

  11.   

    晕死,记错了,确实是增加计数
    Increases the count of the specified semaphore object by a specified amount.
      

  12.   

    信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。这么久以来我一直当成了创建增加引用计数,释放减少引用计数,囧...........多亏了14L兄台
      

  13.   

    呵呵,还是有一点咱两说岔路了
    Realease增加的是信号量的资源计数器,CreateSemaphore第二个参数指定资源计数器初始化多少个资源可利用。
    另外CreateSemaphore创建一个信号量成功后,该信号量内核对象的使用计数是1,当使用OpenSemaphore成功时候内核计数器就会增加1.
    PS:内核对象的使用计数:
    如果你的进程调用了一个创建内核对象的函数,然后你的进程终止运行,那么内核对象不一定被撤消。因为此时内核对象可能被其它进程使用着。内核对象的存在时间可以比创建该对象的进程长。
    每个内核对象包含一个使用计数(有点像COM的引用计数)。当一个对象刚刚创建时,它的使用计数被置为1 。然后,当另一个进程访问一个现有的内核对象时,使用计数就递增1 。当进程终止运行时,内核就自动确定该进程 仍然打开的所有内核对象的使用计数。如果内核对象的使用计数降为0 ,内核就撤消该对象。这样可以确保在没有进程引用该对象时系统中不保留任何内核对象。
    (PS内容摘自http://www.cnblogs.com/fangyukuan/archive/2010/08/31/1813125.html
      

  14.   

    我这么说吧,A程序不是我的,但是A程序利用信号量来限制程序多开,
    所以我要干掉A程序的这个信号量.只能枚举A程序的所有内核对象了么?
    还有,to m617105,你那两个贴子我看了, 确实有个翻译的,但是我测试了不能用.C代码也看不懂
      

  15.   

    还有就是,创建信号量只有 CreateSemaphore 这个API吗?不知道为什么,我HOOK了A程序的CreateSemaphore,然后却没有看到他创建112233445,不知道为什么.难道还有别的API可以创建信号量吗?
    还有,中秋快乐,谢谢
    ps. CreateSemaphore CreateSemaphoreA CreateSemaphoreW 我都HOOK过,没有创建112233445的信号量,但是我用工具XueTr确看到了创建了这个1122334455的信号量,XueTr可以把这个信号量删除,然后我就可以多开A程序了
      

  16.   

    限制程序多开不仅是信号量,mutex也可以的
      

  17.   

    回楼上的,我说的A.exe是用的信号量
      

  18.   

    用XueTr工具看的,如下图,我用createsemaphore(nil,0,5,'1122334455');这一句创建了信号量,
      

  19.   

    To m617105  实在麻烦了,要是解决不了就算了,中秋快乐
      

  20.   

    创建信号量只有这个api,或者LZ做个测试吧,ReleaseSemaphore是允许多次调用的,直到抛异常ArgumentOutOfRangeException
    releaseCount 小于 1。Lz如果能正确取到信号量的句柄,ReleaseSemaphore也能正常执行,那就多次执行ReleaseSemaphore直到该异常抛出,然后再试试能不能多开
     
      

  21.   


    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    type
       UNICODE_STRING = record
         Length: Word;
         MaximumLength: Word;
         Buffer: PWideChar;
    end;
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      hSemaphore:THandle;
    implementation{$R *.dfm}
    procedure EumKnlObjectName(var sList:TStringList);
    type
      PObjectTypeInformation = ^TObjectTypeInformation;
      TObjectTypeInformation = packed record
        Name: string;
        ObjectCount, HandleCount: Cardinal;
        Reserved1: array[0..3] of Cardinal;
        PeakObjectCount, PeakHandleCount: Cardinal;
        Reserved2: array[0..3] of Cardinal;
        InvalidAttributes: Cardinal;
        GenericMapping: TGenericMapping;
        ValidAccess: Cardinal;
        Unknown: UCHAR;
        MaintainHandleDatabase: Boolean;
        Reserved3: array[0..1] of UCHAR;
        PoolType: Cardinal;
        PagedPoolUsage, NonPagedPoolUsage: Cardinal;
      end;  POBJECT_ALL_TYPES_INFORMATION = ^TOBJECT_ALL_TYPES_INFORMATION;
      TOBJECT_ALL_TYPES_INFORMATION = record // Information Class 3
        NumberOfTypes: DWORD;
        TypeInformation: TObjectTypeInformation;
      end;  TOBJECT_INFORMATION_CLASS = (
        ObjectBasicInformation,
        ObjectNameInformation,
        ObjectTypeInformation,
        ObjectAllTypesInformation,
        ObjectHandleInformation);  PObjectNameInformation = ^TObjectNameInformation;
      TObjectNameInformation = packed record
        Name: UNICODE_STRING;
      end;  PSystemHandleInformation = ^TSystemHandleInformation;
      TSystemHandleInformation = packed record
        ProcessId: DWORD;
        ObjectTypeNumber: Byte;
        Flags: Byte;
        Handle: Word;
        eObject: Pointer;
        GrantedAccess: ACCESS_MASK;
      end;  PSystemHandleInformation_Ex = ^TSystemHandleInformation_Ex;
      TSystemHandleInformation_Ex = packed record
        NumberOfHandles: DWORD;
        Information: TSystemHandleInformation;
      end;  PNtQuerySystemInformation = function(SystemInformationClass: DWORD; SystemInformation: Pointer; SystemInformationLength: ULONG; ReturnLength: PULONG): DWORD; stdcall;  PNtQueryObject = function(ObjectHandle: THANDLE;
        ObjectInformationClass: TOBJECT_INFORMATION_CLASS;
        ObjectInformation: Pointer;
        ObjectInformationLength: DWORD;
        ReturnLength: PDWORD): DWORD; stdcall;
    var
      _ModuleHandle, _Count, i: Dword;
      _NtQueryObject: PNtQueryObject;
      _ObjTypeInfo: POBJECT_ALL_TYPES_INFORMATION;
      _P, _StrLen, _Size: DWORD;
      _ObjName: string;
      _NtQuerySystemInformation: PNtQuerySystemInformation;
      pHandleInfor: PSystemHandleInformation_Ex;
      _HandleInfor: PSystemHandleInformation;
      _Name: PObjectNameInformation;
    begin  _Count := 0;
      _ModuleHandle := GetModuleHandle('ntdll.dll');
      _NtQueryObject := GetProcAddress(_ModuleHandle, 'NtQueryObject');
      _NtQuerySystemInformation := GetProcAddress(LoadLibrary('ntdll.dll'), 'NtQuerySystemInformation');
      _Size := $1000;
      GetMem(pHandleInfor, _Size);
      while _NtQuerySystemInformation(16, pHandleInfor, _Size, nil) <> 0 do
      begin
        _Size := _Size + _Size;
        ReallocMem(pHandleInfor, _Size);
      end;
      _Name := GetMemory($1000);
      for I := 0 to pHandleInfor^.NumberOfHandles - 1 do
      begin
        _HandleInfor := PSystemHandleInformation(dword(pHandleInfor) + 4 + (i * SizeOf(TSystemHandleInformation)));
        if (_HandleInfor^.ProcessId = GetCurrentProcessId) then
        begin
          if _NtQueryObject(_HandleInfor^.Handle, ObjectNameInformation, _Name, $1000, nil) = 0 then
          begin
            _ObjName := WideCharToString(_Name.Name.Buffer);
            sList.Add(IntToHex(Dword(_HandleInfor^.Handle), 8) + '-' + IntToStr(_HandleInfor^.ObjectTypeNumber) + ':' + _ObjName);
          end;
        end;
      end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      test:TStringList;
    begin
      hSemaphore:=CreateSemaphore(nil,0,5,'1122334455');
      ShowMessage(IntToStr(GetLastError));
      test:=TStringList.Create;
      EumKnlObjectName(test);
      ShowMessage(IntToStr(GetLastError));
      Memo1.Lines.Assign(test);
    end;
    end.部分运行截图如下: