accesing registry lazarus / 34-Windows ---------------------------------------------------------------------- diego bertotti · 2021-05-10 19:41 hi i have a question, but is about delphi...i know, here is for lazarus, but maybe can help me reading win registry to know how many serial comm ports the machine have, i can do it successfully when executable is running from delphi ide, but when this exe run alone (dblclck on its name), it dont work! that's the piece of code, for very old delphi 2.0 and tested on old delphi 6 too, with the same results; Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var       l: TStringList;  reg: TRegistry;  n: integer;begin  l := TStringList.Create;  reg := TRegistry.Create;  try{$IFNDEF VER100}{$IFNDEF VER120}//    reg.Access := KEY_READ;{$ENDIF}{$ENDIF}  reg.RootKey := HKEY_LOCAL_MACHINE;    reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM', false);    reg.GetValueNames(l);    for n := 0 to l.Count - 1 do      Form3.Combobox1.Items.Add(reg.ReadString(l[n]));     ComboBox1.ItemIndex:= 0;  finally    reg.Free;    l.Free;  end;  can someone help me? ---------------------------------------------------------------------- mas steindorff · 2021-05-10 20:20 I do not know about Deiph anymore but you have old synaser code that may not work even for FPC. what I've had to do is to break up the loading of the reg, 1st into a tstringlist and then, 2nd: tstringlist into the combo box.  you should also note I use ..keyReadOnly  as well. Here is the same function originally written by "Lukas Gebauer" with my mods Code: [Select]function GetSerialPortNames: string; var   reg: TRegistry;   l  : TStringList;   n: integer; begin   l := TStringList.Create;   reg := TRegistry.Create;   try {$IFNDEF VER100}     reg.Access := KEY_READ; {$ENDIF}     reg.RootKey := HKEY_LOCAL_MACHINE;     reg.OpenKeyReadOnly('HARDWARE\DEVICEMAP\SERIALCOMM');//, false);     reg.GetValueNames(l);     Result := l.CommaText;   finally     reg.Free;     l.Free;   end; end; I do suggest you find the latest version of the synaser unit as there are some other  improvements as well.  I believe FPC comes with a version that was derived from this unit but I can't be sure. ---------------------------------------------------------------------- diego bertotti · 2021-05-10 20:48 stop the press! first, thanks for reply. now, the problem is not in the code. is about rights! if i run this exe alone but using "run like admin", then its works ---------------------------------------------------------------------- mas steindorff · 2021-05-10 20:58 you may wish to keep those presses running and think about WHY you need this admin rights ---------------------------------------------------------------------- diego bertotti · 2021-05-10 21:06 yes, i'm working on it, but if you have the answer, i'll be very happy if you share with us ---------------------------------------------------------------------- ASerge · 2021-05-11 02:36 Quote from: diego bertotti on May 10, 2021, 11:06:33 pmyes, i'm working on it, but if you have the answer, i'll be very happy if you share with us The problem is in the code. Read carefully, in the example from @[mas steindorff] it was TRegistry.OpenKeyReadOnly - it's safe. You use TRegistry.OpenKey - this requires the KEY_ALL_ACCESS rights. ---------------------------------------------------------------------- Bart · 2021-05-11 12:11 Quote from: ASerge on May 11, 2021, 04:36:02 amThe problem is in the code. Read carefully, in the example from @[mas steindorff] it was TRegistry.OpenKeyReadOnly - it's safe. You use TRegistry.OpenKey - this requires the KEY_ALL_ACCESS rights. Only by default, you can use the overload for the constructor to specify the access. (I know, it's nitpicking.) Bart ---------------------------------------------------------------------- mas steindorff · 2021-05-11 17:57 Quote from: diego bertotti on May 10, 2021, 11:06:33 pmyes, i'm working on it, but if you have the answer, i'll be very happy if you share with us sorry for ignoring you for so long.  figured I poke you a little (15 minutes) for still using Delphi. I did not plan on getting pulled away but ASerge came up to the task. I'm not sure if that is the fix but I do not have any admin issues on win10 with this code. ---------------------------------------------------------------------- diego bertotti · 2021-05-11 21:24 Quote from: ASerge on May 11, 2021, 04:36:02 amQuote from: diego bertotti on May 10, 2021, 11:06:33 pmyes, i'm working on it, but if you have the answer, i'll be very happy if you share with us The problem is in the code. Read carefully, in the example from @[mas steindorff] it was TRegistry.OpenKeyReadOnly - it's safe. You use TRegistry.OpenKey - this requires the KEY_ALL_ACCESS rights. i saw it but registry.pas unit of old delphi 2.0 don't have this function ---------------------------------------------------------------------- Bart · 2021-05-12 15:11 Quote from: diego bertotti on May 11, 2021, 11:24:09 pmi saw it but registry.pas unit of old delphi 2.0 don't have this function There are plenty registry replacements out there that doe have this function. I have one in my repository, besed upon fpc's one. But IIRC then D2 does not allow to overload functions/procedures/methods, so it probably won't compile in D2. Bart ---------------------------------------------------------------------- diego bertotti · 2021-05-13 21:39 Quote from: Bart on May 12, 2021, 05:11:27 pmQuote from: diego bertotti on May 11, 2021, 11:24:09 pmi saw it but registry.pas unit of old delphi 2.0 don't have this function There are plenty registry replacements out there that doe have this function. I have one in my repository, besed upon fpc's one. But IIRC then D2 does not allow to overload functions/procedures/methods, so it probably won't compile in D2. Bart you right, i try registry.pas unit of another delphi versions, and i got this error (can't be overloaded) ---------------------------------------------------------------------- mas steindorff · 2021-05-13 21:59 since D2 is not current nor designed for later window OS, you may need to modify the exe's properties using the run in (backward) compatibility mode.  I believe you can set the admin access right's in this new shortcut as well if your running win10 pro. Otherwise consider upgrading to a newer (perhaps free) compiler ---------------------------------------------------------------------- Remy Lebeau · 2021-05-14 02:10 Quote from: diego bertotti on May 10, 2021, 09:41:36 pmi have a question, but is about delphi...i know, here is for lazarus, but maybe can help me There are Delphi forums available at https://en.delphipraxis.net. Quote from: diego bertotti on May 10, 2021, 09:41:36 pmthat's the piece of code, for very old delphi 2.0 and tested on old delphi 6 too, with the same results; The problem is that you are opening the key with KEY_ALL_ACCESS rights, which is restricted to admins only.  TRegistry.GetValueNames() uses a combination of RegQueryInfoKey() and RegEnumValue(), so the bare-minimum rights you need to open the key with is just KEY_QUERY_VALUE.  Most users don't have write access to HKEY_LOCAL_MACHINE, but they typically have read-only access. TRegistry has an OpenKeyReadOnly() method since Delphi 4, and an Access property since Delphi 5 (maybe even 4).  For older versions, just call RegCreateKeyEx() or RegOpenKeyEx() directly, as needed.  An interposer class can be used to call the protected TRegistry.ChangeKey() method, which is needed to update the TRegistry.CurrentKey and TRegistry.CurrentPath properties. Try something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$DEFINE HAS_TREGISTRY_OPENKEYREADONLY} {$IFNDEF CONDITIONALEXPRESSIONS} // Delphi 6+  {$IFNDEF VER130} // Delphi 5    {$IFNDEF VER120} // Delphi 4      {$UNDEF HAS_TREGISTRY_OPENKEYREADONLY}    {$ENDIF}  {$ENDIF}{$ENDIF} {$IFNDEF HAS_TREGISTRY_OPENKEYREADONLY}type  TRegistry = class(Registry.TRegistry)  public    function OpenKeyReadOnly(const Key: String): Boolean;  end; function TRegistry.OpenKeyReadOnly(const Key: String): Boolean;var  TempKey: HKey;  S: string;  Relative: Boolean;begin  S := Key;  Relative := not ((S <> '') and (S[1] = '\'));   if not Relative then Delete(S, 1, 1);  TempKey := 0;   Result := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_READ, TempKey);  if not Result then  begin    Result := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, STANDARD_RIGHTS_READ or KEY_QUERY_VALUE or KEY_ENUMERATE_SUB_KEYS, TempKey);    if not Result then      Result := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_QUERY_VALUE, TempKey);  end;  if Result then  begin  if (CurrentKey <> 0) and Relative then S := CurrentPath + '\' + S;  ChangeKey(TempKey, S);  end;end;{$ENDIF} var       l: TStringList;  reg: TRegistry;  n: integer;begin  Form3.Combobox1.Items.BeginUpdate;  try    Form3.Combobox1.Items.Clear;    l := TStringList.Create;    try      reg := TRegistry.Create;      try        reg.RootKey := HKEY_LOCAL_MACHINE;        if reg.OpenKeyReadOnly('HARDWARE\DEVICEMAP\SERIALCOMM') then        begin          reg.GetValueNames(l);          for n := 0 to l.Count - 1 do            Form3.Combobox1.Items.Add(reg.ReadString(l[n]));        ComboBox1.ItemIndex := 0;        end;      finally        reg.Free;      end;    finally      l.Free;    end;  finally    Form3.Combobox1.Items.EndUpdate;  end;end;