Delphi 如何在内存中设置/检测/删除其他进程可以看到的全局标志?

Delphi 如何在内存中设置/检测/删除其他进程可以看到的全局标志?,delphi,delphi-xe2,Delphi,Delphi Xe2,在Delphi XE2中,如何在内存中设置一个特定的全局标志,该标志可以被其他进程看到,并且在创建全局标志的进程终止时不会被删除。例如: if GlobalAddAtom('{B244A213-72EC-47BF-814B-2E7608F55C50}') <> 0 then MessageDialog('GlobalFlag has been created'); 1) 过程A: if CreateGlobalFlag('{B244A213-72EC-47BF-814B-2E7

在Delphi XE2中,如何在内存中设置一个特定的全局标志,该标志可以被其他进程看到,并且在创建全局标志的进程终止时不会被删除。例如:

if GlobalAddAtom('{B244A213-72EC-47BF-814B-2E7608F55C50}') <> 0 then
  MessageDialog('GlobalFlag has been created');
1) 过程A:

if CreateGlobalFlag('{B244A213-72EC-47BF-814B-2E7608F55C50}') then
  MessageDialog('GlobalFlag has been created');
2) ProcessA终止

3) 过程B:

boolGlobalFlagExists := IsGlobalFlagSet('{B244A213-72EC-47BF-814B-2E7608F55C50}');
if boolGlobalFlagExists then 
begin
  if RemoveGlobalFlag('{B244A213-72EC-47BF-814B-2E7608F55C50}') then
    MessageDialog('GlobalFlag has been removed');
end;
不知道上述GUID的其他进程应该无法检测此全局标志

如何实现这样的功能

EDIT201406231757:
如果可能,全局标志应存在于内存中。
如果可能的话,该标志应一直有效,直到Windows关闭。
如果可能,全局标志应为每台机器(而不是每用户)。
全局标志应在关机时消失。
如果可能的话,全局标志应该是秘密的。

您可以使用全局原子将内存中的标志保留到进程的生存期之后

:

只要字符串atom的引用计数大于零,即使在将其放入表中的应用程序终止后,字符串atom的原子名仍保留在全局atom表中

例如:

if GlobalAddAtom('{B244A213-72EC-47BF-814B-2E7608F55C50}') <> 0 then
  MessageDialog('GlobalFlag has been created');
如果GlobalAddAtom({B244A213-72EC-47BF-814B-2E7608F55C50})为0,则
MessageDialog(“已创建GlobalFlag”);

var
GlobalFlag:原子;
开始
GlobalFlag:=GlobalFindAtom(“{B244A213-72EC-47BF-814B-2E7608F55C50}”);
如果GlobalFlag为0,则
开始
SetLastError(0);
GlobalDeleteAtom(GlobalFlag);
如果GetLastError()=0,则
MessageDialog('GlobalFlag已删除');
结束;
请记住,全局原子表是一个有限的资源。它一次只能容纳少于16K个原子,这些原子用于其他全局资源,如注册的剪贴板格式。所以要少用原子


此外,不可预见的情况,如资源管理器/会话崩溃,可能会擦除全局atom表,从而丢失您的标志。

我之前玩过atoms,注意到问题得到了回答:

program TestAtoms;

{$APPTYPE CONSOLE}

uses
  Windows;

const
  AtomName = 'bla-bla-bla-bla-bla-bla-bla';

var
  AtomValue: TAtom;

procedure Test;
begin
  AtomValue:= GlobalFindAtom(PChar(AtomName));
  if AtomValue = 0 then begin
    Writeln('Atom not found, creating');
    AtomValue:= GlobalAddAtom(PChar(AtomName));
    if AtomValue <> 0 then
      Writeln('Atom created, ', AtomValue)
    else
      Writeln('Atom create failed !!!');
  end
  else begin
    Writeln('Atom found, deleting');
    SetLastError(ERROR_SUCCESS);

    GlobalDeleteAtom(AtomValue);
    if GetLastError = ERROR_SUCCESS then
      Writeln('Atom deleted')
    else
      Writeln('Atom delete failed !!!');
  end;
end;

begin
  Test;
  Readln;
end.

与其使用Atom表,不如使用易失性注册表项。有关详细信息,请参阅文档。
REG\u选项\u VOLATILE
将创建一个仅在内存中维护的项,并在卸载相关注册表配置单元时丢弃该项

因此,如果使用
RegCreateKeyEx
HKEY\U LOCAL\U机器
键中创建一个
REG\u选项
键,该键将一直保留到机器关闭

如果确实需要对内容保密,可以保护注册表项,以确保只有某些用户或组可以读取其内容


这应该满足您列出的所有要求。

在公用文件夹中创建一个具有此名称的空文件;或具有此名称的注册表项;很多解决方案都是可能的。你想让国旗挂在哪里?它的一生是什么?永远。直到另一个进程关闭。是每用户还是每台机器?当用户注销时它会死掉吗?关闭?你想把国旗放在哪里?在内存中,如果可能的话它的一生是什么?如果可能的话,直到Windows关闭是每用户还是每台机器?每台机器,如果可能的话。它在关机时死亡。@user246408全局标志应该是机密的。可以检测到公用文件夹中的文件。它不是机密文件。如果其他程序可以读取,那么其他程序也可以读取。如果让进程A在进程B启动之前终止,我看不出您将如何将其保存在内存中和磁盘之外。也许您需要进程C一直运行并充当中间人。您是否有修改设计的余地,或者您是否已经决定修改,并且无法灵活地进行更改。非常感谢Remy Lebeau和user246408提供了此ATOM解决方案!!谢谢你的更新信息。但是,攻击者可以从匿名GUID中获得哪些信息?他可以追溯到我的应用程序吗?@user我们很难在不知道您的要求的情况下就安全性向您提供建议。@DavidHeffernan我没有让user246408向我提供一般性建议,而是专门问他是否有人可以从Atom项中获得Atom项的创建者。
procedure ScanAtomTable;
var
  nAtom: TAtom;
  Buffer: array[0..1023] of Char;
  Size: Cardinal;
  S: string;

begin
  nAtom:= $C000;
  repeat
    Size:= GlobalGetAtomName(nAtom, @Buffer, 1024);
    if Size > 0 then begin
      S:= PChar(@Buffer);
      Writeln(S);
    end;
    Inc(nAtom);
  until nAtom = 0;
end;