2010-08-09 19 views
6

Tôi đang sử dụng Delphi 2010 và chương trình của tôi muốn có đường dẫn tạm thời của hệ thống. Tôi đang sử dụng TPath.GetTempPath và mọi thứ đang hoạt động tốt ... ít nhất là đối với tôi và đồng nghiệp của tôi. Nhưng trên một số máy khách, phương thức này trả về một đường dẫn bị cắt (dĩ nhiên) không tồn tại. Tôi phát hiện ra rằng vấn đề có vẻ là kết quả từ cuộc gọi cơ bản đến GetLongPathName().Kết quả Delphi TPath.GetTempPath bị cắt

Các mã hoàn chỉnh trông như thế này:

[...] 
var 
TmpDir : String; 
Len : Integer; 
begin 

[... Call to GetTempPath succeeds and we have a valid temp directory in short "~" notation in var TmpDir ...] 

Len := GetLongPathName(PChar(TmpDir), nil, 0);  // Len = 37 
    SetLength(TmpDir, Len - 1);       // We want to set the len of TmpDir to 37 - 1. 
    GetLongPathName(PChar(TmpDir), PChar(TmpDir), Len); // Only 32 (instead of 36) characters are copied - so we have a cropped path - But why?! 

end; 
[...] 

này chỉ xảy ra trên một số hệ thống và tôi không biết tại sao. Tôi tìm thấy một cách giải quyết khó chịu cho điều này, nhưng tôi muốn biết những gì đang xảy ra ở đây.

Ai đó có thể đặt ánh sáng lên điều này không?

+0

Bạn có thể cung cấp cho chúng tôi các ví dụ về tên đường dẫn (đúng) và xấu (thực tế) chính xác không? Nó có thể là một vấn đề mã hóa Unicode hay không? –

+0

Chúng tôi cũng nghĩ rằng ở vị trí đầu tiên, nhưng tên đường dẫn không chứa bất kỳ ký tự nào có thể gây ra sự cố với chuyển đổi Unicode. Tên đường dẫn kết quả của GetLongPathName chỉ thiếu 4 ký tự cuối cùng ("emp \" của "Temp \") - tất cả các ký tự khác đều hợp lệ. – Patrick

+0

Âm thanh như http://qc.embarcadero.com/wc/qcmain.aspx?d=92006 –

Trả lời

4

Có một lưu ý về hàm API này Windows trên các trang An ninh Nội địa:

"Các bộ đệm để đổi lấy GetLongPathName() và tương tự chức năng có thể trả về một cắt ngắn đường dẫn và dẫn đến khó lỗi -find. "

https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/753-BSI.html

Nếu bạn có mã nguồn, bạn có thể kiểm tra nếu vấn đề được mô tả trong bài viết này tồn tại trong việc thực hiện Delphi 2010.

+0

Bạn đúng, tôi thấy rằng quá và "giải pháp khó chịu" của tôi là đặt Len thành MAX_PATH ban đầu và kiểm tra kết quả của GetLongPathName(), nhưng tôi tự hỏi tại sao Embarcadero lại sử dụng cách tiếp cận khác ... nhưng cảm ơn bạn đã đăng bài này, bởi vì nó đã xác minh cách tiếp cận của tôi. – Patrick

+0

Bạn nên báo cáo điều này cho QC. –

+1

Vậy vấn đề là gì? Mã trong câu hỏi chính xác gọi hàm hai lần, phải không? Một lần để tìm ra độ dài yêu cầu và sau đó một lần thứ hai để điền vào bộ đệm cho thực. Mã bạn trích dẫn cấp phát bộ đệm đầu tiên để cuộc gọi đầu tiên đến hàm có thể hoạt động, nhưng nếu nó không thành công, nó sẽ cấp phát bộ đệm mới và sử dụng bộ đệm đó thay thế. Đó thực sự là một sự khác biệt quan trọng? Bài viết là cảnh báo chống lại giả định cuộc gọi đầu tiên sẽ luôn thành công khi đưa ra một bộ đệm có kích thước MAX_PATH. Cảnh báo đó áp dụng cho tình huống này như thế nào? –

3

gì xảy ra nếu bạn cố gắng:

var 
    longpath : string; 

SetLength(longpath,MAX_PATH); 
SetLength(longpath, GetLongPathName(PChar(TmpDir),PChar(LongPath),MAX_PATH)); 

này đã làm việc cho tôi, phiên bản của bạn cắt ngắn con đường.

+0

Đó là những gì tôi đang làm trong "workaround" của tôi - nếu vấn đề xảy ra trên máy của bạn: nó sẽ là thú vị nếu chức năng TPath.GetTempPath() đang làm việc cho bạn? – Patrick

+1

Mã này có thể để lại cho bạn chuỗi dài hơn Max_Path nhưng chỉ được gán các ký tự Max_Path. Tức là, 'Length (longpath)> StrLen (PChar (đường dài))'. Bạn cũng có thể bị bỏ sót với một chuỗi có rác trong đó - các tài liệu không nói những gì hàm lưu trữ trong bộ đệm khi bộ đệm quá nhỏ. Bản tin bảo mật và tài liệu đều mô tả cách tránh vấn đề đó. –

+0

Ok, chúng ta nên đề cập đến ở đây, rằng giá trị trả về của GetLongPathName là quan trọng và cần được kiểm tra. – Patrick

Các vấn đề liên quan