Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 09/17/20 in all areas

  1. Anders Melander

    "Self-updating" terminal services DLL

    MoveFileEx with the MOVEFILE_DELAY_UNTIL_REBOOT flag can do that already. Virtual Channel client DLLs are loaded at boot so it's pointless to try to replace the file without a reboot. That said, you could solve it with two DLLs: The Virtual Channel client DLL contains the auto-update functionality but forwards all the VirtualChannel* DLL calls to... The "other DLL" which implements the actual functionality. Of course the Virtual Channel client DLL will need to load the "other DLL" dynamically or you will have the same problem with both DLLs. When the Virtual Channel client DLL determines that it needs to update the "other DLL" it just unload the old DLL and load the new DLL. If the Virtual Channel client DLL needs to update itself it can do so with MoveFileEx (or just unregister the old DLL and register the new) and a reboot. Maybe it's enough to restart the Remote Desktop Services (the documentation just states that the DLL is loaded during Remote Desktop Services initialization), but you will need a third file, an application, that does that for you. Give it a try. Edit: I just realized that the above was basically what @Fr0sT.Brutal wrote.
  2. Carlo Barazzetta

    Looking for SVG support in Delphi?

    I've published an article about SVGIconImageList and IconFontsImageList:https://ethea.it/icons_in_delphi/
  3. Carlo Barazzetta

    Looking for Icon Fonts support in Delphi for High-DPI and Themed app?

    I've published an article about SVGIconImageList and IconFontsImageList: https://ethea.it/icons_in_delphi/
  4. Fr0sT.Brutal

    "Self-updating" terminal services DLL

    Depending on lib usage, you can split your lib into agent part that is rarely updated and functional part that could be unloaded and updated by agent part.
  5. Perhaps a simple "Open as text" in the context menu of a DFM in the project manager may be sufficient.
  6. Much annoying. Very bug. 😛 https://quality.embarcadero.com/browse/RSP-30576
  7. Lars Fosdal

    Add test to Stringgrid

    There is an extra fee for solving homework problems, isn't there?
  8. Sherlock

    Add test to Stringgrid

    Do you know how to add any text to a TStringGrid? Do you know how to read the contents of a TEdit?
  9. dummzeuch

    On IDE cannot get TABS

    Yeah, that's odd. I wonder where this declaration comes from. There are other classes there as well, that are naked declarations. Maybe looking at the project as a whole would give some clues. For a start I would remove all property and method declarations, typecast to this type and try to access the fields to see if that results in plausible values. If they do, it's possible to call the virtual methods through the VMT. But that's definitely out of my league.
  10. to be precise it should be the same issue as https://quality.embarcadero.com/browse/RSP-30588 but DelphiLSP has as well other known issues as https://quality.embarcadero.com/browse/RSP-30627 https://quality.embarcadero.com/browse/RSP-30667 (EMBT is aware of the issues that were already raised during the BETA)
  11. dummzeuch

    "Self-updating" terminal services DLL

    It should be possible to rename a DLL while it is being used and replace it with a new one. I do this all the time in the pre build script of GExperts. This of course requires the rights move the file in the first place.
  12. Binary DFM are devils work and must be burnt at the stake whilst vigorously waving pitchforks and shouting obscenities. Version control systems handle them poorly (not that text DFMs are far better in this regard, but, you can manage, once you move any pictures to a datamodule). Actually they are just binary blobs most of the time and will consume unnecessary storage Everything else, the other guys said
  13. Anders Melander

    RzLauncher vs. Win API call

    I have no idea about how TRzLauncher is implemented, but regardless I would just use a thin wrapper around ShellExecuteEx. Here's the implementation I usually use: unit amShell; (* * Copyright © 2006 Anders Melander * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *) interface uses Windows, Controls; type Shell = class private public class procedure DisplayURL(const URL: string; Parent: TWinControl = nil; const AdditionalParams: string = ''); class function DisplayFile(const Filename: string; Parent: TWinControl = nil): boolean; class function Execute(const Filename: string; const Parameters: string = ''; Parent: TWinControl = nil; Wait: boolean = False): boolean; overload; class function Execute(Parent: TWinControl; const FileName: string; const Operation: string = 'open'; const Parameters: string = ''; ShowCmd: Integer = SW_SHOWNORMAL; Wait: boolean = False): boolean; overload; static; end; resourcestring sShellExecuteBrowseError = 'Failed to open the homepage in your default browser.'+#13#13+ 'Homepage: %s'+#13+ 'Error: %s'; sShellExecuteFileOpenError = 'Failed to open the file.'+#13#13+ 'Filename: %s'+#13+ 'Error: %s'; implementation uses ActiveX, ShellAPI, SysUtils, IOUtils, Forms, Dialogs, StrUtils, Classes, Types, Messages, IdURI, amCursorService, amDialogs; class function Shell.DisplayFile(const Filename: string; Parent: TWinControl): boolean; var Error: integer; begin Result := Execute(Parent, Filename); if (not Result) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteFileOpenError, [Filename, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class function Shell.Execute(const Filename, Parameters: string; Parent: TWinControl; Wait: boolean): boolean; var Error: integer; begin Result := Execute(Parent, Filename, '', Parameters, SW_SHOWNORMAL, Wait); if (not Result) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteFileOpenError, [Filename, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class procedure Shell.DisplayURL(const URL: string; Parent: TWinControl; const AdditionalParams: string); var Error: integer; URI: TIdURI; FinalURL: string; FinalParams: string; ParamList: TStringDynArray; s: string; Params: TStringList; n: integer; Name, Value: string; begin try URI := TIdURI.Create(URL); try // Note that we use TIdURI even with no additional params as we would still like to get the original params encoded (' '->'%20'). if (AdditionalParams <> '') then begin Params := TStringList.Create; try Params.CaseSensitive := False; // Create a Key/Value list of original parameters ParamList := SplitString(URI.Params, '&'); for s in ParamList do Params.Add(s); // Add additional parameters, overriding the original values if there are duplicates ParamList := SplitString(AdditionalParams, '&'); for s in ParamList do begin n := Pos('=', s); if (n <> 0) then begin // Key/Value pair Name := Copy(s, 1, n-1); Value := Copy(s, n+1, MaxInt); Params.Values[Name] := Value; end else // No value, just key Params.Values[s] := ''; end; // Build parameter string FinalParams := ''; for s in Params do if (FinalParams = '') then FinalParams := s else FinalParams := FinalParams + '&' + s; finally Params.Free; end; URI.Params := FinalParams; end; FinalURL := URI.URI; finally URI.Free; end; except on E: EIdURIException do begin s := URL; if (AdditionalParams <> '') then s := s + '(' + AdditionalParams + ')'; MessageDlgEx(Format('Invalid URL: %s'#13'%s', [s, E.Message]), mtWarning, [mbOk], 0); exit; end; end; if (not Execute(Parent, 'rundll32.exe', 'open', 'url.dll,FileProtocolHandler '+FinalURL)) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteBrowseError, [FinalURL, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class function Shell.Execute(Parent: TWinControl; const FileName, Operation, Parameters: string; ShowCmd: Integer; Wait: boolean): boolean; var Handle: HWND; ShellExecuteInfo: TShellExecuteInfo; Error: integer; Res: Cardinal; Msg: TMsg; begin if (Parent <> nil) then Handle := Parent.Handle else Handle := Application.MainForm.Handle; FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0); ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo); ShellExecuteInfo.fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_HMONITOR or SEE_MASK_NOZONECHECKS;// or SEE_MASK_NOCLOSEPROCESS; if (Wait) then ShellExecuteInfo.fMask := ShellExecuteInfo.fMask or SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC; ShellExecuteInfo.Wnd := Handle; ShellExecuteInfo.hMonitor := THandle(Application.MainForm.Monitor.Handle); // Cast to avoind range check error if (Operation <> '') then ShellExecuteInfo.lpVerb := PChar(Operation); if (FileName <> '') then ShellExecuteInfo.lpFile := PChar(FileName); if (Parameters <> '') then ShellExecuteInfo.lpParameters := PChar(Parameters); ShellExecuteInfo.lpDirectory := PChar(TPath.GetDirectoryName(Filename)); ShellExecuteInfo.nShow := ShowCmd; SaveCursor(crAppStart); Result := ShellAPI.ShellExecuteEx(@ShellExecuteInfo); if (not Result) then begin Error := GetLastError; if (Error = ERROR_ACCESS_DENIED) then begin // See: // * https://support.microsoft.com/en-us/kb/287087 // * http://wellsr.com/vba/2016/excel/use-vba-shellexecute-to-open-url-in-default-browser/ if (ShellAPI.ShellExecute(Handle, ShellExecuteInfo.lpVerb, ShellExecuteInfo.lpFile, ShellExecuteInfo.lpParameters, nil, CmdShow) > SE_ERR_DLLNOTFOUND) then Result := True else SetLastError(Error); end; end else if (Wait) then begin try while (True) do begin Res := MsgWaitForMultipleObjects(1, ShellExecuteInfo.hProcess, False, INFINITE, QS_PAINT); case Res of WAIT_OBJECT_0: break; WAIT_OBJECT_0+1: while (PeekMessage(Msg, 0, QS_PAINT shl 16, QS_PAINT shl 16, PM_REMOVE)) do begin if (Msg.message = WM_QUIT) then begin PostQuitMessage(Msg.wParam); exit; end; TranslateMessage(Msg); DispatchMessage(Msg); end; else break; end; end; finally CloseHandle(ShellExecuteInfo.hProcess); end; end; end; var NeedCoUninitialize: boolean = False; initialization // ShellExecute needs CoInitialize NeedCoUninitialize := Succeeded(CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE)); finalization if (NeedCoUninitialize) then CoUninitialize; end.
  14. Anders Melander

    Experience/opinions on FastMM5

    So you're complaining that Pierre has enabled us to use FastMM 5 for free and that there's conditions for this use? I think "thank you" would be more appropriate.
  15. David Heffernan

    Experience/opinions on FastMM5

    Don't use the hammer then. Make your own. Your choice.
  16. Darian Miller

    Experience/opinions on FastMM5

    If you distribute applications that includes some GPL code, then all the code to your application must be made publicly available. Commercial software makers typically stay far away from GPL. Now, if you are actually making money on the software you make and distribute, then it makes sense to pay Pierre for a commercial license, bypassing the GPL issue. It's a real line in the sand for FastMM5. Perhaps Embarcadero will negotiate with Pierre a nice big fee to get a redistributable commercial licensed version of FastMM5... or they will simply keep shipping Delphi with FastMM4. They certainly won't be shipping a GPL version of FastMM5 with Delphi.
×