Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法防止Delphi应用程序在不启用运行时主题的情况下在Vista/Win 7上使用虚拟存储?_Delphi - Fatal编程技术网

有没有办法防止Delphi应用程序在不启用运行时主题的情况下在Vista/Win 7上使用虚拟存储?

有没有办法防止Delphi应用程序在不启用运行时主题的情况下在Vista/Win 7上使用虚拟存储?,delphi,Delphi,这个问题几乎说明了一切 如果启用了运行时主题,我有一个带有旧组件的应用程序无法正常工作。但如果我不启用它们,应用程序最终总是会弄乱虚拟商店 谢谢 更新: 使用下面Mark的解决方案,应用程序不再写入虚拟存储。但是,现在它无法访问它所需要的tdb文件(微小的数据库文件)。此tdb文件与写入虚拟存储的文件相同。关于如何让它访问tdb文件,并且仍然阻止写入虚拟存储,有什么想法吗 您需要向exe添加清单(资源) 清单中有一个XML资源,其内容类似于下面的内容。TrustInfo是导致不使用Virtual

这个问题几乎说明了一切

如果启用了运行时主题,我有一个带有旧组件的应用程序无法正常工作。但如果我不启用它们,应用程序最终总是会弄乱虚拟商店

谢谢

更新:


使用下面Mark的解决方案,应用程序不再写入虚拟存储。但是,现在它无法访问它所需要的tdb文件(微小的数据库文件)。此tdb文件与写入虚拟存储的文件相同。关于如何让它访问tdb文件,并且仍然阻止写入虚拟存储,有什么想法吗

您需要向exe添加清单(资源)

清单中有一个XML资源,其内容类似于下面的内容。TrustInfo是导致不使用VirtualStore的关键部分

此示例引用了Microsoft.Windows.Common-Controls程序集,该程序集启用运行时主题。如果您从清单中删除它,您仍然可以保留TrustInfo部分

Vista使用TrustInfo确定应用程序“知道”UAC限制,而不将VirtualStore用于该应用程序

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="Delphi 7"
    version="7.1.0.0" 
    processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</assembly> 

以及应用程序清单架构上的Microsoft页面:

当然,一旦执行此操作,在UAC打开的情况下,您将无法再将数据写入c:\program files\或其他受保护的位置。这就是微软最初创建虚拟商店的原因。它旨在使旧应用程序保持运行,以便能够写入这些(现在受保护的)位置

您有几个不同的选择:

1:更改文件位置

将tdb文件移动到其他位置。这是一种理想的情况,但可能需要更改最多的代码。有关一些建议,请参见问题“”。Microsoft建议将用户未命名的数据存储在“应用程序数据”文件夹下。我尝试过这个方法,但这让用户很难找到数据并将其移动到另一台计算机。我已将所有用户数据(即使用户未专门保存该文件)移动到“我的文档”文件夹中。这样一来,当他们得到一台新电脑时,他们就可以移动“我的文档”(大多数都可以),我的所有应用程序数据也会移动

2:更改文件的权限,以允许标准用户读取/写入文件。您的安装程序可以这样做,或者您可以在事后对其进行更新,但您需要以管理员身份运行才能进行更改

3:强制应用程序以管理员身份运行。如果按照Sertac的说明将执行级别设置为“requireAdministrator”,则可以写入文件,但用户每次运行应用程序时都会收到UAC提升提示

还请注意,如果您正在升级一直在运行并将数据保存到虚拟存储的用户,则不会自动将数据移动到新位置。将清单添加到应用程序后,它将开始看到实际位于c:\program files*下的文件。您可能需要在虚拟存储中查找文件,并将其复制到用户的新位置。下面是一个例子。在我的例子中,许可证文件存储在安装目录下。升级应用程序后,我需要查找旧许可证文件并将其移动到新位置:

procedure TResetMain.CopyVirtFiles();
var
  VirtLicDir: string;
  NewLicDir: string;
  FileOp: TSHFileOp;

  TempPath : array[0..MAX_PATH] of Char;
begin


  SHGetFolderPath(Application.Handle, CSIDL_LOCAL_APPDATA, 0, 0, TempPath);
  VirtLicDir := TempPath + '\VirtualStore\Program Files\My Company\Licenses';

  NewLicDir := GetMyConfigDir();
  if NewLicDir <> '' then
  begin
    NewLicDir := IncludeTrailingPathDelimiter(NewLicDir) + 'User Licenses';
  end;

  // If the Virtual license directory exists but not the new directory we
  // know this is the first time the updated application has been run
  // and we need to move the files to the correct location.
  if DirectoryExists(VirtLicDir) and Not DirectoryExists(NewLicDir) then
  begin
    ForceDirectories(NewLicDir);

    FileOp := TSHFileOp.Create(nil);

    FileOp.FileList.Add(VirtLicDir + '\*.*');
    FileOp.Destination := NewLicDir;

    FileOp.Action := faMove;
    FileOp.SHOptions := [ofFilesOnly, ofNoConfirmation, ofNoConfirmMKDir, ofRenameOnCollision, ofSilent];
    FileOp.Execute;

    FreeAndNil(FileOp);
  end;

end;
过程TResetMain.CopyVirtFiles();
变量
VirtLicDir:字符串;
NewLicDir:字符串;
FileOp:TSHFileOp;
TempPath:字符的数组[0..MAX_PATH];
开始
SHGetFolderPath(Application.Handle,CSIDL_LOCAL_APPDATA,0,0,TempPath);
VirtLicDir:=TempPath+'\VirtualStore\Program Files\My Company\Licenses';
NewLicDir:=GetMyConfigDir();
如果NewLicDir为“”,则
开始
NewLicDir:=IncludeTrailingPathDelimiter(NewLicDir)+“用户许可证”;
结束;
//如果虚拟许可证目录存在,但新目录不存在,则
//知道这是第一次运行更新的应用程序
//我们需要将文件移动到正确的位置。
如果存在目录(VirtLicDir)而不存在目录(NewLicDir),则
开始
ForceDirectories(NewLicDir);
FileOp:=TSHFileOp.Create(nil);
FileOp.FileList.Add(VirtLicDir+'\*.*');
FileOp.Destination:=NewLicDir;
FileOp.Action:=faMove;
FileOp.SHOptions:=[OfficeOnly、OfNoconfirm、OfNoconfirmkDir、OfNameOnCollision、ofSilent];
FileOp.Execute;
FreeAndNil(FileOp);
结束;
结束;

马克的一些替代方案

  • 右键单击并选择“以管理员身份运行”
  • 修改应用程序的兼容性属性,以包括“以管理员身份运行此程序”
  • 重命名可执行文件,使其包含“安装”、“更新”、“安装”、“修补程序”等词语之一
  • 在版本信息中包含上述词语之一,例如将“Internal Name”设置为“MyApplication install”。细节
  • 如果UAC对话框或运行提升版不可接受,请修改应用程序需要写入的文件夹或文件的权限。例如,如果组件正在“MyApplication\Logs”上删除日志文件,请在“Logs”上设置安全性,以便“Everyone”可以“完全控制”文件夹。不要忘记删除“.\AppData\VirtualStore\Program Files\MyApplication\Logs”以使其生效

不确定您称之为虚拟存储。你是说虚拟存储以及访问注册表和文件夹时出现问题吗?是的,我的意思是虚拟存储……我不明白视觉主题和虚拟存储是以何种方式关联的……不确定这种关系,但是启用了运行时主题的delphi应用程序将不会使用虚拟存储。@croceldon:不,这不是真的。任何试图将文件保存到C:\Program Files\目录(例如)的应用程序都会在不知不觉中写入C:\Users\\AppData\VirtualSt