signature text (--l2-text <text>)

5 views
Skip to first unread message

Rafał Sitek

unread,
Feb 19, 2026, 8:39:14 AM (2 days ago) Feb 19
to JSignPdf
How to pass custom text with newline characters in the --l2-text parameter (cmd - Windows) - it ignores both #10#13 and Java-style \n

Josef Cacek

unread,
Feb 20, 2026, 10:03:14 AM (yesterday) Feb 20
to jsig...@googlegroups.com
Hi Rafal,

the `cmd` is a horrible shell, so I would try to avoid it at all.

Here are the options I see:

1. Keep using the cmd, and prepare a property file with the L2 text (and possibly other properties). Use the classic \n for new lines. Then use -lpf JSignPdf argument to load the property file.
Sample property file content (l2.properties):
visibleSignature.l2text=line 1\nline 2\netc

Sample call:
JSignPdfC.exe -lpf l2.properties -V ...

2. Use PowerShell and its newline support by `n (backtick+n)
.\JSignPdfC.exe -ksf C:\client.p12 -ksp 123456 -d C:\Data C:\test.pdf -V --l2-text "Hello`nBye"

3. launch the JSignPdf directly from the Delphi and use line-feed directly (#10):
var
  R: TProcessResult;
begin
  R := RunProcess('"C:\Program Files\JSignPdf\JSignPdfC.exe" -ksf "C:\Users\Lenovo\AppData\client.p12" -ksp 123456 -d C:\Users\Lenovo\AppData "C:\Program Files\JSignPdf\docs\JSignPdf.pdf" -V --l2-text "line 1'+ #10 +'line 2'+ #10 +'etc"');
  Memo1.Lines.Text := R.Output;
  if R.ExitCode <> 0 then
    ShowMessage('Exit code: ' + R.ExitCode.ToString);
end;
---------------------------
{helper unit:}
uses
  Winapi.Windows,
  System.SysUtils,
  System.Classes;

type
  TProcessResult = record
    Output: string;
    ExitCode: Cardinal;
  end;


function RunProcess(const CommandLine: string;
                    const WorkingDir: string = '';
                    const Encoding: TEncoding = nil): TProcessResult;
const
  BUFFER_SIZE = 8192;
var
  SA: TSecurityAttributes;
  ReadPipe, WritePipe: THandle;
  SI: TStartupInfo;
  PI: TProcessInformation;
  Buffer: array[0..BUFFER_SIZE - 1] of Byte;
  BytesRead, TotalAvail: DWORD;
  OutputStream: TBytesStream;
  WaitRes: DWORD;
  WorkingDirPtr: PChar;
  CmdLineBuffer: PChar;

begin
  Result.Output := '';
  Result.ExitCode := Cardinal(-1);

  if WorkingDir<>'' then
      workingdirptr := PChar(WorkingDir)
  else
    WorkingDirPtr := nil;

  // Security attributes for inheritable pipe
  SA.nLength := SizeOf(SA);
  SA.lpSecurityDescriptor := nil;
  SA.bInheritHandle := True;

  if not CreatePipe(ReadPipe, WritePipe, @SA, 0) then
    RaiseLastOSError;

  try
    // Prevent parent from inheriting read handle
    SetHandleInformation(ReadPipe, HANDLE_FLAG_INHERIT, 0);

    ZeroMemory(@SI, SizeOf(SI));
    SI.cb := SizeOf(SI);
    SI.dwFlags := STARTF_USESTDHANDLES;
    SI.hStdOutput := WritePipe;
    SI.hStdError  := WritePipe;
    SI.hStdInput  := GetStdHandle(STD_INPUT_HANDLE);

    ZeroMemory(@PI, SizeOf(PI));
    CmdLineBuffer := StrAlloc(Length(CommandLine) + 1);
    StrPCopy(CmdLineBuffer, CommandLine);

    if not CreateProcess(
      nil,
      CmdLineBuffer,
      nil,
      nil,
      True,  // inherit handles
      CREATE_NO_WINDOW,
      nil,
      WorkingDirPtr,
      SI,
      PI) then
      RaiseLastOSError;

    // Parent must close write end
    CloseHandle(WritePipe);
    WritePipe := 0;

    OutputStream := TBytesStream.Create;
    try
      repeat
        WaitRes := WaitForSingleObject(PI.hProcess, 50);

        while PeekNamedPipe(ReadPipe, nil, 0, nil, @TotalAvail, nil) and
              (TotalAvail > 0) do
        begin
          if not ReadFile(ReadPipe, Buffer, BUFFER_SIZE, BytesRead, nil) then
            Break;

          if BytesRead > 0 then
            OutputStream.WriteBuffer(Buffer, BytesRead);
        end;

      until WaitRes = WAIT_OBJECT_0;

      // Final drain
      while ReadFile(ReadPipe, Buffer, BUFFER_SIZE, BytesRead, nil) and
            (BytesRead > 0) do
      begin
        OutputStream.WriteBuffer(Buffer, BytesRead);
      end;

      if not GetExitCodeProcess(PI.hProcess, Result.ExitCode) then
        RaiseLastOSError;

      try
        Result.Output := TEncoding.UTF8.GetString(
          OutputStream.Bytes, 0, OutputStream.Size);
      except
        on EEncodingError do
          Result.Output := TEncoding.GetEncoding(GetOEMCP).GetString(
            OutputStream.Bytes, 0, OutputStream.Size);
      end;
    finally
      OutputStream.Free;
    end;

    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);

  finally
    if WritePipe <> 0 then
      CloseHandle(WritePipe);
    CloseHandle(ReadPipe);
  end;
end;


Regards,
Josef


čt 19. 2. 2026 v 14:39 odesílatel Rafał Sitek <rav...@gmail.com> napsal:
How to pass custom text with newline characters in the --l2-text parameter (cmd - Windows) - it ignores both #10#13 and Java-style \n

--
You received this message because you are subscribed to the Google Groups "JSignPdf" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsignpdf+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/jsignpdf/c3f7476a-0b91-48a6-9cdb-65ce80699fcfn%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages