I want to ask whether there is some way to detect missing function in DLL included to my application, while application is running. I know about possibility to import function manualy using HMODULE and check it when calling this function, but I don't want to solve each function call in this way. Idea is to cover function call with some try-catch block or something similar, which doesn't cause application crash. Any solutions? Thanks.
According to MSDN (https://msdn.microsoft.com/en-us/library/1c9e046h.aspx), in C/C++ with MSVC compiler you can do something like this:
#include <windows.h>
#define FACILITY_VISUALCPP ((LONG)0x6d)
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
const DWORD LIB_NOT_FOUND = VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND);
const DWORD FUNC_NOT_FOUND = VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND);
__try
{
MyDLLFunction();
}
__except(GetExceptionCode() == LIB_NOT_FOUND || GetExceptionCode() == FUNC_NOT_FOUND
? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
printf("library or function not found\n");
}
You could try calling the function, which will generate an EntryPointNotFoundException if the function doesn't exist. For example (VB.NET):
Dim MissingFunction as Boolean = False
Try
TheFunction()
Catch ex As System.EntryPointNotFoundException
MissingFunction = True
End Try
Related
I have a Win32 DLL I am trying to convert to be usable from UWP. I need to replace file handling code (CreateFile, ReadFile, etc.) to the WinRT safe equivalents (Windows::Storage::StorageFile). I have the code converted and compiling, but when I run the app I get this exception calling get on the returned async operations and I am not sure how to resolve this.
Ok, took a bit to figure out what I was doing wrong but the correct way to handle this in my case is to wrap my code in a co_routine and then call it using PPL.
IAsyncOperation<int> DoWork()
{
co_await winrt::resume_background();
…
return someValue;
}
int Foo()
{
return create_task([]{
return DoWork().get();
}).get();
}
I have a Windows Form in Visual Studio C++. (CLR)
In the header file I declare bool isRunning (to find if notepad is running):
private:
bool isRunning(LPCSTR pnotepad)
{
HWND hwnd;
hwnd = FindWindow(NULL, pnotepad);
if (hwnd != 0)
{
return true;
}
else
{
return false;
}
}
Now on a checkbox, I want it to check if the process is running.
private: System::Void checkBox2_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
if (bool application::GUI::isRunning)
label1->Text = "cat";
I get this error:
a pointer-to-member is not valid for a managed class
I tried changing it to &isRunning. This gives me the same error as above and
illegal operation on bound member function expression
How can I fix this?
everything with below seems wrong:
if (bool application::GUI::isRunning)
you don't need bool if you don't wanna save the result of function. Either define a variable that's bool and assign the result of function to that:
bool result = isRunning(...);
if(result)
...
or
if(isRunning())
...
application::gui::isRunning expression returns the pointer of isRunning function which you are trying to define as a bool variable.
Lets say you fixed first two as:
LPCSTR arg = ...;
if(application::GUI::isRunning(arg))
label1->Text = "cat";
Which implies that you are calling static function of a GUI class
or a function under the namespace of GUI (also GUI is under application namespace).
My guess is GUI is a Form class so you are trying to invoke and since the function is not static you will get error again. So you have two cases to fix:
if you are getting this error from another function of GUI
LPCSTR arg = ...;
if (isRunning(arg))
label1->Text = "cat";
otherwse you need a pointer to GUI object:
LPCSTR arg = ...;
if (gui-> isRunning(arg))
label1->Text = "cat";
I think you are making function call in incorrect manner.
Probably it should be like below,
if (application::GUI::isRunning())
{
label1->Text = "cat";
}
Above is just a hint to make proper function call - but since isRunning is a private member function, how it can be invoked directly from outside class and that too without creating any object. It is not a static member function. Please check this point.
In SourceMod, how do I check if a plugin exists? I tried the GetFeatureStatus method, but it doesn't work. Any ideas?
If a plugin has registered itself as a Library, you can check if it exists using the LibraryExists command on the name it registered. Traditionally, this name is in all lowercase, but some plugins/extensions use mixed-case, such as SteamTools (which uses "SteamTools").
Having said that, it's generally better to cache whether a library exists instead of constantly calling this command... but then a library can be unloaded or loaded on your without your knowledge. There are functions to catch that.
So, the best way is generally to do something like this (using the NativeVotes plugin as an example).
#undef REQUIRE_PLUGIN
#include <nativevotes>
//global variable
new bool:g_bNativeVotes = false;
public OnAllPluginsLoaded()
{
g_bNativeVotes = LibraryExists("nativevotes");
}
public OnLibraryAdded(const String:name[])
{
if (StrEqual(name, "nativevotes"))
{
g_bNativeVotes = true;
}
}
public OnLibraryRemoved(const String:name[])
{
if (StrEqual(name, "nativevotes"))
{
g_bNativeVotes = false;
}
}
If a plugin isn't registered as a library, you can use GetFeatureStatus to check for a particular native. The catch is in realizing that this function doesn't return a bool, but rather a FeatureStatus_ value.
For instance, here's how I'd check for a (in development) feature for the same plugin as mentioned above:
if (GetFeatureStatus(FeatureType_Native, "NativeVotes_IsVoteCommandRegistered") == FeatureStatus_Available)
{
// Do something with vote commands.
}
I have created a GUI using tcl. I want to make some of the core functionalities of the tcl code available to be used by any program which supports dll. For that i have taken a very simple tcl code example, which adds two integer numbers and i have written a c wrapper function to use this functionality. This is working for me. Now how can i create a dll for these two c and tcl files, so that any program can use this addition functionality by simply loading the dll.
Here is my simple tcl code :
/* Filename : simple_addition.tcl */
#!/usr/bin/env tclsh8.5
proc add_two_nos { } {
set a 10
set b 20
set c [expr { $a + $b } ]
puts " c is $c ......."
}
And here is my c wrapper function which uses the above tcl addition functionality :
#include <tcl.h>
#include <tclDecls.h>
#include <tclPlatDecls.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
Tcl_Interp *interp;
int code;
char *result;
printf("inside main function \n");
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
code = Tcl_Eval(interp, "source simple_addition.tcl; add_two_nos");
/* Retrieve the result... */
result = Tcl_GetString(Tcl_GetObjResult(interp));
/* Check for error! If an error, message is result. */
if (code == TCL_ERROR) {
fprintf(stderr, "ERROR in script: %s\n", result);
exit(1);
}
/* Print (normal) result if non-empty; we'll skip handling encodings for now */
if (strlen(result)) {
printf("%s\n", result);
}
/* Clean up */
Tcl_DeleteInterp(interp);
exit(0);
}
This c wrapper is working fine for me and gives correct results.
Now I want to create a dll file, so that if i include that dll to any program that supports dll, it should be able to use this addition functionality of the above tcl code. Can anybody please tell me the way i can do it. Please help me. I am new to this dll concept.
In order to create the .dll you'll have to use something like Visual Studio and C or C++ to create the .dll (there are lots of other tools out there that can create .dll files but VS is easy to get hold of and to use.) So in VS create a new project, this needs to be a C++ WIN32 project. Select the DLL application type and the Export Symbols additional option.
VS will create a basic .dll that you can then amend to do what you want. I short I'd look at putting the creating/destruction of the intrepter into the dllmain:
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
Tcl_FindExecutable(NULL);
interp = Tcl_CreateInterp();
}
case DLL_THREAD_ATTACH:
break ;
case DLL_THREAD_DETACH:
break ;
case DLL_PROCESS_DETACH:
{
Tcl_DeleteInterp(interp);
break;
}
}
return TRUE;
}
and then create functions exported by the .dll that make use of the interpreter. If you aren't familiar with the concept of shared libaries then I'd suggest spending a little time reading up on them, try here and here for some background reading.
I've run into this problem before, but never in a situation like this. I'm completely confused. As the question states, I'm getting the runtime error "Object reference not set to an instance of an object." Using the debugger tools, I think I've pinpointed the problem to this line:
dataFileLocation = path;
The entire function is here:
void DATReader::SetPath(String^ path)
{
if(!File::Exists(path))
{
MessageBox::Show( "DATReader (missing dat file: \n"+path+"\n )", "Error", MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
return;
}
dataFileLocation = path;
}
dataFileLocation is declared here, but nothing is assigned to it:
ref class DATReader
{
private:
System::String^ dataFileLocation;
// ...
}
Now I know the reason I'm getting the error is because dataFileLocation is assigned to nothing. But I'm having problems assigning it. When I add = 0; to it, it won't build because its a ref class. When I try to assigned it to = 0; in the constructor, it yells at me for trying to convert it from a System::String^ to an int. If I assign it to a = gcnew String(""); it builds, but throws the same runtime exception.
I don't get it, am I reading the debugger wrong, and this isn't the source of the problem at all? I've just started to use managed code recently, so I'm confused :\
You may want to check and make sure your DATReader object isn't null as well It may be throwing the exception at your DATReader.SetPath() call.
This is a nicety in C# that's missing in C++/CLI. C# generates code that ensures this can never be null. Easily seen in the debugger by setting a breakpoint on the method and inspecting "this". Here's an example program that reproduces the exception:
#include "stdafx.h"
using namespace System;
ref class Example {
String^ dataFileLocation;
public:
void SetPath(String^ path) {
dataFileLocation = path; // Set breakpoint here and inspect "this"
}
};
int main(array<System::String ^> ^args)
{
Example^ obj /* = gcnew Example */;
obj->SetPath("foo");
return 0;
}
Remove the /* */ comments to fix. Fix your code by looking at the call stack to find the method that forgot to instantiate the object.
Managed C++ uses nullptr for null references. So you can check:
if (path == nullptr) { ... }
or use:
if (!String::IsNullOrEmpty(path))