2009-01-22 26 views
6

Tôi có một quá trình tự nâng cấp được thực hiện khi exe ứng dụng chính của tôi khởi chạy một exe cập nhật và xử lý chính nó trên dòng lệnh. Các exe ứng dụng sau đó gọi ExitProcess để thoát ra, và các cuộc gọi updater WaitForSingleObject trên đã qua trong xử lý để chờ cho exe ứng dụng chấm dứt.Khi nào các cửa sổ báo hiệu một quá trình xử lý?

WaitForSingleObject sẽ đợi. Cho đến khi ứng dụng gọi ExitProcess thì trình cập nhật không hoạt động.

Tuy nhiên, đôi khi, khi trình cập nhật cố gắng ghi đè lên các dll ứng dụng bằng các phiên bản mới, tôi nhận được lỗi khóa tệp mà phiên bản hiện tại của trình cập nhật của tôi coi là lỗi không thể khôi phục và chấm dứt. Dường như bao gồm một giấc ngủ tùy ý (100) là đủ để bỏ qua "vấn đề" này nhưng tôi thực sự ghét mã như thế. thực sự ghét.

Có vẻ như rất kỳ quặc đối với tôi rằng quá trình xử lý có thể được báo hiệu trong khi ứng dụng chính vẫn còn đủ sống để có tệp dll bị khóa.

Trả lời

1

Như câu trả lời khác chỉ ra, quá trình xử lý được hiệu khi quá trình đã ngừng thi công, và hệ điều hành có thể mất một chút thời gian để giải phóng DLLs.

Bạn có quyền dựa vào Sleep (100) là một ý tưởng tồi.Thay vào đó, bạn nên ghi đè lên các tệp DLL của mình trong vòng lặp như sau:

BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) { 
    int tries = 150; 
    while (tries--) { 
    if (TryUpdateDll(dll_name, whatever)) 
     return TRUE; 
    Sleep(200); 
    } 
    return FALSE; 
} 

Điều này tiếp tục cố gắng tải DLL của bạn trong 30 giây và sau đó từ bỏ. 30 giây là đủ ngay cả khi hệ thống đang chịu tải nặng, nhưng vẫn sẽ bảo vệ cập nhật của bạn khỏi bị treo mãi mãi. (Trong trường hợp UpdateDll trả về FALSE, hãy chắc chắn trình bày một thông báo lỗi có ý nghĩa cho người dùng của bạn, nêu rõ tên của vi phạm DLL.)

Nếu bạn đang gây rối với COM, một cuộc gọi đến CoFreeUnusedLibraries trước khi bỏ cũng có thể hữu ích. (http://msdn.microsoft.com/en-us/library/ms679712.aspx) Thành thật mà nói, tôi không biết nếu COM có thể giữ DLL ngay cả sau khi quá trình của bạn thoát, nhưng tốt hơn là an toàn.

Điểm mấu chốt là có rất nhiều điểm kỳ lạ trong Win32 API. Bạn không phải đối phó với mọi trường hợp miễn là bạn có thể tìm thấy một giải pháp có thể chấp nhận được. Rõ ràng là giấc ngủ (100) có thể bị phá vỡ, nhưng một vòng lặp bỏ phiếu dài 30 giây có vẻ chấp nhận được với tôi.

2

Quá trình báo hiệu khi mã ứng dụng thoát. Nó có thể mất hệ điều hành một chút thời gian để dỡ bỏ quá trình hoàn toàn. Điểm của tín hiệu là nói "Tôi đã làm xong những gì tôi cần làm", nó có hiệu quả hơn để phát hành mã khác có thể có những thứ thực sự hữu ích để làm thay vì làm cho mã chờ trong khi hệ điều hành thực hiện một số dịch vụ vệ sinh.

+0

Dường như - thực tế - xử lý xử lý sẽ được báo hiệu ngay sau khi có mã thoát hợp lệ để trả về từ GetExitCode(). Tuy nhiên, xét về các trường hợp sử dụng phổ biến, các ứng dụng thích hợp nhất để chờ xử lý xử lý là các trình cài đặt/cập nhật cần biết khi nào chúng có thể xóa nội dung. –

0

Có thể do các tệp DLL bị khóa bởi một số quy trình khác tại thời điểm đó. Một cách để kiểm tra điều này sẽ là tạo ra một báo cáo về bất cứ điều gì đang nắm giữ vào DLL khi điều này xảy ra.

0

Đã thấy phát ban này với một số phần mềm diệt vi rút khoảng sáu tháng trước. Hãy thử mà không có AV, và ít nhất, đảm bảo AV được cập nhật.

0

Nếu bất kỳ của DLL bạn đang sử dụng đang sử dụng đề, họ có thể không chấm dứt (hoặc tham gia) đủ nhanh nếu bạn không dỡ bỏ một cách rõ ràng họ- đó sẽ đương nhiên xảy ra nếu bạn đã nạp một cách rõ ràng họ sử dụng LoadLibrary

Hãy xem ở đây: http://msdn.microsoft.com/en-us/library/ms682596(VS.85).aspx

Cụ thể dòng này:

... các DLL được bốc dỡ khi quá trình chấm dứt hoặc gọi FreeLib chức năng rary và tham chiếu số trở thành số không. Nếu quá trình chấm dứt do kết quả của hàm TerminateProcess hoặc TerminateThread , hệ thống sẽ không gọi hàm mục nhập DLL.

0

có thể sửa chữa cho bạn ... trong khi bạn không thể thay thế dll được sử dụng, bạn có thể đổi tên nó. vì vậy nếu bạn có một dll mà bạn cần phải thay thế, nhưng nó được sử dụng vì một số lý do, đổi tên nó thành .delete hoặc một cái gì đó như thế. thực hiện cập nhật, sau đó tìm kiếm chương trình chính của bạn cho bất kỳ tệp .delete nào và xóa chúng khi khởi động.

-don

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