【问题标题】:how to store settings in resource如何将设置存储在资源中
【发布时间】:2010-07-16 16:39:25
【问题描述】:

我正在尝试将一些设置存储在我的应用程序的资源中 但失败了 我不想使用 ini 文件或注册表方法 我正在使用此代码

    var
    data :string;

  procedure WriteSettings(ServerFile: string; Settings: string);
    var
     ResourceHandle: THandle;
     pwServerFile: PWideChar;
    begin
     GetMem(pwServerFile, (Length(ServerFile) + 1) * 2);
     try
       StringToWideChar(ServerFile, pwServerFile, Length(ServerFile) * 2);
       ResourceHandle := BeginUpdateResourceW(pwServerFile, False);
       UpdateResourceW(ResourceHandle, MakeIntResourceW(10), 'SETTINGS', 0, @Settings[1], Length(Settings) + 1);
       EndUpdateResourceW(ResourceHandle, False);
     finally
       FreeMem(pwServerFile);
     end;
    end;
    function ReadSettings(ServerFile: string): string;
    var
      ServerModule: HMODULE;
      ResourceLocation: HRSRC;
      ResourceSize: dword;
      ResourceHandle: THandle;
      ResourcePointer: pointer;
    begin
      ServerModule := LoadLibrary(pchar(ServerFile));
      try
        ResourceLocation := FindResource(ServerModule, 'SETTINGS', RT_RCDATA);
        ResourceSize := SizeofResource(ServerModule, ResourceLocation);
        ResourceHandle := LoadResource(ServerModule, ResourceLocation);
        ResourcePointer := LockResource(ResourceHandle);
        if ResourcePointer <> nil then
        begin
          SetLength(Result, ResourceSize - 1);
          CopyMemory(@Result[1], ResourcePointer, ResourceSize);
          FreeResource(ResourceHandle);
        end;
      finally
        FreeLibrary(ServerModule);
      end;
    end;
  procedure TForm1.saveClick(Sender: TObject);
begin
    writesettings(paramastr(0),'true');  
end;
 procedure TForm1.ReadClick(Sender: TObject);
begin
   data:=readsettings(paramstr(0));  
end;

 begin
   if data='true' then checkbox1.checked:=true;
 end

但是 nit 是否存储了我写入资源的内容 :( 还有其他更好的选择吗? 请帮忙

【问题讨论】:

  • if data:='true' then checkbox1.checked:=true;?也许你的意思是if data='true' then checkbox1.checked:=true;
  • 是的,很抱歉犯了错误
  • 请注意,具有常规用户权限的用户将无法在程序文件夹中写入文件。所以这对他们不起作用。从 Vista 开始使用 UAC,它甚至不适用于管理员,除非他们以提升的权限运行您的程序。
  • 嗯,谢谢先生的信息,但我的程序不是安装程序。无论如何,我正在我的 Windows XP Sp3 上尝试这个,但没有奏效:(
  • 听@Lars。如果您有任何想要在 Vista、Windows7 或更高版本上运行的用户,那么您注定要使用这种方法。除非您是安装程序,否则您不能修改任一“程序文件”文件夹中的任何文件。即除非关闭 UAC 或您以管理员身份运行,否则常规程序无法在那里写入。 IMO,您应该遵循已发布的开发者指南来存储设置。

标签: delphi


【解决方案1】:

The documentation for BeginUpdateResource 清楚地说明了您的代码不起作用的原因(已添加重点):

pFileName [in]

LPCTSTR

更新资源的二进制文件。应用程序必须能够获得对该文件的写访问权; pFileName 引用的文件当前无法执行。如果 pFileName 没有指定完整路径,则系统在当前目录中搜索文件。

如果您按照文档的建议检查 API 函数的返回值并在失败时调用 GetLastError,您可能已经能够自己推断出错误的原因。

您可以将设置存储在资源中,但不能将设置存储在您尝试存储其设置的程序的资源中。既然我们已经确定不允许您在程序本身中存储设置,那么您不妨放弃资源的想法并使用更传统的方法将设置存储在外部位置,例如注册表, INI 文件或其他文件。如果您发现外部位置还没有任何设置,您可能仍希望从资源中读取一组 默认 设置,这可能在全新安装后发生。

【讨论】:

    【解决方案2】:

    让您的程序自行修改是个坏主意。正如一些人已经指出的那样,在大多数情况下,这在 Vista 和 Win7 下会严重失败。最好不要和操作系统打架。 Windows 已经为您的程序提供了几种不同的方式来存储其设置。您可以将 INI 或其他配置文件放在 Program Files 之外的某个文件夹中,也可以将其存储在注册表中,这可能是最好的选择。

    【讨论】:

    • 通过“Program Files 之外的某个文件夹”,Mason Wheeler 表示“C:\Users\\AppData\Local\\\ ",其中第一部分(直到并包括“Local”)应通过 Windows API (msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx) 的SHGetFolderPath 函数动态获取。
    • 是的,基本上。如果您使用的是 Vista 或更高版本,那也是正确的方法。否则 SHGetFolderPath 会将您发送到其他地方。 (这就是为什么应该使用它而不是尝试对路径进行硬编码。)
    • “让你的程序自行修改是个坏主意”。同意。此外,这是高度可疑的行为,可能会被标记为恶意软件。让我想知道 DEP 或类似的东西是否会阻止他的代码首先工作?诚然,我跳进了“坏主意”的演讲,没有多看代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多