Konwersja ścieżki zawierającej polskie znaki

0

Witam

Problem może banalny ale nie umiem sobie poradzić.
Wywołuję ShellExecute, gdzie ścieżka do pliku wykonywalnego może zawierać polskie znaki. W ShellExecute przekazuję także parametry z jakimi uruchamiany ma być plik wykonywalny.
Jeśli ścieżka do pliku wykonywalnego nie zawiera polski znaków, jest ok, czyli kod:

ShellExecute(Handle, 'open', PChar(ExtractFilePath(Application.ExeName)+'PlikWykonywalny.exe'), PChar(parametry), nil, SW_NORMAL);

działa bez problemu.
Problem pojawia się gdy w ścieżce wystąpią polskie znaki. I teraz nie wiem czy w dobrym kierunku zmierzam: Udało mi się sprawdzić, że konwersja tej ścieżki przy pomocy Utf8Encode lub AnsiToUtf8</code> lub <code>SysToUtf8</code> (konwersję ścieżki testowo "podstawiłem" do Label.Caption) daje pożądany efekt, tzn zamiast pytajników w ścieżce mam polskie znaki. Nie mam za to kompletnie już pomysłu jakiej konwersji użyć przy <code>PChar(parametry)...

Całość dzieje się na Lazarusie 1.4.2, FPC 2.6.4.

pozdrawiam
Wojtek

0

Spróbuj poniższego rzutowania i funkcji ShellExecuteW:

PWideChar(UTF8ToUTF16(AnsiToUTF8(ExtractFilePath(Application.ExeName) + 'PlikWykonywalny.exe')))

Pamiętaj, że literały domyślnie kodowane są w multibajtowym UTF-8, a nie w ANSI; Z kolei znaki diakrytyczne (nie tylko "lokalne") obsłuży funkcja ShellExecuteW, ale ona potrzebuje PWideChar i UTF-16, stąd tyle konwersji;

Pomysł zaczerpnięty z mailinglisty znalezionej w Google.

0

Otrzymuję komunikat

Error: Identifier not found "UTF8ToUTF16"

Coś muszę dodać do Uses?

0

Tak, musisz dodać moduł LazUTF8; Znajduje się on w paczce (package) LCL, więc jeśli piszesz aplikację konsolową to trzeba będzie i tę paczkę dodać do projektu; A jeśli piszesz aplikację okienkową to będziesz miał dostęp do tego modułu.

0

Coś takiego:

ShellExecuteW(Handle, 'open', PWideChar(UTF8ToUTF16(ExtractFilePath(Application.ExeName) + 'stany_magazynowe.exe')), PWideChar(parametry), nil, SW_NORMAL);

Niestety nie działa. Całość się kompiluje ale nie działa. Jak zrobię "podgląd" na labelu to widzę pytajniki w miejscu polskich znaków... :(

2

Zgubiłeś konwersję AnsiToUTF8; ExtractFilePath zwraca łańcuch kodowany w ANSI, a nie w UTF-8;

Jak zrobię "podgląd" na labelu to widzę pytajniki w miejscu polskich znaków...

Aby poprawnie wyświetlić zawartość łańcucha kodowanego w UTF-8, font ustawiony dla etykiety musi zawierać rozszerzony zestaw znaków; Jeśli używasz np. fontu Tahoma czy tych obecnych od nowości w systemie to nie będzie problemu.

0

Twoje rozwiązanie wydaje się być strzałem w dziesiątkę. Teraz czeka mnie konwersja reszty ścieżek... i walka z parametrami... ;-)

Do pliku wykonywalnego, w ShellExecuteW przesyłam dwa parametry (cyfry i tekst - tutaj już bez polskich znaków). W programie wykonywalnym odbieram te parametry w zdarzeniu FormShow: parametr1:=paramstr(1); oraz parametr2:=paramstr(2); Podejrzewam, że parametry są przekazywane tylko trzeba je znowu przekonwertować w tym drugim programie... Zmienne parametr1 i parametr2 są typu string.

pozdrawiam
Wojtek

1

Jeśli w ShellExecuteW podajesz parametr kodowany w UTF-16 to aby uzyskać z niego łańcuch kodowany w UTF-8, musisz przekonwertować go funkcją UTF16ToUTF8.

0

Ok, co robię źle:

parametr1:=UTF8ToAnsi(UTF16ToUTF8(paramstr(1)));  
parametr2:=UTF8ToAnsi(UTF16ToUTF8(paramstr(2)));
0

Wyklucz UTF8ToAnsi, bo oczekujesz łańcucha kodowanego natywnie, czyli w UTF-8; A tak w ogóle to w jakim kodowaniu potrzebujesz mieć łańcuch? Ten przekazany w parametrze uruchomieniowym;

PS: Tak przy okazji - można użyć TProcess i nie bawić się z API Windowsa (rozwiązanie niezależne).

0

@wotik - sprawdź poniższe rozwiązanie:

uses
  Process;

{..}

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TProcess.Create(nil) do
  try
    Executable := 'C:\Program.exe';
    Parameters.Add('C:\Zażółć\Gęślą\Jaźń\Plik.txt');
    Execute();
  finally
    Free();
  end;
end;

To jest metoda przycisku w programie głównym, który uruchamia program podrzędny (Program.exe); W tym podrzędnym odbieraj parametry funkcją ParamStrUTF8 - powinno działać.

0

Postaram się to sprawdzić jutro, bo dziś już nie mam siły się z tym męczyć ;-). Jeszcze raz dzięki za pomoc i zaangażowanie.

1

Pod najnowszym Lazarusem (dzisiaj skompilowany z repo na githubie) i Free Pascalem (wczorajszym):

Projekt 1:

procedure TForm1.Button1Click(Sender: TObject);
var path:string;
    params:string;
begin
  path:=ExtractFilePath(Application.ExeName)+'żółć.exe';
  params:='ąćę 日本語 فارسی';
  label1.caption:=path;
  label2.caption:=params;
  ShellExecuteW(Handle, 'open', pwidechar(unicodestring(path)), pwidechar(unicodestring(params)), nil, SW_NORMAL);
end;

Projekt 2:

procedure TForm1.FormCreate(Sender: TObject);
begin
  label1.Caption:=ParamStr(1);
  label2.Caption:=ParamStr(2);
  label3.Caption:=ParamStr(3);
end;

efekt:
żółć.PNG

żadnych skomplikowanych utf8tocośtam, tylko to pwidechar(unicodestring(path))

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.