Dll error handling

C++ Documentation. Contribute to MicrosoftDocs/cpp-docs development by creating an account on GitHub.
title description ms.date helpviewer_keywords

Error handling and notification

Learn more about: DLL delay load error handling and notification

01/19/2021

error handling, and notification

Error handling and notification

If your program uses delay-loaded DLLs, it must handle errors robustly, since failures that occur while the program is running will result in unhandled exceptions. Failure handling is composed of two portions: Recovery through a hook, and reporting via an exception.

For more information on DLL delay load error handling and notification, see Understand the helper function.

For more information on hook functions, see Structure and constant definitions.

Recovery through a hook

Your code may need to recover on a failure, or to provide an alternate library or routine. You can provide a hook to the helper function that can supply the alternative code, or remedy the situation. The hook routine needs to return a suitable value, so that processing can continue (an HINSTANCE or FARPROC). Or, it can return 0 to indicate that an exception should be thrown. It could also throw its own exception or longjmp out of the hook. There are notification hooks and failure hooks. The same routine may be used for both.

Notification hooks

The delay load notification hooks are called just before the following actions are taken in the helper routine:

  • The stored handle to the library is checked to see if it has already been loaded.

  • LoadLibrary is called to attempt the load of the DLL.

  • GetProcAddress is called to attempt to get the address of the procedure.

  • Return to the delay import load thunk.

The notification hook is enabled:

  • By supplying a new definition of the pointer __pfnDliNotifyHook2 that’s initialized to point to your own function that receives the notifications.

    -or-

  • By setting the pointer __pfnDliNotifyHook2 to your hook function before any calls to the DLL that the program is delay loading.

If the notification is dliStartProcessing, the hook function can return:

  • NULL

    The default helper handles the loading of the DLL. It’s useful to call just for informational purposes.

  • a function pointer

    Bypass the default delay-load handling. It lets you supply your own load handler.

If the notification is dliNotePreLoadLibrary, the hook function can return:

  • 0, if it just wants informational notifications.

  • The HMODULE for the loaded DLL, if it loaded the DLL itself.

If the notification is dliNotePreGetProcAddress, the hook function can return:

  • 0, if it just wants informational notifications.

  • The imported function’s address, if the hook function gets the address itself.

If the notification is dliNoteEndProcessing, the hook function’s return value is ignored.

If this pointer is initialized (nonzero), the delay load helper invokes the function at certain notification points throughout its execution. The function pointer has the following definition:

// The "notify hook" gets called for every call to the
// delay load helper.  This allows a user to hook every call and
// skip the delay load helper entirely.
//
// dliNotify == {
//  dliStartProcessing |
//  dliNotePreLoadLibrary  |
//  dliNotePreGetProc |
//  dliNoteEndProcessing}
//  on this call.
//
ExternC
PfnDliHook   __pfnDliNotifyHook2;

// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook   __pfnDliFailureHook2;

The notifications pass in a DelayLoadInfo structure to the hook function along with the notification value. This data is identical to the data used by the delay load helper routine. The notification value will be one of the values defined in Structure and constant definitions.

Failure hooks

The failure hook is enabled in the same manner as the notification hook. The hook routine needs to return a suitable value so that processing can continue (an HINSTANCE or FARPROC), or 0 to indicate that an exception should be thrown.

The pointer variable that refers to the user-defined function is:

// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
ExternC
PfnDliHook   __pfnDliFailureHook2;

The DelayLoadInfo structure contains all the pertinent data necessary for detailed reporting of the error, including the value from GetLastError.

If the notification is dliFailLoadLib, the hook function can return:

  • 0, if it can’t handle the failure.

  • An HMODULE, if the failure hook fixed the problem and loaded the library itself.

If the notification is dliFailGetProc, the hook function can return:

  • 0, if it can’t handle the failure.

  • A valid proc address (import function address), if the failure hook succeeded in getting the address itself.

Report by using an exception

If all that’s required to handle the error is to abort the procedure, no hook is necessary, as long as the user code can handle the exception.

Delay load exception codes

Structured exception codes can be raised when failures occur during a delayed load. The exception values are specified by using a VcppException macro:

//
// Exception information
//
#define FACILITY_VISUALCPP  ((LONG)0x6d)
#define VcppException(sev,err)  ((sev) | (FACILITY_VISUALCPP<<16) | err)

For a LoadLibrary failure, the standard VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) is thrown. For a GetProcAddress failure, the error thrown is VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND). The exception passes a pointer to a DelayLoadInfo structure. It’s in the LPDWORD value retrieved by GetExceptionInformation from the EXCEPTION_RECORD structure, in the ExceptionInformation[0] field.

If the incorrect bits are set in the grAttrs field, the exception ERROR_INVALID_PARAMETER is thrown. This exception is, for all intents and purposes, fatal.

For more information, see Structure and constant definitions.

See also

Linker support for delay-loaded DLLs

This article will describe pitfalls and «gotcha»s for using and handling exceptions in DLLs. It will also discuss using exception tracer tools in DLLs.

Important Note: please see most recent version of this documentation here.

Content:

  • What is DLL?
  • What is exception?
  • How DLLs report about failures?
  • What is the proper way to handle exceptions in DLL?
    • Framework
    • System or 3rd party API
    • Your own API
  • Using exception tracer tool in DLLs
    • Single instance of exception tracer
    • Multiply instances of exception tracer
  • Using exception tracer with frameworks in DLLs
    • Single instance of exception tracer
    • Multiply instances of exception tracer
  • Conclusion

Important Note: please see most recent version of this documentation here.

Note: this article will use EurekaLog 7.0.4.3 or higher as exception tracer.

What is DLL?

DLL is a library of functions. Application (.exe file) can load DLL (.dll file) and call a function from it. DLL is isolated file, not related to application. Therefore, DLL and application can be written in different programming languages.

Application is often called a «host application» or just «host» . Both DLL and host are also called «executable modules» or just «modules». Sometimes «application» is referred to host with loaded DLLs (not just host itself).

DLL and application need to understand each other. So, a set of rules must be established to communicate. Such set of rules is called «API».

API can be developed by you or some other developers/company. If you’re the API developer — then you can decide how DLL will work with host. If you’re not the API developer — then you can only follow already established rules, but you can’t invent your own rules.

What is exception?

Exception is represented by an object (class instance) in most modern high-level programming languages. This means that exceptions can be inherited from base classes, as well as be extended with arbitrary properties.

Since exception is a way to interrupt normal execution path of a code — it requires support from hardware level. Modern CPUs provides such support. However, user-mode applications do not have direct access to the hardware. Therefore, operating system provides method to use exceptions on particular hardware. This is called SEH («Structured Exception Handling») in Windows.

Exception on operating system level is represented by its address, code, options («flags») and up to 15 4-byte integers («params»). High-level programming languages use SEH and this low-level representation as basis for their own exception handling. For example, exception in high-level programming language (i.e. exception object) is implemented as OS exception with special code (for example: $EEECFADE for Delphi) and pointer to object is stored in exception params. Exceptions with other codes are wrapped in generic class (EExternalException for Delphi).

Short conclusion:

  1. There are 3 levels of exceptions support: hardware, OS, and programming language.
  2. User-mode code has access to OS and language levels.
  3. OS exceptions are compatible among all programming languages.
  4. Language exceptions are specific to programming language and could not be properly used in another programming language.

How DLLs report about failures?

Remember that object and class implementations are specific for programming language and compiler. I.e. a Delphi application doesn’t know how to work with objects/classes from (for example) Microsoft C++ (and visa versa). This means that hi-level exception raised in DLL could not be properly handled by host application, unless both DLL and host are compiled by the same compiler and exception class uses the virtual destructor.

Also note that mixing OS and language exceptions within same module is confusing/problematic thing.

Therefore, APIs for DLLs usually do not use exceptions as a way to report errors. Instead: functions can use error codes — such as numeric codes, success/failure flags (booleans) and so on. There are de facto standard ways to report errors — provided by operating system (for example: GetLastResult, HRESULT — on Windows). However, 3rd party DLLs may use arbitrary error reporting method.

What is the proper way to handle exceptions in DLL?

As you should already understood by now: rule #1 when working with exceptions in DLLs is «never let exception escape DLL». All exceptions in DLL functions must be captured and handled by translating them to error code or other error signature as required by DLL API.

How this should be done? That highly depends on what your DLL API is. This also depends on what framework you do use. There are 3 possible cases:

  1. You develop DLL by using a framework.
    For example: you write a control panel applet by using VCL. Or you write ISAPI module by using IntraWeb.
  2. You develop DLL for already established API without using a ready framework.
    For example: you write a plugin for 3rd party application (like Total Commander). Or you write a global system hook (which requires DLL).
  3. You develop both DLL and API specification.
    For example: you write your own DLL to be used by different applications.

Case 1: Framework

This is the simplest case — because all pitfalls are already handled by a framework. All your code is called by the framework. All exception from your code are handled by the framework. Framework handles exceptions and convert them to something (what is required by the API).

In this case you can just write your code as you usually do. Framework will provide a default handling and error reporting. Some frameworks also allow you to alter default handling (useful for customizations). You should refer to the documentation of your framework if you want to do such customizations. Usually, there is some sort of global Application.OnException event, which you may assign to your handler’s code.

Case 2: 3rd party API

This case is a more complex. Basically, you need to study the API and figure out how you should report about errors in your function. You can not use arbitrary nor default way — because API is already established by someone. It’s not you who develop API. You only develop a DLL.

Let’s consider a little example. Suppose that you want to write a global system hook — the one that is installed via SetWindowsHookEx function. Global hook requires you to place your handler code inside DLL, so that DLL can be injected in all running programs (which makes the hook a global one).

Naturally, API (i.e. communication rules between OS and your code) is already established — it’s defined by Microsoft (as a developer of hooking functions). Therefore, the first thing that you should do is to study documentation for the functions. You pass a pointer to your handler’s code via second argument in SetWindowsHookEx function (lpfn param). Prototype of the handler depends on what kind of hook do you want to use. Let’s use WH_GETMESSAGE hook for this example. This means that we must study description of GetMsgProc callback.

The important part for error handling looks like this:

If code is less than zero, the hook procedure must return the value returned by CallNextHookEx.

If code is greater than or equal to zero, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_GETMESSAGE hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure does not call CallNextHookEx, the return value should be zero.

In other words, your code could not report any failure reason. All that you can do is either return 0 or return whatever CallNextHookEx returns.

Therefore, your DLL code must looks at least like this:

library Project2;

uses
  Windows;

function MyHook(Code: Integer; _wParam: WPARAM; _lParam: LPARAM): LRESULT; stdcall;
begin
  try
    if Code >= 0 then
    begin
      // <- your code
    end;
  except
    // There is no way to report errors, so we must handle all exceptions
  end;
  Result := CallNextHookEx(Code, _wParam, _lParam);
end;  

Usually it’s not a good idea to silently hide all exceptions. If API doesn’t allow you to report about errors — then you should at least implement some kind of logging, so you can store information about exception in the log.

Let’s see another example. Suppose you’re writing a control panel applet without using any framework. This means that you must write and register DLL. DLL must export CPlApplet function. This function will be used for all communication between OS and your code. Description of CPlApplet says:

The return value depends on the message.
For more information, see the descriptions of the individual Control Panel messages.

This means that you also must study each message from the system that you want to process. Luckily, most messages require you to handle errors in the same way:

If the CPlApplet function processes this message successfully, the return value is zero; otherwise, it is nonzero.

So, you should write your DLL at least like this:

library Project2;

uses
  Windows;

function CPlApplet(hwndCPl: HWND; uMsg: UINT; lParam1, lParam2: LPARAM): LongInt; stdcall;
begin
  try
    case uMsg of
      ...
    end;

    Result := 0;
  except
    Result := 1;
  end;
end;

exports
  CPlApplet;

end.

Since you can’t report what is actual report is — a good idea would be to report error to the user. We can safely do this because control panel applet is a single interactive GUI application. Showing error as dialog box is not a good idea for non-interactive applications (such as services) or code that may be used multiply times (such as global hook).

library Project2;

uses
  Windows;

function CPlApplet(hwndCPl: HWND; uMsg: UINT; lParam1, lParam2: LPARAM): LongInt; stdcall;
begin
  try
    case uMsg of
      ...
    end;

    Result := 0;
  except
    on E: Exception do
    begin
      MessageBox(hwndCPl, PChar(E.Message), 'Error', MB_OK or MB_ICONERROR);
      Result := 1;
    end;
  end;
end;

exports
  CPlApplet;

end.

Please note that code above is just example. Not all messages to control panel applet have the same requirements. You should study description of each message that you’re going to handle in your code. For example, CPL_INIT message has different requirements:

If initialization succeeds, the CPlApplet function should return nonzero. Otherwise, it should return zero.
If CPlApplet returns zero, the controlling application ends communication and releases the DLL containing the Control Panel application.

Therefore, you need to use such code to handle CPL_INIT message:

library Project2;

uses
  Windows;

function CPlApplet(hwndCPl: HWND; uMsg: UINT; lParam1, lParam2: LPARAM): LongInt; stdcall;
var
  SuccessCode, FailureCode: LongInt;
begin
  // "If initialization succeeds, the CPlApplet function should return nonzero. Otherwise, it should return zero."
  if uMsg = CPL_INIT then
  begin
    SuccessCode := 1;
    FailureCode := 0;
  end
  else
  // "If the CPlApplet function processes this message successfully, the return value is zero; otherwise, it is nonzero."
  begin
    SuccessCode := 0;
    FailureCode := 1;
  end;

  try
    case uMsg of
      ...
    end;

    Result := SuccessCode;
  except
    on E: Exception do
    begin
      MessageBox(hwndCPl, PChar(E.Message), 'Error', MB_OK or MB_ICONERROR);
      Result := FailureCode;
    end;
  end;
end;

exports
  CPlApplet;

end.

Next example would be a Shell extension. Shell extensions are implemented as COM objects. That means that you need to write and register a DLL, which follows COM rules. A COM rule for error handling is to use HRESULT as return value of any method. There are two ways to work with HRESULT. First one is quite direct: you write a function/method that returns HRESULT and you convert each exception to HRESULT value:

...

function ConvertExceptionToHRESULT(const E: Exception): HRESULT;
begin
  Result := E_FAIL; // <- this is just a simple example
  // See HandleSafeCallException function from ComObj unit to see more complicated example
end;

type
  ICopyHook = interface(IUnknown)
  ['{000214FC-0000-0000-C000-000000000046}']
    function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD): HRESULT; stdcall;
  end;

  TMyHook = class(TInterfacedObject, ICopyHook)
  protected
    function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD): HRESULT; stdcall;
  end;

function TMyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD): HRESULT; stdcall;
begin
  try 
    // your code

    Result := S_OK;
  except
    on E: Exception do
      Result := ConvertExceptionToHRESULT(E);
  end; 
end;

function DllCanUnloadNow: HRESULT; stdcall;
begin
  try 
    if { it's OK to unload DLL } then
      Result := S_OK
    else
      Result := S_FALSE;
  except
    on E: Exception do
      Result := ConvertExceptionToHRESULT(E);
  end; 
end;

...

The second way is to use Delphi wrapper for HRESULT. Delphi compiler provides assisting for HRESULT returning methods via safecall keyword.
Any function like this:

function Funcensten1(... some arguments ...): HRESULT; stdcall;
function Funcensten2(... some arguments ...; out AResult: TSomeType): HRESULT; stdcall;

has the same protype and the same calling convention as such function:

procedure Funcensten1(... some arguments ...); safecall;
function Funcensten2(... some arguments ...): TSomeType; safecall;

In other words, the above code fragments are binary compatible with each other. So, for example, DLL may use first code block and host may use second code block — and both will work correctly.

The difference between HRESULT/stdcall and safecall headers is assisting from Delphi compiler. Each safecall function and method automatically handles all exceptions within itself. Moreover, each call to safecall function/method automatically converts HRESULT return value back to exception.

So, the second way to work with HRESULT is:

...

type
  ICopyHook = interface(IUnknown)
  ['{000214FC-0000-0000-C000-000000000046}']
    procedure CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD); safecall;
  end;

  TMyHook = class(TInterfacedObject, ICopyHook)
  protected
    procedure CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD); safecall;
  end;

procedure TMyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PWideChar;
      dwSrcAttribs: DWORD; pszDestFile: PWideChar; dwDestAttribs: DWORD); safecall;
begin
  // your code
end;

function DllCanUnloadNow: HRESULT; stdcall;
// Unfortunately, it's not possible to customize return code to be S_FALSE for simple function.
// Otherwise DllCanUnloadNow could have been written like this:
//  procedure DllCanUnloadNow; safecall; 
begin
  try 
    if { it's OK to unload DLL } then
      Result := S_OK
    else
      Result := S_FALSE;
  except
    on E: Exception do
      Result := ConvertExceptionToHRESULT(E);
  end; 
end;

...

Converting exception to HRESULT value will be done automatically by Delphi’s RTL code.

Notes:

  • Barebone converting to HRESULT may be insufficient for your needs. It’s possible to customize it by overriding SafeCallException method. See Delphi help for more information.
  • COM also allow you to ship additional information with exception. See SetErrorInfo function.

Case 3: your own API

When you want to develop a new DLL which will be used by many applications («common DLL») or if you want to write an application which may be extended with 3rd party DLLs («plugins») — then you need to develop API, i.e. set of rules which will be used to communications between host and DLLs.

It’s a good idea to provide an informative and easy way to report and handle errors. An easy solution would be to use COM. That’s because COM is relatively modern API, which provides a decent way to work with errors. COM also has support in many frameworks.

If you think that COM is an «overkill» for your application, then you have to develop your own API. It would be a good idea to use HRESULT as base of error handling part in your API. That’s because HRESULT offers a good range of possible error values, it has additional support in Delphi (via safecall) and it’s familiar for many Windows developers.

So, functions from your DLL may looks like this:

library Project2;

uses
  Windows;

procedure Init; safecall; 
// the same as:
// function Init: HRESULT; stdcall; 
begin
  // your code
end;

function DoSomething(A1: Integer; const A2: WideString): Integer; safecall;
// the same as:
// function DoSomething(A1: Integer; const A2: WideString; our AResult: Integer): HRESULT; stdcall; 
begin
  // your code
end;

procedure Done; safecall; 
// the same as:
// function Done: HRESULT; stdcall; 
begin
  // your code
end;

exports
  Init, DoSomething, Done;

end;

Note: it’s also a good idea to use interfaces instead of simple functions in your DLLs. Interfaces allow you to customize safecall handling by overriding SafeCallException method. Interfaces also allow you to simplify memory management and avoid using shared memory manager.

Using exception tracer tool in DLLs

Many developers prefer to use exception tracer tool in their DLLs. Exception tracer collects information about problems in your code, allowing you to diagnose failures more easily.

Remember what exception tracer does to your application:

A typical executable module with exception tracer (EurekaLog is used as example)

Exception tracer includes its code in your module. It also injects some data — debug information and options. Both (code and data) are required for exception tracer to function.

When you have more than just single executable module — things become interesting. Exception tracer could be inserted into one module or into each module:

  1. There is single instance of exception tracer in application
  2. Each module has its own exception tracer code

First case is good when you can afford enabling exception tracer in host application. Centralized management will allow you to reduce performance cost when you have many DLLs. For example, consider application with 50 DLLs (keep in mind «plugins» scenario). Each exception must be analyzed by exception tracer. If each DLL has its own exception tracer — then each exception will be analyzed 50 times. A good idea would be to have only one instance of exception tracer, so information is collected only once. Any DLL can ask central exception tracer for information about exception.
Second case is good when host application is out of your control. Since you can not use exception tracer in host — then the only choice left is to add it to DLL. Each DLL will have its own isolated exception tracer.

Now, let’s examine both cases on practice.

Note: this article will use EurekaLog 7.0.4.3 or higher as exception tracer.

Case 1: Single instance of exception tracer: «DLL» profile

This case require you to enable exception tracer for host application. You should do this in the same way as you do it for typical application without any DLLs. For example, if you have VCL Forms application as the host — then you need to enable EurekaLog for host application and set application type to «VCL Forms Application». This will add EurekaLog code and data into final .exe file. It would also set hook for Forms.TApplication.HandleException method, which will allow to automatically handle exceptions without writing any code.

Now, the host has exception tracer. It will catch any exception regardless of where exception was raised. It will also collect information about each exception. Exceptions from DLL will be also analyzed by tracer in the host.

Each DLL must also has EurekaLog enabled and application type must be set to «DLL». Such settings will inject debug information into DLL, but will not include exception tracer code. Rather DLL will ask host application for information. Please note that majority of EurekaLog settings will be ignored, since there will be no EurekaLog code in your DLL.

Note: it’s not strictly necessary to enable EurekaLog for DLLs in this example. You can just supply debug information and keep EurekaLog off. For example, you may create .map file or use JCL debug information. This will work fine.

Host application loads multiply DLLs with «DLL» profile
(click image to enlarge/zoom in)

Let’s see this on practice. Create a new VCL application and place buttons to invoke functions from DLL.

...

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    FDLL: HMODULE;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FDLL := LoadLibrary('Project2.dll');
  Win32Check(FDLL <> 0);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeLibrary(FDLL);
  FDLL := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  raise Exception.Create('Error Message');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  P: procedure;
begin
  P := GetProcAddress(FDLL, 'Test1');
  Win32Check(Assigned(P));
  P;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  P: procedure;
begin
  P := GetProcAddress(FDLL, 'Test2');
  Win32Check(Assigned(P));
  P;
end;

...

Code is pretty simple: we load DLL on form’s creating and unload it when form is gone. There are 3 buttons on the form to invoke different testing routines. First button raises exception in application itself. The 2nd and 3rd buttons raise exceptions in DLL.

Don’t forget to enable EurekaLog for host and set application type to «VCL Forms Application». That’s all.

Now, create a new DLL project:

library Project2;

uses
  // Added automatically
  EAppDLL, // "DLL" profile

  // Added manually
  Windows,
  SysUtils,
  Classes;

{$R *.res}

procedure Test1;
begin
  // This is just example! It's highly not recommended to do this.
  raise Exception.Create('Error Message');
end;

procedure Test2;
var
  Msg: String;
begin
  // Recommended way: handle exceptions, do not let them escape DLL
  try
    raise Exception.Create('Error Message');
  except
    on E: Exception do
    begin
      Msg := E.ToString + sLineBreak + E.StackTrace;
      MessageBox(0, PChar(Msg), 'Error', MB_OK or MB_ICONSTOP);
    end;
  end;
end;

exports
  Test1, 
  Test2;

end.

This simple DLL exports 2 functions to test exceptions. First function raises exception and lets it escape DLL, so it will be catched by caller. In our test example caller would be the host application. Such approach is not recommended — as it’s already explained above: you should never let exceptions escape DLL. This is done only for example (illustration). It will work correctly for our case, because DLL and exe are both compiled by the same compiler. This will not work properly for generic case. So, it’s only suitable for testing.

Note: if you want to raise exception in DLL and catch it by the caller — then do not use DLLs. Use packages instead. Using packages will guarantee compatible compiler for host and DLL (package). It’s also generally less problematic with all cross-modules communications.

Second function illustrate more correct approach: we catch exceptions in function and handle them somehow. For this example we will do very simple handling: just display error message with stack trace. More proper approach was discussed above: you should use some kind of error indication (such as boolean flag, HRESULT, etc.) to indicate failure condition to the caller.

Now, enable EurekaLog for this DLL and set application type to «DLL».

Note: EAppDLL unit will be added automatically when you set profile to «DLL».

Compile both host and DLL project, run host application.

Hit buttons 1-3.

Typical exception in host application
Call stack shows only items for exe
(click image to enlarge/zoom in)

Exception escaped DLL
Call stack shows mixed exe/DLL lines
Notice line numbers for routine in DLL
(click image to enlarge/zoom in)

Exception did not escape DLL, it was handled by DLL by displaying error message
(screenshot was cut to save space)
Call stack shows mixed exe/DLL lines
Notice line numbers for routine in DLL
(click image to enlarge/zoom in)

Please note that last case was a simple example of trivial exception handling in DLL. You may be not satisfied with looks of error dialog. You may want not just «error message», but complete bug report. To do this — you need to replace the call to MessageBox with a call to exception manager. Normally, it would be ExceptionManager.Handle. However, there is no exception manager in our DLL. We’ll show how to do this below (see «Working with frameworks and exception tracers in DLLs» section).

Case 2: Multiply instances of exception tracer: «Standalone DLL» profile

This case does not require you to enable exception tracer for host application. You can do it, but it’s not required. Typically this approach should be used only when you develop DLLs to be used in non-EurekaLog enabled host. If you have EurekaLog enable for the host — please try to implement case 1 approach above.

Since host application do not necessary have exception tracer — you must to include tracer in each of your DLLs. Each DLL will have exception tracer. All tracers and DLLs will be independent of each other. Each exception will be catched by each exception tracer in each DLL.

Therefore, each DLL must has EurekaLog enabled and application type must be set to «Standalone DLL». Such settings will add exception tracer in DLL and inject debug information.

Host application loads multiply DLLs with «Standalone DLL» profile
(click image to enlarge/zoom in)

Let’s see this on practice. We’ll use the same host application for this example. Of course, it has EurekaLog enabled, but remember that it’s not necessary. You may turn EurekaLog off for host application, if you want. Actually, let’s do this for the sake of better illustration. So, open your host application project, disable EurekaLog for it and recompile (all source code will remain the same as above).

We’ll use the same DLL project for this example. We’ll make only few changes. Open DLL project and change application type from «DLL» to «Standalone DLL». This will also replace EAppType unit in uses clause with multiply EurekaLog units. Also, go to dialogs options and change «None» to any dialog that you like. We will use «MS Classic» for this example.

This could be all, but since now we have full exception tracer on board — why not ask it to handle exceptions? We can replace our old MessageBox with a call to exception manager. So full changed code will looks like:

library Project2;

uses
  // Automatically generated:
  EMemLeaks, 
  EResLeaks,
  EDialogWinAPIMSClassic,
  EDialogWinAPIEurekaLogDetailed,
  EDialogWinAPIStepsToReproduce,
  EDebugExports,
  EDebugJCL,
  ExceptionLog7,

  // Added manually:
  EExceptionManager,
  Windows,
  SysUtils,
  Classes;

{$R *.res}

procedure Test1;
begin
  raise Exception.Create('Error Message');
end;

procedure Test2;
begin
  try
    raise Exception.Create('Error Message');
  except
    ExceptionManager.ShowLastExceptionData;
  end;
end;

exports
  Test1, Test2;

end.

Save all and recompile. Run application and hit all 3 buttons:

Typical exception in host application
There is no bug report, since host application do not have exception tracer

Exception escaped DLL
There is no bug report, since exception was caught by host application (without exception tracer)

Exception did not escape DLL, it was handled by DLL by displaying complete bug report
Call stack shows only lines within DLL
There is no information about exe, because exe do not have any debug infomation
(click image to enlarge/zoom in)

This example gives you full EurekaLog support within DLL, but exe completely lacks any support. It doesn’t even have debug information, so even exception tracer from DLL is unable to display call stack for exe. Of course, this can be fixed by enabling EurekaLog for exe. Just remember that host application is not always under your control.

Working with frameworks and exception tracers in DLLs

The above sections assumed that you write DLLs without using any frameworks. If you use framework (such as VCL or IntraWeb), then your actions will be slightly different. That’s because framework already contain some sort of exception handling code.

A general concept would be the same. You can use either «DLL» or «Standalone DLL» profiles for your DLLs. So the above facts would be the same. Additionally, you have to configure DLLs for your framework. EurekaLog has support for common cases out of the box. For example, if you use Forms unit in your DLL (i.e. your DLL has forms) — then you need to hook Application.HandleException method. This can be done by enabling «VCL Forms application» option on Advanced/Code/Hooks page in EurekaLog project options. This is true for both «DLL» and «Standalone DLL» profiles.

Note: «Standalone DLL» profile with «VCL Forms application» option on Hooks page is equal to «VCL Forms Application» profile. When you enable such options — DLL profile will be switched to «VCL Forms Application» profile. This is normal behavior. After all, a profile is just set of predefined options. If you change options to match another profile — it will be shown as used. There is no build-in profile for «DLL» profile with «VCL Forms application» option, so «DLL» profile will not be changed after enabling option.

Now, let’s change our example to illustrate this on practice. As usual, host application will remain unchanged. All changes will be done for DLL.

Case 1: Single instance of exception tracer: «DLL» profile

Open DLL, enable EurekaLog and set application type to «DLL». Since we’re going to use forms in our DLL — go do Advanced/Code/Hooks page in EurekaLog project options and enable «VCL Forms application» option.

Now, create a new form for DLL, place a button to raise exception:

...

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  raise Exception.Create('Error Message');
end;

...

And change DLL code as:

library Project2;

uses
  // Automatically generated by EurekaLog
  EAppDLL,  // "DLL" profile
  EAppVCL,  // "VCL Forms application" hook

  // Added manually
  EAppType,
  Windows,
  SysUtils,
  Classes,
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

procedure Test1;
begin
  try
    raise Exception.Create('Error Message');
  except
    on E: Exception do
      // Ask exception manager in host application to process this exception
      _ExceptionManagerHandle(E, ExceptAddr);
  end;
end;

procedure Test2;
var
  Form: TForm2;
begin
  try
    Form := TForm2.Create(nil);
    try
      Form.ShowModal;
    finally
      FreeAndNil(Form);
    end;
  except
    on E: Exception do
      // Ask exception manager in host application to process this exception
      _ExceptionManagerHandle(E, ExceptAddr);
  end;
end;

exports
  Test1, Test2;

end.

Normally, if you want to ask EurekaLog to process exception (display error dialog with bug report, send it to developer, etc.) — then you have to call ExceptionManager.Handle. However, we can not do this in our case, because we’ve used «DLL» profile, which means no exception tracer (and no exception manager) in our DLL. That’s why we use _ExceptionManagerHandle function instead of ExceptionManager.Handle.

_ExceptionManagerHandle function is a lightweight exception manager. If there is exception tracer code in current module — the function will invoke it (i.e. ExceptionManager.Handle). If there is no tracer in the module — the function will try to invoke exception manager from host application. If there is no tracer in host application either — the function will act as if EurekaLog was disabled.

Therefore, you can use _ExceptionManagerHandle function to handle exceptions when you don’t know if there will be EurekaLog in your project. This function will automatically use suitable way to process exceptions.

Okay, so the first function in our DLL will just raise exception in DLL function. The difference with first example is that we handle it properly now: there is try/except block which handles exception by asking exception manager from host application to perform full processing (displaying bug report, sending it to developer, etc.).

Second function will create and show a modal form. There is no exception inside function itself, but form contains button to raise exception. This exception will not be catched by our try/except block, because exceptions in form’s event handlers are handled by VCL framework. That’s why we need EAppVCL unit (it contains hooks for VCL). Try/except block in second function will catch exceptions only for form’s creating or destroying.

That’s all. Save all and compile. Run application and hit all buttons. First button is not changed at all. Second button and third button behave differently:

Button #2: Exception did not escape DLL, it was handled by DLL by displaying complete bug report
Call stack shows mixed exe/DLL lines
(click image to enlarge/zoom in)
Button #3: Exception was raised by form. It was handled by VCL.
EurekaLog hook displays full bug report
Call stack shows mixed exe/DLL lines
(click image to enlarge/zoom in)

Case 2: Multiply instances of exception tracer: «Standalone DLL» profile

Open DLL, enable EurekaLog and set application type to «Standalone DLL». Since we’re going to use forms in our DLL — go do Advanced/Code/Hooks page in EurekaLog project options and enable «VCL Forms application» option. Also change dialog to «MS Classic» or any other desired type.

Note: a combination of «Standalone DLL» profile + «VCL Forms application» hook will set the same options as «VCL Forms Application» profile. That’s why you’ll see «VCL Forms Application» instead of «Standalone DLL» in «Application type» option when you open project settings next time. That’s totally expected behavior. You can also initially only switch profile to «VCL Forms Application» and do nothing else — that’s because this profile will set dialogs and turn on hooks for VCL.

The code for both DLL and exe remain unchanged from previous example. Run application and hit the buttons. You should see the same behavior and dialogs as in previous example.

Note that even if visual appearance seems the same — the internals are working differently now. DLL now has its own exception tracer. _ExceptionManagerHandle function will just invoke ExceptionManager.Handle in DLL. It will not try to communicate with exe host.

Conclusion

This article has described the basics for using EurekaLog in DLLs. It’s also useful source of information for learning general concepts of using exceptions in DLLs. Of course, you’re not limited to examples shown in this article. You may extend them or use your own combination of settings. For example, you host application may install callbacks for DLL — to allow DLL to request arbitrary services from the host.

I have developed a project which uses an external dll as FTPServer, I have created the FTP Server on my project like this:

private ClsFTPServer _ClsFTPServer;
_ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);

The Code above creates an instance of FTP server class, the class starts the FTPserver on it’s constructor, it works fine independently as a module while the clients send their request correctly, but when an incorrect request comes to FTP server it throws an exception and cause my application to crash.

How can I handle the exception thrown by the external dll to prevent my application from crashing?

asked Feb 20, 2013 at 9:58

m-abdi's user avatar

m-abdim-abdi

5401 gold badge6 silver badges30 bronze badges

6

I recently answered a similar (ish) question which may prove useful —
Catch completely unexpected error

EDIT. I have to agree with Hans’ comment above — might be an idea to find another FTP server.

Just for completeness, here’s the appdomain/thread exception setup from — http://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx

Application.ThreadException += new ThreadExceptionEventHandler  (ErrorHandlerForm.Form1_UIThreadException);

// Set the unhandled exception mode to force all Windows Forms errors to go through 
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Add the event handler for handling non-UI thread exceptions to the event. 
AppDomain.CurrentDomain.UnhandledException +=
    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Community's user avatar

answered Feb 20, 2013 at 10:32

NDJ's user avatar

NDJNDJ

5,1791 gold badge18 silver badges27 bronze badges

2

In case of using external unmanagedunsafe code, .NET (above .net 4) by default cannot handle Memory Access Violation exceptions that happens inside of dll code.
in order to catch these kind of exceptions, there is three things to do. I did them and it worked for me:

  1. Add these Attributes to the method that exception occurred inside of it :
    (the method that calls the method of the unmanaged code.)

    [HandleProcessCorruptedStateExceptions]
    [SecurityCritical]
    
  2. Add this tag to App.Config file below runtime tag :

    <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true"/>
    <!-- other tags -->
    </runtime>
    
  3. Catch these kind of exception by using System.AccessViolationException exception type :

      try{
            //Method call that cause Memory Access violation Exeption
         }
    catch (System.AccessViolationException exception)
         {
            //Handle the exception here
          }
    

What i said is just the cure for these type of exception. for more information about this exception’s ego and how this approach works, see System.AccessViolationException

answered Mar 17, 2020 at 12:41

Mamo Ghandi's user avatar

Mamo GhandiMamo Ghandi

772 silver badges10 bronze badges

You’ve probably already tried this, but just in case, have you tried wrapping it in a try catch?

try
{
    _ClsFTPServer = new ClsFTPServer(FTPUserName, FTPPassword, FTPPath);
    ...
}
catch(Exception e)
{
    ...
}

answered Feb 20, 2013 at 10:06

Adam K Dean's user avatar

Adam K DeanAdam K Dean

7,35710 gold badges47 silver badges68 bronze badges

4

By putting a try…catch block around every call into the object and its methods.

Something like:

try
{
    // use the DLL in some way
}
catch (Exception e) 
{
    // Handle the exception, maybe display a warning, log an event, etc.)
}

Also note that while running under Visual Studio, if you go to the «Debug» menu and select «Exceptions…» it will allow the debugger to break on ALL exceptions if you start your program under the debugger, and not just unhandled exceptions. Just click the ‘Thrown’ checkbox next to «Common Language Runtime Exceptions».

Server Overflow's user avatar

answered Feb 20, 2013 at 10:24

Scott Earle's user avatar

Scott EarleScott Earle

65811 silver badges20 bronze badges

5

With version 2.0.0, DLL integrations were made possible, but they were not secure. Registry operations are something not possible from .bat files, so I added that. Most importantly, the exec() function used to ignore errors; it now raises errors by default, and there’s an option you can pass in to ignore them as needed.

  • Download source code — 89 KB

Introduction

This article covers the 2.0.2 minor release of the mscript scripting language and runtime

If you’re new to mscript, check out mscript.io for the latest documentation and downloads.

For a developer’s perspective, you can also check out the original article about version 1.0 and the second article about version 2.0.

The project is open source on GitHub.

DLL Security

When I added DLL integration to mscript with version 2.0, I took what you gave me with the path to the DLL, and I used LoadLibrary() and hoped for the best. With this version, I’m requiring that the DLL be alongside the mscript EXE, in C:Program Files (x86)mscript on most systems, and no slashes, no ..’s, just right in that folder. Also, I’m requiring that DLLs be signed by the same subject and publisher as the mscript EXE. I’d like all DLL development to be done in the GitHub mscript solution, where I can build it and sign it and make it part of the installer. If you don’t care about being part of the installer or do any signing, know that if the EXE is unsigned that the DLLs it loads can be unsigned. The DLL directory restriction stands.

Here’s the code for determining the subject and publisher of an EXE or DLL:

bin_crypt.h

#pragma once

#include <string>

namespace mscript
{
    struct bin_crypt_info
    {
        std::wstring publisher;
        std::wstring subject;
    };
    bin_crypt_info getBinCryptInfo(const std::wstring& filePath);
}
bin_crypt.cpp

#include "pch.h"
#include "bin_crypt.h"
#include "utils.h"

#include <wincrypt.h>
#include <wintrust.h>
#pragma comment(lib, "crypt32.lib")

#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)

mscript::bin_crypt_info mscript::getBinCryptInfo(const std::wstring & filePath)
{
    mscript::bin_crypt_info crypt_info;

        std::string exp_msg;
#define BIN_CRYPT_ERR(msg) { exp_msg = (msg); goto Cleanup; }

        DWORD dwEncoding = 0, dwContentType = 0, dwFormatType = 0, dwSignerInfo = 0, dwData = 0;
    HCERTSTORE hStore = NULL;
    HCRYPTMSG hMsg = NULL;
    BOOL fResult = FALSE;
    PCMSG_SIGNER_INFO pSignerInfo = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    LPTSTR szName = NULL;

        fResult =
        CryptQueryObject
        (
            CERT_QUERY_OBJECT_FILE,
            filePath.c_str(),
            CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
            CERT_QUERY_FORMAT_FLAG_BINARY,
            0,
            &dwEncoding,
            &dwContentType,
            &dwFormatType,
            &hStore,
            &hMsg,
            NULL
        );
    if (!fResult)
        return crypt_info;

        fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
    if (!fResult)
        BIN_CRYPT_ERR("Getting binary security signer info failed");
    pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
    if (!fResult)
        BIN_CRYPT_ERR("Allocating signer info memory failed");
    fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwSignerInfo);
    if (!fResult)
        BIN_CRYPT_ERR("Getting signer info failed");

        CERT_INFO CertInfo;
    CertInfo.Issuer = pSignerInfo->Issuer;
    CertInfo.SerialNumber = pSignerInfo->SerialNumber;
    pCertContext = 
        CertFindCertificateInStore
        (
            hStore,
            ENCODING,
            0,
            CERT_FIND_SUBJECT_CERT,
            (PVOID)&CertInfo,
            NULL
        );
    if (!fResult)
        BIN_CRYPT_ERR("Finding signing certificate failed");

        dwData =
        CertGetNameString
        (
            pCertContext,
            CERT_NAME_SIMPLE_DISPLAY_TYPE,
            CERT_NAME_ISSUER_FLAG,
            NULL,
            NULL,
            0
        );
    if (dwData == 0)
        BIN_CRYPT_ERR("Getting certificate issuer length failed");
    szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
    if (!szName)
        BIN_CRYPT_ERR("Allocating memory for certificate issuer failed");
    if (!(CertGetNameString(pCertContext,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,
        CERT_NAME_ISSUER_FLAG,
        NULL,
        szName,
        dwData)))
    {
        BIN_CRYPT_ERR("Getting certificate issuer failed");
    }
    crypt_info.publisher = szName;
    LocalFree(szName);
    szName = NULL;

        dwData =
        CertGetNameString
        (
            pCertContext,
            CERT_NAME_SIMPLE_DISPLAY_TYPE,
            0,
            NULL,
            NULL,
            0
        );
    if (dwData == 0)
        BIN_CRYPT_ERR("Getting certificate subject length failed");
    szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
    if (!szName)
        BIN_CRYPT_ERR("Allocating memory for certificate subject failed");
    if (!(CertGetNameString(pCertContext,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,
        0,
        NULL,
        szName,
        dwData)))
    {
        BIN_CRYPT_ERR("Getting certificate subject failed");
    }
    crypt_info.subject = szName;
    LocalFree(szName);
    szName = NULL;

Cleanup:
    if (pSignerInfo != NULL) LocalFree(pSignerInfo);
    if (szName != NULL) LocalFree(szName);
    if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
    if (hStore != NULL) CertCloseStore(hStore, 0);
    if (hMsg != NULL) CryptMsgClose(hMsg);

            if (!exp_msg.empty())
        raiseError(exp_msg.c_str()); 
    else
        return crypt_info;
}

For this version, I’ve added a new DLL — mscript-registry.dll — for working with registry keys:

msreg_create_key(key)
 - ensure that a registry key exists

msreg_delete_key(key)
 - ensure that a registry key no longer exists

msreg_get_sub_keys(key)
 - get a list of the names of the sub-keys of a key
 - just the names of the sub-keys, not full keys

msreg_put_settings(key, settings_index)
 - add settings to a key with the name-values in an index
 - you can send in number and string settings
 - to remove a setting, pass null as the index value

msreg_get_settings(key)
 - get the settings on a key in a name-values index

NOTE: You can only put REG_DWORD and REG_SV settings. You only get REG_DWORD and REG_SV settings out, others are ignored.

Here’s the source code that powers this DLL:

registry.h

#pragma once
#include "pch.h"

using namespace mscript;

class registry
{
public:
	registry(const object::list& params)
		: m_params(params)
		, m_root_key(nullptr)
		, m_local_key(nullptr)
	{
		if (m_params.empty() || m_params[0].type() != object::STRING)
			raiseError("Registry functions take a first registry key string parameter");
		m_input_path = m_params[0].stringVal();

		size_t first_slash = m_input_path.find('\');
		if (first_slash == std::wstring::npos)
			raiseWError(L"Invalid registry key (no slash): " + m_input_path);

		m_path = m_input_path.substr(first_slash + 1);
		if (m_path.empty())
			raiseWError(L"Invalid registry key (empty key): " + m_input_path);

		std::wstring reg_root;
		reg_root = toUpper(m_input_path.substr(0, first_slash));
		if (reg_root.empty())
			raiseWError(L"Invalid registry key (invalid m_root_key): " + m_input_path);

		if (reg_root == L"HKCR" || reg_root == L"HKEY_CLASSES_ROOT")
			m_root_key = HKEY_CLASSES_ROOT;
		else if (reg_root == L"HKCC" || reg_root == L"HKEY_CURRENT_CONFIG")
			m_root_key = HKEY_CURRENT_CONFIG;
		else if (reg_root == L"HKCU" || reg_root == L"HKEY_CURRENT_USER")
			m_root_key = HKEY_CURRENT_USER;
		else if (reg_root == L"HKLM" || reg_root == L"HKEY_LOCAL_MACHINE")
			m_root_key = HKEY_LOCAL_MACHINE;
		else if (reg_root == L"HKU" || reg_root == L"HKEY_USERS")
			m_root_key = HKEY_USERS;
		else
			raiseWError(L"Invalid registry key (unknown root): " + 
                          m_input_path + L" (" + reg_root + L")");
	}

	~registry()
	{
		if (m_local_key != nullptr)
			::RegCloseKey(m_local_key);
	}

	void createKey()
	{
		DWORD dwError = ::RegCreateKey(m_root_key, m_path.c_str(), &m_local_key);
		if (dwError != ERROR_SUCCESS)
			raiseWError(L"Creating key failed: " + m_input_path + L": " + 
                          getLastErrorMsg(dwError));
	}

	void deleteKey()
	{
		{
			DWORD dwError = ::RegOpenKey(m_root_key, m_path.c_str(), &m_local_key);
			if (dwError != ERROR_SUCCESS)
				raiseWError(L"Opening key failed: " + m_input_path + L": " + 
                              getLastErrorMsg(dwError));
		}

		{
			DWORD dwError = ::RegDeleteTree(m_local_key, m_path.c_str());
			if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND && 
			    dwError != ERROR_TOO_MANY_OPEN_FILES)
				raiseWError(L"Deleting key failed: " + m_input_path + L": " + 
                              getLastErrorMsg(dwError));
		}
	}

	object::list getSubKeys()
	{
		DWORD dwError = ::RegOpenKey(m_root_key, m_path.c_str(), &m_local_key);
		if (dwError != ERROR_SUCCESS)
			raiseWError(L"Opening key failed: " + m_input_path + L": " + 
                          getLastErrorMsg(dwError));

		const size_t MAX_VALUE_LEN = 16 * 1024;
		std::unique_ptr<wchar_t[]> value_name(new wchar_t[MAX_VALUE_LEN + 1]);
		value_name[MAX_VALUE_LEN] = '';

		object::list retVal;
		DWORD result = ERROR_SUCCESS;
		for (DWORD e = 0; ; ++e)
		{
			result = ::RegEnumKey(m_local_key, e, value_name.get(), MAX_VALUE_LEN);
			if (result == ERROR_NO_MORE_ITEMS)
				break;
			else if (result == ERROR_SUCCESS)
				retVal.push_back(std::wstring(value_name.get()));
			else
				raiseWError(L"Enumerating key failed: " + m_input_path + L": " + 
                              getLastErrorMsg(dwError));
		}
		return retVal;
	}

	void putKeySettings()
	{
		if (m_params.size() != 2 || m_params[1].type() != object::INDEX)
			raiseError("msreg_put_settings takes a registry key 
                        and an index of settings to put");
		object::index index = m_params[1].indexVal();

		DWORD dwError = ::RegOpenKey(m_root_key, m_path.c_str(), &m_local_key);
		if (dwError != ERROR_SUCCESS)
			raiseWError(L"Opening key failed: " + m_input_path + L": " + 
                          getLastErrorMsg(dwError));

		for (const auto& name : index.keys())
		{
			if (name.type() != object::STRING)
			{
				raiseWError(L"msreg_put_settings index key is not a string: " 
                            + name.toString());
			}

			object val = index.get(name);
			if (val.type() == object::NOTHING)
			{
				dwError = ::RegDeleteValue(m_local_key, name.stringVal().c_str());
				if (dwError != ERROR_SUCCESS)
					break;
			}
			else if (val.type() == object::NUMBER)
			{
				int64_t num_val = int64_t(round(val.numberVal()));
				if (num_val < 0)
					raiseWError(L"msreg_put_settings value must be a positive integer: " 
                                  + name.toString());
				else if (num_val > MAXDWORD)
					raiseWError(L"msreg_put_settings value must not exceed DWORD capacity: " 
                                + name.toString());
				DWORD dw_val = DWORD(num_val);
				dwError = ::RegSetKeyValue(m_local_key, nullptr, name.stringVal().c_str(), 
				REG_DWORD, LPCWSTR(&dw_val), sizeof(dw_val));
				if (dwError != ERROR_SUCCESS)
					raiseWError(L"Setting number value failed: " + m_input_path + L": " + 
					name.stringVal() + L": " + getLastErrorMsg(dwError));
			}
			else if (val.type() == object::STRING)
			{
				dwError = ::RegSetKeyValue(m_local_key, nullptr, name.stringVal().c_str(), 
				REG_SZ, val.stringVal().c_str(), 
                (val.stringVal().length() + 1) * sizeof(wchar_t));
				if (dwError != ERROR_SUCCESS)
					raiseWError(L"Setting string value failed: " + m_input_path + L": " + 
					name.stringVal() + L": " + getLastErrorMsg(dwError));
			}
			else
				raiseWError(L"msreg_put_settings value is not null, number, or string: " 
                              + val.toString());
		}
	}

	object::index getKeySettings()
	{
		object::index ret_val;
		DWORD dwError = ::RegOpenKey(m_root_key, m_path.c_str(), &m_local_key);
		if (dwError != ERROR_SUCCESS)
			raiseWError(L"Opening key failed: " + m_input_path + L": " 
                        + getLastErrorMsg(dwError));

		const size_t MAX_VALUE_LEN = 16 * 1024;
		std::unique_ptr<wchar_t[]> value_name(new wchar_t[MAX_VALUE_LEN + 1]);
		value_name[MAX_VALUE_LEN] = '';
		for (DWORD i = 0; ; ++i)
		{
			DWORD val_len = MAX_VALUE_LEN;
			DWORD dwValRet =
				::RegEnumValue(m_local_key, i, value_name.get(), &val_len, 
                               nullptr, nullptr, nullptr, nullptr);
			if (dwValRet != ERROR_SUCCESS)
				break;

			const DWORD flags = RRF_RT_REG_DWORD | RRF_RT_REG_SZ;
			DWORD type = 0;
			DWORD data_len = 0;
			dwError =
				::RegGetValue(m_local_key, nullptr, value_name.get(), 
                              flags, &type, nullptr, &data_len);
			if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
				break;
			if (type == REG_DWORD)
			{
				DWORD data_val = 0;
				dwError =
					::RegGetValue(m_local_key, nullptr, value_name.get(), 
                                  flags, &type, &data_val, &data_len);
				if (dwError != ERROR_SUCCESS)
					raiseWError(L"Getting DWORD value failed: " + 
                                m_input_path + L": " + getLastErrorMsg(dwError));
				ret_val.set(std::wstring(value_name.get()), double(data_val));
			}
			else if (type == REG_SZ)
			{
				std::unique_ptr<wchar_t[]> value(new wchar_t[data_len + 1]);
				dwError =
					::RegGetValue(m_local_key, nullptr, value_name.get(), 
                                  flags, &type, value.get(), &data_len);
				if (dwError != ERROR_SUCCESS)
					raiseWError(L"Getting string value failed: " + 
                                m_input_path + L": " + getLastErrorMsg(dwError));
				ret_val.set(std::wstring(value_name.get()), std::wstring(value.get()));
			}
					}

		return ret_val;
	}

private:
	object::list m_params;

	std::wstring m_input_path;

	HKEY m_root_key;
	std::wstring m_path;

	HKEY m_local_key;
};

exec() Error Handling

exec() now raises an error if the exit code of the called program is not zero. exec() takes a second parameter, an index of options, one of which is «ignore_errors«. When set to true, non-zero exit codes do not raise errors. You can still get the error code in the returned index, with the key «exit_code«.

As an example of a real-world mscript, it was a pain dealing with the .bat file, so how about an mscript to…build mscript: (mscript-builder.exe is a copy of a recent mscript EXE, gotta start somewhere).

? arguments.length() != 1
	>> Usage: mscript-builder.exe build.ms version
	>> version should be like "2.0.2"
	* exit(0)
}

$ version = arguments.get(0)
> "Finalizing version " + version

$ ignore_errors = index("ignore_errors", true)

>> Binaries...
* exec("rmdir /S /Q binaries", ignore_errors)
* exec("mkdir binaries")
* exec("xcopy /Y ..mscriptWin32Release*.exe binaries.")
* exec("xcopy /Y ..mscriptWin32Release*.dll binaries.")

>> Samples...
* exec("rmdir /S /Q samples", ignore_errors)
* exec("mkdir samples")
* exec("xcopy /Y ..mscriptmscript-examples*.* samples.")

>> Resource hacking and signing...
$ modules = list("mscript2")
* modules.add("mscript-dll-sample")
* modules.add("mscript-timestamp")
* modules.add("mscript-registry")
@ module : modules
	> "..." + module
	
	$ ext = "dll"
	? module = "mscript2"
		& ext = "exe"
	}
	
	$ filename = module + "." + ext

	* exec("del resources.res", ignore_errors)
	* exec("ResourceHacker.exe -open resources-" + module + 
           ".rc -save resources.res -action compile")
	* exec("ResourceHacker.exe -open binaries" + filename + 
           " -save binaries" + filename + " -action addoverwrite -resource resources.res")
	* exec("signtool sign /f mscript.pfx /p foobar binaries" + filename)
}

>> Building installer
* exec("AdvancedInstaller.com /rebuild mscript.aip")

>> Building site
* exec("rmdir /S /Q ..mscript.ioreleases" + version, ignore_errors)
* exec("mkdir ..mscript.ioreleases" + version)

* exec("mkdir ..mscript.ioreleases" + version  + "samples")
* exec("xcopy samples*.* ..mscript.ioreleases" + version + "samples.")

@ module : modules
	$ ext = "dll"
	? module = "mscript2"
		& ext = "exe"
	}
	
	$ filename = module + "." + ext
	* exec("xcopy /Y binaries" + filename + " ..mscript.ioreleases" + version + ".")
}

>> Finalizing installer
* exec("xcopy /Y mscript-SetupFilesmscript.msi ..mscript.ioreleases" + version + ".")
* exec("signtool sign /f mscript.pfx /p foobar ..mscript.ioreleases" + 
        version + "mscript.msi")

>> All done!

Conclusion and Points of Interest

DLL security is much improved, the core exec() routine now supports reasonable error handling, and you have a simple DLL for working with the registry.

Enjoy!

History

  • 5th April, 2022: Initial version

Hi,

I am working in the Error Handling too I would be very interested in know how to do it the way you explain. Because I could not find anything that explains me how to implement the Error Handling and Checking for a DLL that gets called from a CLFN.

Actually, I would be very happy just if I could associate an error number and message to the «error in» input and «error out» output that the CLFN shows if you select the Default level of Error checking.

You can’t to that! The error cluster of the CLFN is for reporting runtime errors from LabVIEW in trying to load the DLL and execute the function, including possible exceptions when you have configured the CLFN to use high error reporting.

If you want to pass error information from your function to the LabVIEW diagram you have to do it through a function parameter or function return value. I have done both.

Method1: When an error code is returned by all functions I have a common error handler VI that is placed after each CLFN and converts this error code into a LabVIEW error cluster.

Method2: Or you can pass the Error Cluster as extra parameter:

#pragma pack(1)typedef struct {    	LVBoolean status;    	int32 code;    	LStrHandle message;} ErrorCluster;#pragma pack()static MgErr FillErrorCluster(MgErr err, char *message, ErrorCluster *error){    	if (err)    	{            	int32 len = StrLen(message);            	error-&gt;status = LVBooleanTrue;            	error-&gt;code = err;                err = NumericArrayResize(uB, 1, (UHandle*)&amp;(error-&gt;message), len);                if (!err)                {                    	MoveBlock(message, LStrBuf(*error-&gt;message), len);                    	LStrLen(*error-&gt;message) = len;                }     	}   	return err;}MgErr MyFunction(......, ErrorCluster *error){    	MgErr err = error-&gt;code;    	if (!error-&gt;status)    	{                err = CallAPIFunction(.....);                FillErrorCluster(err, "Error here!!!", error);    	}    	return err;}

I then use this error cluster to feed through the VI, not the error cluster from the CLFN itself. The CLFN error is useful during development and debugging to see possible errors and understand why it wouldn’t work, but for most use cases, once the CLFN call has been tested and debugged, the node should not return any runtime error anymore.The function call however might, otherwise the whole exercise to pass the error cluster as parameter is quite senseless :rolleyes:.

  • Remove From My Forums
  • Question

  • Good Day Everyone

    I have a .dll file together with my .exe file but if I remove or delete the .dll file and run the exe,

    It gives me a standard MS.net runtime error message. I want to handle this kind of error like

     using the Try Catch Block, but since try catch block is not applicable at «General Declaration»

    i don’t know what to do next. 

    here’s my codes so far

    ‘DLL Class Library code 

    Public Class Cls_Access
        Class SubCls_Code
            Shared Function SfnAccessCode()
                Dim strPassWord = «admin» ‘unhashed for testing only
                Return strPassWord
            End Function
        End Class
    End Class

    ‘WinForm code

    Imports BUNDY_CLOCK_PASSWORD_DLL.Cls_Access ‘my custom dll

    Public Class Frm_BundyClock
        Private Sub Frm_BundyClock_Load(sender As Object, e As EventArgs) Handles MyBase.Load
                Dim strPassword As String = Mod_Password.pFnPassword
                MsgBox(strPassword)
        End Sub
    End Class

    • Edited by

      Tuesday, February 9, 2016 12:31 PM

Answers

  • You should dynamically load the DLL rather then trying to use IMPORTS.

    Have a look at this example:
    (http://stackoverflow.com/questions/8298122/check-if-dll-file-exists-and-load-it).

    You could also embed your DLL into your application
    like this (C# example but you get the idea http://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource)

    Here
    this is vb.net (attempt at it (http://www.vbforums.com/showthread.php?642512-RESOLVED-Embedding-DLL-resources-into-Executable-%28No-more-ILmerge%29).


    Cyrille Precetti

    • Marked as answer by
      MetalZERO-1
      Wednesday, February 17, 2016 4:38 AM

Скачать сейчас

Ваша операционная система:

Как исправить ошибку Api-ms-win-core-errorhandling-l1-1-1.dll?

Прежде всего, стоит понять, почему api-ms-win-core-errorhandling-l1-1-1.dll файл отсутствует и почему возникают api-ms-win-core-errorhandling-l1-1-1.dll ошибки. Широко распространены ситуации, когда программное обеспечение не работает из-за недостатков в .dll-файлах.


What is a DLL file, and why you receive DLL errors?

DLL (Dynamic-Link Libraries) — это общие библиотеки в Microsoft Windows, реализованные корпорацией Microsoft. Файлы DLL не менее важны, чем файлы с расширением EXE, а реализовать DLL-архивы без утилит с расширением .exe просто невозможно.:


Когда появляется отсутствующая ошибка Api-ms-win-core-errorhandling-l1-1-1.dll?

Если вы видите эти сообщения, то у вас проблемы с Api-ms-win-core-errorhandling-l1-1-1.dll:

  • Программа не запускается, потому что Api-ms-win-core-errorhandling-l1-1-1.dll отсутствует на вашем компьютере.
  • Api-ms-win-core-errorhandling-l1-1-1.dll пропала.
  • Api-ms-win-core-errorhandling-l1-1-1.dll не найдена.
  • Api-ms-win-core-errorhandling-l1-1-1.dll пропала с вашего компьютера. Попробуйте переустановить программу, чтобы исправить эту проблему.
  • «Это приложение не запустилось из-за того, что Api-ms-win-core-errorhandling-l1-1-1.dll не была найдена. Переустановка приложения может исправить эту проблему.»

Но что делать, когда возникают проблемы при запуске программы? В данном случае проблема с Api-ms-win-core-errorhandling-l1-1-1.dll. Вот несколько способов быстро и навсегда устранить эту ошибку.:


метод 1: Скачать Api-ms-win-core-errorhandling-l1-1-1.dll и установить вручную

Прежде всего, вам нужно скачать Api-ms-win-core-errorhandling-l1-1-1.dll на ПК с нашего сайта.

  • Скопируйте файл в директорию установки программы после того, как он пропустит DLL-файл.
  • Или переместить файл DLL в директорию вашей системы (C:WindowsSystem32, и на 64 бита в C:WindowsSysWOW64).
  • Теперь нужно перезагрузить компьютер.

Если этот метод не помогает и вы видите такие сообщения — «api-ms-win-core-errorhandling-l1-1-1.dll Missing» или «api-ms-win-core-errorhandling-l1-1-1.dll Not Found,» перейдите к следующему шагу.

Api-ms-win-core-errorhandling-l1-1-1.dll Версии

Версия

биты

Компания

Язык

Размер

6.3.9600.16384

32 bit

Microsoft Corporation

U.S. English

3 kb

Версия

биты

Компания

Язык

Размер

6.2.9200.16384

32 bit

Microsoft Corporation

U.S. English

3 kb

Версия

биты

Компания

Язык

Размер

10.0.18362.1

32 bit

Microsoft Corporation

U.S. English

11 kb

Версия

биты

Компания

Язык

Размер

10.0.17763.1

64 bit

Microsoft Corporation

U.S. English

11.5 kb

Версия

биты

Компания

Язык

Размер

10.0.10586.0

32 bit

Microsoft Corporation

U.S. English

3 kb

Версия

биты

Компания

Язык

Размер

10.0.10565.0

64 bit

Microsoft Corporation

U.S. English

11.5 kb

Версия

биты

Компания

Язык

Размер

10.0.10240.16384

64 bit

Microsoft Corporation

U.S. English

11.3 kb

Версия

биты

Компания

Язык

Размер

10.0.10240.16384

32 bit

Microsoft Corporation

U.S. English

11.3 kb


метод 2: Исправление Api-ms-win-core-errorhandling-l1-1-1.dll автоматически с помощью инструмента для исправления ошибок

Как показывает практика, ошибка вызвана непреднамеренным удалением файла Api-ms-win-core-errorhandling-l1-1-1.dll, что приводит к аварийному завершению работы приложений. Вредоносные программы и заражения ими приводят к тому, что Api-ms-win-core-errorhandling-l1-1-1.dll вместе с остальными системными файлами становится поврежденной.

Вы можете исправить Api-ms-win-core-errorhandling-l1-1-1.dll автоматически с помощью инструмента для исправления ошибок! Такое устройство предназначено для восстановления поврежденных/удаленных файлов в папках Windows. Установите его, запустите, и программа автоматически исправит ваши Api-ms-win-core-errorhandling-l1-1-1.dll проблемы.

Если этот метод не помогает, переходите к следующему шагу.


метод
3: Установка или переустановка пакета Microsoft Visual C ++ Redistributable Package

Ошибка Api-ms-win-core-errorhandling-l1-1-1.dll также может появиться из-за пакета Microsoft Visual C++ Redistribtable Package. Необходимо проверить наличие обновлений и переустановить программное обеспечение. Для этого воспользуйтесь поиском Windows Updates. Найдя пакет Microsoft Visual C++ Redistributable Package, вы можете обновить его или удалить устаревшую версию и переустановить программу.

  • Нажмите клавишу с логотипом Windows на клавиатуре — выберите Панель управления — просмотрите категории — нажмите на кнопку Uninstall.
  • Проверить версию Microsoft Visual C++ Redistributable — удалить старую версию.
  • Повторить деинсталляцию с остальной частью Microsoft Visual C++ Redistributable.
  • Вы можете установить с официального сайта Microsoft третью версию редистрибутива 2015 года Visual C++ Redistribtable.
  • После загрузки установочного файла запустите его и установите на свой ПК.
  • Перезагрузите компьютер после успешной установки.

Если этот метод не помогает, перейдите к следующему шагу.


метод
4: Переустановить программу

Как только конкретная программа начинает давать сбой из-за отсутствия .DLL файла, переустановите программу так, чтобы проблема была безопасно решена.

Если этот метод не помогает, перейдите к следующему шагу.


метод
5: Сканируйте систему на наличие вредоносного ПО и вирусов

System File Checker (SFC) — утилита в Windows, позволяющая пользователям сканировать системные файлы Windows на наличие повреждений и восстанавливать их. Данное руководство описывает, как запустить утилиту System File Checker (SFC.exe) для сканирования системных файлов и восстановления отсутствующих или поврежденных системных файлов (включая файлы .DLL). Если файл Windows Resource Protection (WRP) отсутствует или поврежден, Windows может вести себя не так, как ожидалось. Например, некоторые функции Windows могут не работать или Windows может выйти из строя. Опция «sfc scannow» является одним из нескольких специальных переключателей, доступных с помощью команды sfc, команды командной строки, используемой для запуска System File Checker. Чтобы запустить её, сначала откройте командную строку, введя «командную строку» в поле «Поиск», щелкните правой кнопкой мыши на «Командная строка», а затем выберите «Запустить от имени администратора» из выпадающего меню, чтобы запустить командную строку с правами администратора. Вы должны запустить повышенную командную строку, чтобы иметь возможность выполнить сканирование SFC.

  • Запустите полное сканирование системы за счет антивирусной программы. Не полагайтесь только на Windows Defender. Лучше выбирать дополнительные антивирусные программы параллельно.
  • После обнаружения угрозы необходимо переустановить программу, отображающую данное уведомление. В большинстве случаев, необходимо переустановить программу так, чтобы проблема сразу же исчезла.
  • Попробуйте выполнить восстановление при запуске системы, если все вышеперечисленные шаги не помогают.
  • В крайнем случае переустановите операционную систему Windows.

В окне командной строки введите «sfc /scannow» и нажмите Enter на клавиатуре для выполнения этой команды. Программа System File Checker запустится и должна занять некоторое время (около 15 минут). Подождите, пока процесс сканирования завершится, и перезагрузите компьютер, чтобы убедиться, что вы все еще получаете ошибку «Программа не может запуститься из-за ошибки Api-ms-win-core-errorhandling-l1-1-1.dll отсутствует на вашем компьютере.


метод 6: Использовать очиститель реестра

Registry Cleaner — мощная утилита, которая может очищать ненужные файлы, исправлять проблемы реестра, выяснять причины медленной работы ПК и устранять их. Программа идеально подходит для работы на ПК. Люди с правами администратора могут быстро сканировать и затем очищать реестр.

  • Загрузите приложение в операционную систему Windows.
  • Теперь установите программу и запустите ее. Утилита автоматически очистит и исправит проблемные места на вашем компьютере.

Если этот метод не помогает, переходите к следующему шагу.


Frequently Asked Questions (FAQ)

QКакая последняя версия файла api-ms-win-core-errorhandling-l1-1-1.dll?

A6.3.9600.16384 — последняя версия api-ms-win-core-errorhandling-l1-1-1.dll, доступная для скачивания

QКуда мне поместить api-ms-win-core-errorhandling-l1-1-1.dll файлы в Windows 10?

Aapi-ms-win-core-errorhandling-l1-1-1.dll должны быть расположены в системной папке Windows

QКак установить отсутствующую api-ms-win-core-errorhandling-l1-1-1.dll

AПроще всего использовать инструмент для исправления ошибок dll

В статье мы опишем все возможные способы, как исправить ошибки DLL Windows 7, 10. Исправление msvcp140 dll, msvcp110 dll, kernelbase dll, comctl32 и других.

DLL – это файлы системных библиотек в Windows. Формально они являются исполняемыми, но запустить их по отдельности не получится. Библиотеки используются другими программами для выполнения стандартных функций сохранения, удаления, печати.

К примеру, когда в одной из программ вы запускаете опцию печати, приложение автоматически подгружает отвечающий за эту функцию файл DLL. Иногда в процессе работы программы появляются системные сообщения о том, что произошла неполадка в работе файла библиотеки. После этого приложение завершает свою работу или вы не можете выполнить определенную функцию. Далее рассмотрим все возможные способы, как исправить ошибки DLL Windows 7, 10. Схема действий одинакова для всех версий ОС.

Причины ошибок в работе библиотек DLL Windows

Так как каждая библиотека отвечает за конкретную функцию, причина ошибки зависит от того, какой файл DLL не отвечает. Наиболее частая неполадка происходит с Windows.dll – это главная системная библиотека, отвечающая за запуск всех приложений и самой операционной системы.

Существуют следующие типы ошибок DLL:

  • «Файл не найден». Возможно, вы удалили нужную библиотеку, переименовали или переместили её в другое место на жестком диске;
  • «Файл отсутствует». Такое сообщение появляется в том случае, если система не может найти нужный объект на диске и часто причиной такой ошибки является работа вредоносного ПО, которое заменило программный код в библиотеке;
  • «Нарушение прав доступа к файлу». С этим типом неполадки пользователи сталкиваются при попытке включения игры. Вместо запуска работ ПО система выдает сообщение о невозможности получения доступа к библиотеке. К примеру, «ошибка msvcr100 DLL»;
  • «DLL не удалось зарегистрировать» — это означает, что произошла фатальная ошибка при установке приложения. Устранить неполадку поможет повторная инсталляция игры.

Большинство ошибок DLL в Windows появляется из-за установки пиратской версии ОС. Как правило, в модифицированных сборках используются вредоносные библиотеки, с которыми не могут взаимодействовать другие приложения. Если вы используете неофициальную версию Виндовс, советуем скачать на сайте Microsoft.com оригинальную копию образа ОС и установить её на свой компьютер.

Другие причины появления проблем с файлами DLL:
  • Случайное удаление файла. Часто при попытке очистить жесткий диск Windows от ненужных файлов пользователи по незнанию удаляют файлы библиотек. Также, деинсталлировать файл может другая программа (вредоносное ПО или утилита для автоматической очистки диска);
  • Отказ оборудования. Если для установки или запуска игры вы используете оптический диск и дисковод, при некачественном материале одного из компонентов может появиться фатальная ошибка, которая повреждает файл запуска с расширением DLL;
  • В системе не установлены последние обновления. Разработчики из Майкрософт всегда рекомендуют устанавливать новейшие апдейты ОС. Это позволяет избавиться от проблем не только с библиотеками, но и с ошибками, которые они провоцируют. Также, обновления защищают систему. Она становиться менее подвержена действию вирусов;
  • Проблемы с драйверами. Когда для конкретной программы или внешнего устройства, которое она использует, не установлены последние версии драйверов, пользователь сталкивается со всевозможными ошибками ОС. Одной из таких проблем может стать ошибка msvcp120 – система не может открыть приложение из-за фатальной ошибки совместимости;
  • Несовместимость технических требований игры и характеристик компьютера. В таком случае, нужно выбрать другую более старую версию приложения и переустановить его или же обновить используемую сборку ОС.

Способ 1 — Ошибочное удаление файла DLL

Если после открытия приложения ничего не происходит, а через несколько секунд появляется сообщение «ошибка msvcr100 DLL» или «ошибка msvcp120 DLL», это означает, что на компьютере нет нужной библиотеки. Возможно, она не была установлена вместе с ОС или файл был удален другой программой.

Системное окно с ошибкой выглядит следующим образом:

как исправить ошибки DLL Windows

Если вы столкнулись с такой проблемой, для начала рекомендуем открыть папку жесткого диска С и в графе поиска вписать название нужного DLL. Часто библиотека просто перемещена в другую папку. Исправить проблему поможет её помещение в директорию CWindowsSystem32 (для 32-х разрядный версий ОС) или в CWindowsSysWoW64 (для 64-х разрядных сборок).

В случае, если на диске «С» вы не нашли нужный файл, на сайте Майкрософт нужно скачать апдейт для программного пакета Visual C++ 2013. Эта утилита настраивает взаимодействие всех системных файлов и исправляет существующие ошибки.

Для скачивания пакета перейдите по ссылке https://support.microsoft.com/ru-ru/help/3179560/update-for-visual-c-2013-and-visual-c-redistributable-package, в таблице выберите свою страну и язык, а затем кликните на ссылке для скачивания.

как исправить ошибки DLL Windows

После инсталляции обновления перезагрузите компьютер и попробуйте повторно запустить программу. Если этот вариант решение не помог, переходите к следующему методу.

Способ как исправить ошибки DLL  – Регистрация библиотеки вручную

Бывают случаи, когда нужна библиотека есть на компьютере пользователя и находится в правильной папке, но программа все равно её «не видит». После установки пакета обновления Visual C++, как правило, тоже ничего не происходит. Как быть в этом случае?

Исправить такую ошибку DLL в Windows 10 и Windows 7 поможет регистрация библиотеки на сервере Майкрософт. Скорее всего, на вашем компьютере установлена корректная версия DLL, но из-за проблем со связью копии ОС и сервером разработчика возникают подобного рода проблемы.

Пользователь может самостоятельно запустить работу службы регистрации и менее чем за 1 минуту добавить существующую библиотеку в список «пригодных» для использования файлов.

Следуйте инструкции:

  • Одновременно нажмите на клавиши Win+R для открытия окна «Выполнить»;
  • Теперь в текстовом поле введите «CMD» и подтвердите действие;

как исправить ошибки DLL Windows

  • В результате, откроется окно командной строки, с помощью которого и будет проводиться регистрация библиотеки. В новой строке введите указанную на рисунке ниже команду. Изменяйте название библиотеке в зависимости от того, какое её имя указано в ошибка запуска приложения.

как исправить ошибки DLL Windows

Важно! Для выполнения регистрации вы должны быть авторизованы в учетной записи администратора системы и компьютер необходимо подключить к интернету. 

Способ 3 — Запуск среды восстановления

Еще один способ быстрого исправления всех ошибок системы – это использование утилиты восстановления. Запустить нужное окно можно с помощью среды Виндовс. Откройте окно параметров нажатием клавиш Win-I.

как исправить ошибки DLL Windows

Затем откройте вкладку «Обновление и безопасность»«Восстановление». В правой части окна промотайте страничку вниз и в разделе «Особые варианты загрузки» кликните на «Перезагрузить сейчас».

Заметьте! В этом же окне вы можете сбросить настройки ОС к заводским параметрам. Если вы хотите полностью восстановить систему и готовы к удалению все программ и файлов, выбирайте этот пункт. С его помощью есть больше шансов навсегда избавиться от ошибок, которые связан с системными библиотеками. 

После выбора особых вариантов загрузки и повторного запуска компьютера вы увидите не рабочий стол системы, а специальное окно Troubleshooting (решение неполадок). Кликните на указанную ниже плитку, чтобы запустить автоматическое сканирование и исправление:

как исправить ошибки DLL Windows

После повторной перезагрузки ОС система ошибки будут исправлены. Пользовательские файлы удалены не будут.

Владельцам Windows 7 недоступна возможность автоматического исправления в режиме перезагрузки, но можно запустить встроенную утилиту диагностики. Для этого зайдите в окно панели управления и в строке поиска введите «Средство проверки». Кликните на первый результат поисковой выдачи.

Следуйте инструкции в окне встроенного помощника для выявления проблем и их исправления:

как исправить ошибки DLL Windows

Способ 4 — Установка отсутствующих DLL и обновление программ

Ранее м уже рассмотрели варианты восстановления ошибочных библиотек. Однако, если в Windows XP, 7, 10 возникла ошибка Kernel32 DLL, рекомендуется переустановить файл вручную. Рассмотрим, как исправить такого рода неполадку.

На веб-сайте разработчика пользователи могут только загрузить пакет программ для комплексного восстановления системных файлов. Если же ваша ОС работает нормально, а проблемы возникли только с одной библиотекой, рекомендуется найти в сети и скачать на компьютер нужный файл вручную.

В интернете есть масса сайтов, предлагающих скачать копии DLL, с проблемами которых пользователи сталкиваются чаще всего. Важно помнить, что не следует ничего скачивать из подозрительных ресурсов, а перед помещением файла в системную папку его нужно обязательно просканировать встроенным брандмауэром и еще одним усыновленным в системе антивирусом. Это поможет избавиться от дальнейших неполадок, если библиотека окажется вирусной.

Среди надежных ресурсов для скачивания системных DLL можно выделить:

  • DLL.ru;
  • Dll-files.ru;
  • Download-dll.ru.

Пользователю необходимо ввести имя недостающей библиотеки и начать её скачивание. Далее поместите полученный файл в системную папку System32 или SysWOW64, в зависимости от разрядности установленной копии ОС. При следующем открытии программы ошибка исчезнет.

Также, рекомендуем обновить программу, с которой возникли неполадки. Часто даже после многократной замены файла библиотеки не удается избавиться от ошибок запуска или работы программы. Это говорит о ом, что в системе установлена несовместимая версия игры или прикладного приложения.

Способ 5 — Переустановка приложения

Еще один способ решения – это простая переустановка программы. Возможно, после возникновения проблем с DLL утилита не «видит» нового файла библиотеки, потому необходимо деинсталлировать программу.

Удаляйте приложения только через окно Панель управления — Установка и удаление программ. После деинсталляции советуем также поискать на диске «С» папки с названием игры, которые могли быть не удалены. Затем перезагрузите компьютер, установите ПО ее раз и попробуйте запустить его. Новая библиотека должна распознаться без проблем.

как исправить ошибки DLL Windows

Способ 6 — Обновление драйверного ПО

Обновление драйверного ПО позволяет устранить ошибки несовместимости установленных программ, аппаратного оборудования и операционной системы. Рассмотрим, как исправить ошибку HAL DLL в Windows 7, 10, ведь именно этот тип неполадки появляется из-за несовместимости компонентов.

Необходимо установить последние обновления для всех компонентов ОС. Зайдите в Диспетчер задач Виндовс. В седьмой версии это можно сделать с помощью окна панели управления, в десятой версии нужно воспользоваться окном поиска по системе.

В окне Диспетчера кликните правой кнопкой мышки на названии компьютера, а затем выберите поле «Обновить конфигурацию». Для установки новых версий драйверов на компьютере должно быть установлено соединение с интернетом.

как исправить ошибки DLL Windows

Способ 7 — Удаление вирусов

Просканируйте систему встроенным Защитником или другим установленным антивирусом. Если в результате сканирования обнаружится, что вирус — это и есть ошибочная библиотека, удалите её с компьютера и загрузите пакет обновления Visual C++ на сайте Майкрософт.

Теперь вы знаете, как быстро исправить ошибки DLL в Windows 10 и Windows 7. Если у вас остались вопросы по восстановлению DLL, оставляйте их в комментариях.

как исправить ошибки DLL Windows

Понравилась статья? Поделить с друзьями:
  • Dll api ms win core synch l1 2 0 dll ошибка
  • Dll advapi32 dll как исправить ошибку windows 7
  • Dll advapi32 dll исправить ошибку при запуске
  • Dlib python error
  • Dle установка файлов шаблонов http error 500