Automatically make your PC wake up at a given time

 Windows, Windows 10  Comments Off on Automatically make your PC wake up at a given time
Mar 282020
 

Due the the COVID19 pandemic I am currently working from home, using Putty + ssh + Remote Desktop to log into and work on my office PC. For this to work, the office PC must be turned on and booted. So far I have let it running 24h which is really a waste of energy but since sometimes nobody is in the office at all, that was the most fool proof way.

Today I have had some time at my hands waiting for an Ubuntu server to finish installing, so I thought about alternatives.

  • One would have been Wake on LAN (WOL), if the BIOS of my computer supported it, but unfortunately it doesn’t (see edit below).
  • Waking up using the RTC (real time clock) is actually an option in the BIOS, but that would have woken it up every day rather than just on weekdays.

Finally I stumbled upon an article on How-To Geek about “How to Make Your PC Wake From Sleep Automatically“.

The Windows Scheduler has an option to wake up the computer to run a task. Note that it works only if the computer wasn’t turned off but rather sent into hibernation. So I set up a task that runs “cmd.exe” with the parameter “/c exit” weekly on Monday to Friday at 7:30. Of course I tested it first with a on time schedule and it worked fine.

So now I have sent my office PC into hibernation. We’ll see whether it is available on Monday when I want to log into it.

EDIT:
It turns out that my office PC supports WOL even though it’s not visible in the BIOS. But the network card properties under Windows have a setting for it:

So when I read the hint from Vandrovnik on the international Delphi Praxis forum, I ssh’d into the company intranet and was able to simply wake up my office PC using the wakeonlan tool installed on the remote logon computer:

wakeonlan [hardware address]

Great, this is much more flexible than I thought.

 Posted by on 2020-03-28 at 13:36

Extract jpeg files from mjpeg video on Linux

 Linux  Comments Off on Extract jpeg files from mjpeg video on Linux
Mar 122020
 

Just in case I ever need it again:

Extracting all frames from an mjpeg video as jpegs is easy and very fast with ffmpeg, because it does not need to decode and encode the pictures, just prepend the DHT to each one:

ffmpeg -i inputmpeg.avi -c:v copy -bsf:v mjpeg2jpeg frame_%d.jpg

Source ffmpeg documentation.

 Posted by on 2020-03-12 at 09:58

Skipping the UTF-8 BOM with TMemIniFile in Delphi 2007

 Delphi  Comments Off on Skipping the UTF-8 BOM with TMemIniFile in Delphi 2007
Mar 072020
 

Recently I came across a problem with INI files: Some editors (including recent versions of Windows Notepad) add a byte order mark (BOM) to the files they save. In particular the BOM for UTF-8 kept appearing in INI files which then were read incorrectly by the Delphi 2007 implementation of TMemIniFile (I guess the same applies to all pre Unicode versions of Delphi). In particular this was a problem with programs that used TJvAppIniStorage for streaming application settings to disk. (TJvAppIniStorage internally uses TMemIniFile.) So I tried to fix this, first by adding code that reads that file, removes the BOM and writes it back, before actually using it. This had some unpleasant side effects because some programs that usually start at the same time tried to access the file in parallel and failed. (No problem when only reading, but a big problem when writing.)

So I dug deeper and found that modifying TMemIniFile.LoadValues like this fixed the problem:

procedure TMemIniFile.LoadValues;
const
  BOM_LENGTH = 3;
var
  List: TStringList;
  st: TMemoryStream;
  Buffer: array[0..BOM_LENGTH-1] of Byte;
begin
  if (FileName <> '') and FileExists(FileName) then
  begin
    List := nil;
{$MESSAGE hint 'UTF-8 fix for TMemIniFile.LoadValues is active'}
    st := TMemoryStream.Create;
    try
      st.LoadFromFile(FileName);
      st.Position := 0;
      if BOM_LENGTH = st.Read(Buffer, BOM_LENGTH) then begin
        // the file contains at least BOM_LENGTH bytes
        if (Buffer[0] = $EF) and (Buffer[1] = $BB) and (Buffer[2] = $BF) then begin
          // we have a BOM -> Just leave the stream position as it is
        end else begin
          // no BOM -> reset stream position
          st.Position := 0;
        end;
      end;

      List := TStringList.Create;
      List.LoadFromStream(st);
      SetStrings(List);
    finally
      List.Free;
      st.Free;
    end;
  end
  else
    Clear;
end;

Note that this will only skip the BOM for UTF-8, but that is the only case I have ever encountered, because UTF-8 is an encoding that is mostly compatible with ANSI encoding. Other encodings will break TMemIniFile completely. But even with UTF-8 you will still encounter problems with characters that are encoded with more than one byte. So this is more of a simple workaround than a bugfix. For a bugfix, you will have to properly decode the whole file. (Or use a Unicode aware version of Delphi where this problem doesn’t exist.)

Of course TMemIniFile is declared in the RTL unit IniFiles so modifying it is not something to do on a whim. It turned out that at least in my case there was no problem as apparently there are no other RTL units that needed to be recompiled to include the changed IniFiles unit. So the easiest way was to copy IniFiles.pas to my program’s source directory, add it to the project (I prefer doing that so it’s easier to spot such a modified unit.) and recompile.

 Posted by on 2020-03-07 at 10:45

Delphi’s TStream.Read returns the number of bytes read

 Delphi  Comments Off on Delphi’s TStream.Read returns the number of bytes read
Mar 022020
 

Note to self: TStream.Read in the Delphi RTL returns the number of bytes read. It does not check whether the intended number of bytes could actually be read. So if you do not check it yourself, call TStream.ReadBuffer instead.

So, it’s either:

var
  st: TFileStream;
  Buffer: array[0..7] of Byte;
  BytesRead: Integer;
begin
  st := TFileStream.Create(fn, fmOpenRead);
  try
    BytesRead := st.Read(Buffer, SizeOf(Buffer));
    if BytesRead <> SizeOf(Buffer) then
      raise Exception.CreateFmt('BytesRead (%d) <> SizeOf(Buffer) (%d)',
        [BytesRead, SizeOf(Buffer)]);
    // do something with the content of buffer
  finally
    FreeAndNil(st);
  end;
end;

or

var
  st: TFileStream;
  Buffer: array[0..7] of Byte;
begin
  st := TFileStream.Create(fn, fmOpenRead);
  try
    st.ReadBuffer(Buffer, SizeOf(Buffer));
    // do something with the content of buffer
  finally
    FreeAndNil(st);
  end;
end;

The same logic applies to TStream.Write and TStream.WriteBuffer.

I have just grep-ed my sources and found way to many places where I used Read instead of ReadBuffer and Write instead of WriteBuffer.

Unfortunately that’s an easy mistake to make, so I guessed that I am not the only one who made it. And lo and behold, I found lots of places in the Delphi 2007 RTL and VCL (so they might have been fixed in the mean time, I didn’t check though) and several 3rd party libraries (including the current JCL and JVCL) where this mistake was made. So it’s probably a good idea if you do that check on your own code.

The regular expressions I used for this were:

^\s*\w*\.read\(
^\s*\w*\.write\(

If you use GExperts Grep, don’t forget to enable the “Regular Expression” option!

 Posted by on 2020-03-02 at 16:03

dzBdsLauncher 1.0.3 released

 Delphi, dzBdsLauncher  Comments Off on dzBdsLauncher 1.0.3 released
Mar 012020
 

The latest version of dzBdsLauncher can now also handle some .dproj files with invalid ProjectVersion entries (e.g. those generated by project JEDI which apparently uses ProjectVersion 17.3 for all Delphi versions >XE8). It does this by evaluating the DllSuffix entry, if one exists. This can also help solving conflicts if the ProjectVersion is not unique.

In addition the tool can now also open .grouproj files. It handles them by inspecting the first project listed in the file.

Another small improvement is colored diagnostic output to help troubleshooting if something goes wrong.

See the main dzBdsLauncher page for download links.

 Posted by on 2020-03-01 at 19:24