草庐IT

windows - 全局信号量忽略本地信号量

coder 2024-06-08 原文

我有一个访问某些文件和系统资源的应用程序,因此可能只有一个应用程序实例处于事件状态。这是通过创建一个命名的信号量并在已经分配信号量时停止应用程序运行来实现的。 过去(阅读:当 Windows XP 是最常见的操作系统时)运行良好,但现在我们注意到旧代码不适用于多个用户 session 。

这里是旧代码:

hInstanceSem := CreateSemaphore(nil, 0, 1, PChar(GetProductName(Application.ExeName)));
if (hInstanceSem <> 0) and (GetLastError = ERROR_ALREADY_EXISTS) then
// do not run the Application

所以我做了一些研究,了解了全局信号量并将代码更改为:

function CreateGlobalSemaphor(SemaphorName: String): Cardinal;
var
  desc: SECURITY_DESCRIPTOR;
  att : TSecurityAttributes;
  sem : Cardinal;
begin
  att.nLength := SizeOf(TSecurityAttributes);
  att.bInheritHandle := true;
  att.lpSecurityDescriptor := @desc;

  InitializeSecurityDescriptor(att.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(att.lpSecurityDescriptor, True, nil, False);

  sem := CreateSemaphore(@att, 0, 1, PChar('Global\' + SemaphorName));
  if (sem <> 0) and (GetLastError() <> ERROR_ALREADY_EXISTS) then begin
    Result := sem;
  end else begin
    Result := 0;
    CloseHandle(sem);
  end;
end;

if CreateGlobalSemaphor(GetProductName(Application.ExeName)) = 0 then
// do not run the Application

现在,当我在 User1 上启动应用程序时,更改为 User2 并尝试启动该应用程序,它不会运行(按预期)。

但是当我运行我的程序的旧版本并在同一个用户 session 中使用新代码启动当前版本时,新代码会忽略旧代码创建的信号量并启动我的应用程序的第二个实例。 (崩溃就不用说了。。。)

在我看来,局部信号量超出了全局信号量的范围,否则无法创建具有相同名称的第二个对象。 我的问题是:全局信号量(新代码)如何检测到已经分配了同名的本地信号量(旧代码)?

请记住,这是一个向后兼容的问题。我不能简单地重新编译和重新分发我的应用程序的旧版本。

最佳答案

kernel object namespaces 的文档解释说:

For processes started under a client session, the system uses the session namespace by default.

由于旧程序未明确包含 namespace ,因此使用 session namespace Local\。这意味着旧程序创建了一个名为 Local\xxx 的信号量。现在,新程序使用名为 Global\xxx 的信号量。所以你有两个不同的信号量,程序完全没有意识到自己。

  • 如果您希望新程序与旧程序进行交互,您必须使用名为Local\xxx 的对象。
  • 如果您希望新程序在不同的 session 中阻止其他新程序,您必须使用名为Global\xxx 的对象。

这里得出的明显结论是您需要创建两个对象。一个名为 Local\xxx,一个名为 Global\xxx

请注意,不可能将跨 session 排除反驳到现有程序中。他们已经在使用 Local\xxx 并且您现在无法更改它。

您还必须修复新代码中的错误处理。您调用 CreateSemaphore,然后继续调用 GetLastError,而没有先检查调用 CreateSemaphore 返回的值。

关于windows - 全局信号量忽略本地信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27226992/

有关windows - 全局信号量忽略本地信号量的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  3. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  4. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  6. c - mkmf 在编译 C 扩展时忽略子文件夹中的文件 - 2

    我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。

  7. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  8. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

    在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

  9. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  10. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

随机推荐