Leaderboard
Popular Content
Showing content with the highest reputation since 07/05/25 in all areas
-
pascal-process: A new library for running processes and redirecting their output.
pyscripter posted a topic in I made this
There are many components/libraries available for running processes and capturing their output. But, I got frustrated with their design and functionality, mostly for the following reasons: Fixation with and premature conversion to strings. Processes produce and consume bytes. Blocking reading of process output, resulting to inefficiencies (tight loops with Sleep, or separate threads for reading the output or providing input to the process) Incomplete features and/or over-bloated So, I have made my own pascal-process single unit library. Main features: Asynchronous reading of process output Separate stdout and stderr reading which can optionally be merged Ability to consume output as it is produced or else let it accumulate and read the final result Ability to provide input to the running process before or while the process is running. Ability to terminate the running process. Synchronous and asynchronous execution of processes. Interfaced-based facilitating memory management. MIT licence Usage: You do not need to install the library. Just download or clone the repo and add the source subdirectory to the Library path. Then add PascalProcess to your uses clause. If you just want to get the output of a process you can use the class functions of TPProcess. TPProcess = class(TInterfacedObject, IPProcess) class function Execute(const ACommandLine: string; const ACurrentDir: string = ''): TBytes; overload; class procedure Execute(const ACommandLine: string; const ACurrentDir: string; out Output, ErrOutput: TBytes) overload; end; This is an example: var Output: TBytes; begin Output := TPProcess.Execute('cmd /c echo Hi'); Writeln(TEncoding.ANSI.GetString(Output)); end; For more demanding cases you can use the IPProcess interface. Example: type TUtils = class class procedure OnRead(Sender: TObject; const Bytes: TBytes); end; class procedure TUtils.OnRead(Sender: TObject; const Bytes: TBytes); begin Writeln(TEncoding.ANSI.GetString(Bytes)); end; procedure Test2; // Processes ouput as it gets produced // The main thread terminates the process var Process: IPProcess; begin Process := TPProcess.Create('cmd /c dir c:\ /s'); Process.OnRead := TUtils.OnRead; WriteLn('Press Enter to start the process. Press Enter again to terminate'); ReadLn; Process.Execute; ReadLn; Process.Terminate; end; See here the definition of IPProcess. Limitations: Currently the library is Windows only. The intention is to support other platforms (help wanted).- 23 replies
-
- open-source
- process
-
(and 1 more)
Tagged with:
-
Blocking hackers
Angus Robertson replied to Angus Robertson's topic in ICS - Internet Component Suite
Illegal accesses to my web site have escalated since my last message here in March, and increased 10 fold in the last 10 days. Initially, the Chinese hackers are using what I assume are VPN IPs in various countries, which were relatively easy to slow down. Then I got attempts from 20,000 IPs in Vietnam, and increasingly from other countries. My ICS web server had access attempts from 170,000 different IPs over the last 15 hours on Sunday night. I added geo-blocking last week from a list of countries in Asia, Africa, South America and the Middle East, and 200,000 connections were rejected and 20,000 allowed, although probably only 1,000 would have been from legitimate users on a Sunday night. Did this using the Delphi TMMDBReader component from https://github.com/optinsoft/MMDBReader that reads MaxMind database files of IP addresses, listing country, ASN, City, ISP and other information (for a price), but I'm currently using a simple country lookup database from https://db-ip.com/ . MaxMind has an anonymous IP database that is probably ideal for my purpose, but no public pricing so probably more than I want to pay. Angus -
There is a new version at https://github.com/rmesch/Bitmaps2Video-for-Media-Foundation. New stuff: Some rewrite of audio, making sure that gaps at the beginning of a stream are filled with silence. 2 optimized frame-rates for audio-synching, see below. Most importantly: One can now run @Kas Ob.'s frame analysis from within the demo, if one enables the hidden tab "Analysis". I just made the lines a bit shorter, as the rest was just repeating the same values for all I tested, as far as I could see. The file ffprobe.exe needs to be in the same directory as DemoWMF.exe. ffprobe is part of ffmpeg-git-essentials.7z on https://www.gyan.dev/ffmpeg/builds/. I spent a good amount of time trying to figure out what I can and what I cannot control about audio-synching, tracing into the relevant code and running the analysis. Results of audio-rethynching follow (beware, it's long): The math is for audio-sample-rate of 48000 and the time units are all s. Audio-blockalign is always 4 Bytes for what I do. There are at least 2 different meanings of "sample": PCMSample: as in samples per second. ByteSize: Channels*BitsPerSample/8 = 2*16/8 = 4 Bytes. Time: 1/48000 s IMFSample: Chunk of audio returned by IMFSourceReader.ReadSample. It contains a buffer holding a certain amount of uncompressed PCMsamples, and info like timestamp, duration, flags ... The size of these samples varies a lot with the type of input. Some observed values: .mp3-file 1: Buffersize = 96 768 Bytes Duration = 0.504 (96768 bytes = 96768/4 PCMSamples = 96768/4/48000 s OK) .mp3-file 2: Buffersize = 35 108 Bytes Duration = 0.1828532 (35108/4/48000 = 0.182854166.. not OK) .wmv-file: Buffersize = 17 832 Bytes Duration = 0.092875 (17832/4/48000 = 0.092875 OK) Except for the first sample read, the values don't differ from sample to sample. Those are the samples I can write to the sinkwriter for encoding. Breaking them up seems like a bad idea. I have to trust MF to handle the writing correctly. The buffers seem to always be block-aligned. I've added some redundant variables in TBitmapEncoderWMF.WriteAudio so these values can be examined in the debugger. A related quantity are audio-frames. Similarly to the video-stream the audio-stream of a compressed video consists of audio-frames. 1 audio-frame contains the compressed equivalent of 1024 PCMSamples. So: AudioFrameDuration = 1024/48000 AudioFrameRate = 48000/1024 I can only control the writing of the video by feeding the IMFSamples of video and audio to the sinkwriter in good order. The samples I write to the sinkwriter are collected in a "Leaky-Bucket"-buffer. The encoder pulls out what it needs to write the next chunk of video. It hopefully waits until there are enough samples to write something meaningful. Problems arise if the bucket overflows. There need to be enough video- and audio-samples to correctly write both streams. So here is the workflow, roughly (can be checked by stepping into TBitmapEncoderWMF.WriteOneFrame): Check if the audio-time written so far is less than the timestamp of the next video-frame. Yes: Pull audio-samples out of the sourcereader and write them to the sinkwriter until audio-time >= video-timestamp. Looking at the durations above, one sample might already achieve this. Write the next video-frame Repeat In the case of mp3-file 1 the reading and writing of 1 audio-sample would be followed by the writing of several video-samples. The encoder now breaks the bucket-buffer up into frames, compresses them and writes them to file. It does that following its own rules, which I have no control over. Frame-analysis can show the result: A group of video-frames is followed by a group of audio-frames, which should cover the same time-interval as the video-frames. In the output I have seen so far, the audio-frame-period is always 15 audio-frames. For video-framerate 30, the video-frame-period is 9 or 10 frames. Why doesn't it make the audio- and video-periods smaller? No idea. Guess that's the amount of info the players can handle nowadays, and these periods are a compromise between optimal phase-locking of audio- video- periods and the buffer-size the player can handle. Theoretically, at framerate 30, 16 video-frames should phase-lock with 25 audio-frames. Here is one of those video-audio-groups. Video-framerate is 30. video stream_index=0 key_frame=0 pts=39000 pts_time=1.300000 duration_time=0.033333 video stream_index=0 key_frame=0 pts=40000 pts_time=1.333333 duration_time=0.033333 video stream_index=0 key_frame=0 pts=41000 pts_time=1.366667 duration_time=0.033333 video stream_index=0 key_frame=0 pts=42000 pts_time=1.400000 duration_time=0.033333 video stream_index=0 key_frame=0 pts=43000 pts_time=1.433333 duration_time=0.033333 video stream_index=0 key_frame=0 pts=44000 pts_time=1.466667 duration_time=0.033333 video stream_index=0 key_frame=0 pts=45000 pts_time=1.500000 duration_time=0.033333 video stream_index=0 key_frame=0 pts=46000 pts_time=1.533333 duration_time=0.033333 video stream_index=0 key_frame=0 pts=47000 pts_time=1.566667 duration_time=0.033333 video stream_index=0 key_frame=0 pts=48000 pts_time=1.600000 duration_time=0.033333 audio stream_index=1 key_frame=1 pts=62992 pts_time=1.312333 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=64016 pts_time=1.333667 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=65040 pts_time=1.355000 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=66064 pts_time=1.376333 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=67088 pts_time=1.397667 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=68112 pts_time=1.419000 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=69136 pts_time=1.440333 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=70160 pts_time=1.461667 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=71184 pts_time=1.483000 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=72208 pts_time=1.504333 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=73232 pts_time=1.525667 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=74256 pts_time=1.547000 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=75280 pts_time=1.568333 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=76304 pts_time=1.589667 duration_time=0.021333 audio stream_index=1 key_frame=1 pts=77328 pts_time=1.611000 duration_time=0.021333 pts stands for "presentation time stamp" and pts_time is of interest. Video-time-intervall: from 1.300000 to 1.600000+0.033333=1.633333 Audio-time-intervall: from 1.312333 to 1.611000+0.021333=1.632333 Audio is a bit ahead at the beginning and a tiny bit behind at the end. pts should be multiples of 1024, but they aren't hmm. The difference is still 1024, but they are phase-shifted. Phase-shift is 62992 mod 1024 = 528 (or -496). The interval from a bit further ahead: Video: From 8.066667 to 8.366667+0.033333=8.400000 Audio: From 8.053667 to 8.352333+0.021333=8.373666 pts-phase-shift: still 528 (-496) Audio is lagging behind. To really see what is happening I will have to implement better statistics than just looking at things 🙂 One further test: I tried to phase-lock audio and video optimally: VideoFrameRate: f. AudioFrameRate: 48000/1024, so f = 48000/1024 = 46,875. I've added this frame-rate to the demo. Result: Perfect sync for the first audio-video group. In the middle of the second group the pts-phase-shift is again 528, and audio lags behind. For the rest of the groups the lag doesn't get bigger, it is always corrected to some degree. But the file should have identical audio and video timestamps in the first place! There is another new frame-rate, which is the result of trying to phase-lock 2 video-frames to 3 audio-frames. 2/f = 3*1024/4800 results in f = 2*48000/3/1024 = 31.25 I will try to find out what causes the phase-shift in audio by parsing the ffprobe-output a bit more (sigh). Maybe generate a log-file for the samples written, too. (Sigh). No, so far it's still fun. For those, who made it up to here: Thanks for your patience. Renate
-
pascal-process: A new library for running processes and redirecting their output.
Dave Nottage replied to pyscripter's topic in I made this
I tested it on macOS using this command: "/Applications/PAServer-23.3.app/Contents/MacOS/iosinstall" -q -c -t 5 -W Which ran as expected. This is the command PAServer issues when it wants to detect what devices are visible to the Mac. One thing to note: in the docs on your repo, it suggests using this in the OnRead (of which the parameters in the example do not match the actual source): TEncoding.ANSI.GetString(Bytes) Which might work elsewhere, but on macOS this works: TEncoding.Default.GetString(Bytes)- 23 replies
-
- open-source
- process
-
(and 1 more)
Tagged with:
-
https://www.delphitools.info/samplingprofiler/ "SamplingProfiler is a performance profiling tool for Delphi, from version 5 up to both 32bits & 64bit Delphi 12.x (and likely the next ones). Its purpose is to help locate bottlenecks, even in final, optimized code running at full-speed." ... "With version 1.7+, SamplingProfiler includes a small http web server which can be used for real-time monitoring of the profiled application. The monitor provides code hot-spot information in real-time, in HTML or XML form."
-
[Info & Feedback] DelphiGenAI v1.1.0 — Sharing Updates and an Educational Approach
Maxidonkey posted a topic in I made this
Hi everyone, I wanted to share the main updates in version 1.1.0 of DelphiGenAI (OpenAI wrapper for Delphi) here—mainly to offer what I can to the community, and maybe get some feedback if anyone feels like weighing in on my approach. Main Updates Compatibility with the Latest OpenAI Features (including Remote MCP & Code interpreter) Ready-to-Use Templates Two archives (TestGenAI_VCL.zip and TestGenAI_FMX.zip) let you copy and paste any snippet from the documentation and test it out, with no complicated setup. Variety of Code Snippets For each feature: synchronous, asynchronous (event/callback), and asynchronous with async/await. The idea is to allow everyone to compare the approaches and pick the one that fits them best. Documentation That’s Directly Usable All markdown examples can be tested as-is within the supplied templates. A Gradual Learning Path The aim: make it easier to learn about AI in Delphi, whatever your starting level, and to keep things as accessible as possible. About This Approach I’m not an experienced “Delphi old-timer” and I don’t know the community very well yet; that’s why I chose to offer several approaches (synchronous, asynchronous, and async/await) for each example. But maybe that’s not really necessary—maybe some would prefer strictly asynchronous, or even just synchronous? I’d be interested in your thoughts or experiences on this (no pressure—just curious, and trying to do what's most helpful). Also Tried on Other Wrappers I’ve used the same principle in a Delphi wrapper for Deepseek. Depending on the feedback I get here, I’ll decide whether to take this approach with a few other wrappers I’ve put up on Github. Thanks in advance for reading, and best wishes to all. -
How upgrading from Delphi 7 to Delphi 12 eliminated 15 monthly support tickets and unlocked Linux deployment In May 2024, we were contacted by a European leader in natural gas measurement systems. Their software was partly built in Delphi 7 and partly in C#. It had become difficult to maintain. The company wanted to migrate to Delphi 12, modernize the UI, and enable Linux deployment, without breaking existing functionality. Our team faced and handled the following challenges: The project relied on Delphi 7. That version lacked full Unicode support. The framework used ANSI strings by default, and this created critical limitations for modern global applications. The legacy app only ran on 32-bit Windows, using outdated Win32 APIs and hardcoded paths (C:\Data\). This prevented deployment on Linux cloud servers (AWS/Ubuntu). The app was built on obsolete BDE components and unsupported libraries. Here's what we did: ✅ Migrated from Delphi 7 to Delphi 12 ✅ Replaced BDE and Indy 9 with FireDAC and Indy 10 ✅ Refactored code for cross-platform compatibility ✅ Delivered a modernized UI with preserved workflow familiarity We achieved: - 15 support tickets per month were reduced to zero - Windows-only application is now cross-platform - Overall, the application is more prepared for future challenges A few months later, the client returned for an estimate to migrate other Delphi projects to a web-based platform. If you want to see the full story, with the challenges and solutions broken down, follow the link https://www.softacom.com/cases/modernizing-industrial-software-with-delphi-12/
-
Why TListView.OnItemChecked event called by ListView.Items.Add?
Remy Lebeau replied to Marsil's topic in VCL
I cannot reproduce any memory leak with that code, but I can reproduce the caption issue. You need to add the item before changing its Caption: var Item := TListItem.Create (ListView1.Items); ListView1.Items.AddItem (Item); // <-- move here Item.Caption := SomeLinkedObject.Name; Item.Checked := SomeLinkedObject.Enabled; Item.Data := SomeLinkedObject; The reason is because setting the Caption assigns the LPSTR_TEXTCALLBACK flag on the item, which TListView needs to display the assigned String data, but AddItem() does not set that same flag. So, if you set the Caption and then Add, the flag is not set and the ListView has no text data to display. Looks like a bug, I have reported it: RSS-3772: TListItems.AddItem() does not set LPSTR_TEXTCALLBACK flag for existing TListItem -
Vcl DBChart Line Series Set Line Thickness
Henry Olive replied to Henry Olive's topic in General Help
I solved the problem -
What you indicated is not the last one: (of course you could have installed it manually too...). But, if you don't find the source files, obviously something went wrong during the installation. Did you check the installation for all platforms during the installation of Rad Studio? (I did)
-
Why TListView.OnItemChecked event called by ListView.Items.Add?
Remy Lebeau replied to Marsil's topic in VCL
As I said earlier, you are getting the event when the new item's default state image is assigned. More specifically, when TListView.Items.Add() creates a new TListItem object and inserts it into the TListView.Items, it calls the Win32 ListView_InsertItem() function, which immediately sends the TListView a LVN_ITEMCHANGED notification before it returns. In that notification, the item's uChanged field is LVIF_STATE and the state image has changed index from 0 to 1. That condition is what fires the OnItemChecked event. The item is fully initialized from the Win32 perspective before TListView.Items.Add() returns. Anything you do extra to the item after Add() returns is optional, and is initialization from your perspective, not the Win32 perspective. -
My sources about Posix are in "C:\Program Files (x86)\Embarcadero\Studio\23.0\source\rtl\posix" If you have trouble compiling, look at: https://docwiki.embarcadero.com/RADStudio/Athens/en/Installation_Notes There are some notes about Linux at the end of the page (missing lib paths). P.S.: in my installations of course there are the compiled units in ALL needed paths.
-
Why TListView.OnItemChecked event called by ListView.Items.Add?
Kas Ob. replied to Marsil's topic in VCL
Debugging and tracking the OnChecked event, the behavior has nothing to do with Delphi and its VCL, it is triggered by Windows message, so you have to use a workaround about that, something like what Remy suggested. -
Why TListView.OnItemChecked event called by ListView.Items.Add?
Kas Ob. replied to Marsil's topic in VCL
You are right the the behavior is wrong and buggy, Using similar approach of create then add, doesn't show caption, but no memory leak on XE8. -
Why TListView.OnItemChecked event called by ListView.Items.Add?
Marsil replied to Marsil's topic in VCL
I tried this var Item := TListItem.Create (ListView1.Items); Item.Caption := SomeLinkedObject.Name; Item.Checked := SomeLinkedObject.Enabled; Item.Data := SomeLinkedObject; ListView1.Items.AddItem (Item); but the item is shown without caption!, and memory leak occurred! --------------------------- Unexpected Memory Leak --------------------------- An unexpected memory leak has occurred. The unexpected small block leaks are: 13 - 20 bytes: TList x 4, Unknown x 4 21 - 28 bytes: UnicodeString x 3 37 - 44 bytes: UnicodeString x 1 45 - 52 bytes: TListItem x 4 77 - 84 bytes: TSubItems x 4 I don't think solves the issue since the only way to implement your suggestion is to use ListView.Items.AddItem which is called by ListView.Items.Add. -
Why TListView.OnItemChecked event called by ListView.Items.Add?
Kas Ob. replied to Marsil's topic in VCL
But, it is already created, initialized (with default) and added with ListView1.Items.Add Your next Item.Checked := SomeLinkedObject.Enabled; Is triggering the event as designed, nothing wrong here, If you don't want that behavior, then try to create the item as local var, not by calling Items.Add then set (Initialize) properties and only then add it to the items, though i am not sure if this will trigger the event or not, it shouldn't, but who knows you need to test it, this will change the narrative of the expected behaviour and might, i say might, be discussed as bug or short in design, if just adding an item triggers an event. -
Why TListView.OnItemChecked event called by ListView.Items.Add?
Remy Lebeau replied to Marsil's topic in VCL
The checkboxes are implemented as state images. You are getting the event when the item's initial state is assigned. Just check for the nil condition and don't access the object when it's not ready yet: procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); begin if Assigned(Item.Data) then TSomeLinkedObject(Item.Data).Enabled := Item.Checked; end; Alternatively, disable the event when adding an item, and then re-enable the event when ready: ListView1.OnItemChecked := nil; var Item := ListView1.Items.Add; ... ListView1.OnItemChecked := ListView1ItemChecked; -
Passing an SQL into a REST Request, and returning Result in JSON Dataset?
Lars Fosdal replied to Robert Gilland's topic in Network, Cloud and Web
Short answer: Yes Long answer: Yes, but don't! It would put your SQL database at risk. Instead, build a proper REST API as - it hides the underlying database - it allows you to change the underlying database operations without changing the client A REST API done right is far more secure and robust. -
How upgrading from Delphi 7 to Delphi 12 eliminated 15 monthly support tickets and unlocked Linux deployment.
FabsMuller replied to Serge Pilko's topic in Tips / Blogs / Tutorials / Videos
Good story, thanks for sharing, Kind of impressive that it took just 4 people (2 devs) to do all that, and probably to the users it was just some new boxes and buttons, nothing so different than they were used to. Not so bad for a system that probably was +20 years old. These Delphi tales always astonishes me. Everybody knows one or a couple of cases like this. Obviously, if the company had kept a little system maintenance about let's say each 5 years, the system wouldn't have so many problems. But almost nobody does that. For sure, it paid itself hundred of times. Anyway, Better late than never. Congratulations. -
function declarations without ; at the end
Oleksandr Skliar replied to Günther Schoch's topic in RTL and Delphi Object Pascal
Continuing with the "funny" compiler "errors": 1. Optional semicolon (for global and nested proc declarations only!!!) if you have any of these specifiers (platform, deprecated, assembler, register, stdcall... etc): But semicolon is required if this is a const/var/type/method 2. Crazy mixing of these specifiers (you can mix all these specifiers as you want): 3. Crazy mixing of "platform" specifier for global variable declaration: I suppose there are much more similar "bugs", I see it on 11.3 and 12.3, and believe emba will never fix it, their favorite answer - don't do like this! 😄 -
That is pretty trivial to implement, eg: procedure TMainForm.GoBtnClick(Sender: TObject); var url: string; idx: integer; begin { change this https://www.youtube.com/watch?v=ZJhJILyS388 to this https://www.youtube.com/embed/ZJhJILyS388 } url := StringReplace(addresscb.Text, 'watch?v=', 'embed/', [rfIgnoreCase]); addressCb.Text := url; WVBrowser1.Navigate(url); idx := ComboBox1.Items.IndexOf(url); if idx = -1 then ComboBox1.Items.Add(url); end;
- 12 replies
-
- delphi xe7
- youtube
-
(and 1 more)
Tagged with:
-
Annoying warning message a'attribute declaration must precede definition'
weirdo12 replied to tester1234's topic in General Help
The warning is caused by having #include "Label.h" *before* the USEFORM. #include "Label.h" ... USEFORM("Label.cpp", fmLabelView); Try this: USEFORM("Label.cpp", fmLabelView); ... #include "Label.h" -
I wrote it myself a few years ago, based on an article written by Cary Jensen that you can find here. Attached is the code for the expert in its current state, the changing of the format source key assignment is still a work in progress. Editor.zip
-
Access Violation with a TFDMemTable placed on a datamodule inheriting from TMARSFDDataModuleResource
Andrea Magni replied to Stuart Clennett's topic in MARS-Curiosity REST Library
Hi @Stuart Clennett, it's a bug! 🙂 Thanks for spotting it. The TMARSFireDAC.InjectMacroValues and TMARSFireDAC.InjectParamValues implementations assume every TFDAdaptedDataSet actually has a Command (not nil). TFDMemTable do not have Command assigned. Workaround: if you do not need your memory table to be included as the result of Retrieve method, you can decorate it with the RESTExclude attribute: [RESTExclude] FDMemTable1: TFDMemTable; However, I just fixed this in the "develop" branch of MARS repository: https://github.com/andrea-magni/MARS/commit/b6299926671b00e75981c47a74375d9c51c529ca Another workaround would be to change your copy of TMARSFDDataModuleResource.Retrieve and change this line: if LDataSet is TFDAdaptedDataSet then to this: if (LDataSet is TFDAdaptedDataSet) and Assigned(TFDAdaptedDataSet(LDataset).Command) then The MARS.Data.FireDAC.DataModule has nothing special, it is provided as an example of use, you can copy it, change it... it is obviously the counter-part of a TMARSFDResource but there no direct deal with the specific class, just matter of the shape of its methods (types returned, GET/POST selection, ...). Thanks, Andrea -
You'll also get emails when the issue is changed/updated. In my experience from trawling issues and the handful I've raised it seems relatively rare for an issue to be worked on or fixed.