Archive: Detect Graphics Card Specs? + More


Detect Graphics Card Specs? + More
Greetings!

I was wondering if there have been any discussions about how to detect the specs on the graphics card on a users computer with NSIS?

For example: My application cannot run on a computer that does not have a DirectX Compatable 32MB 3d Graphics Card.

I have seen some entries in the registry regarding DirectX version and the video driver provider but nothing that gives me all the information that I need.

How about a sound card? or a 101 key keyboard and at least 2 button mouse?

Are there some functions in the plugins that might help me to gather this information? Is there a place where I can find prototypes and/or descriptions for the functions included in the plugins?

Thanks in advance for any information regarding this.

Matthew Win Tibbals


Maybe you can search for information about how to detect this information using C/C++, so you can write a NSIS plugin.


Yes.. yes.. that is what I am trying to avoid.. if I do end up having to write my own I'll be sure to post it.

On a different note, some useless information: I work only a few blocks from the Nullsoft HQ in Potrero. (@ 20th and Florida)


There is no plug-in available, so you have to write your own.


Is there a place where I can find prototypes and/or descriptions for the functions included in the plugins?
Take a look at each plugin's readme file.

The System plugin might help you if you just want to call a few Windows API functions without writing your own plugin.

Hello,

I have not given up on this yet so don't worry.

I have found a function in an existing dll that will return the amount of video memory available to the user. This is the syntax that I am using to try and call the function that I need:

System::Call "D3D8::GetAvailableTextureMem() i().r2"
MessageBox MB_OK "Texture Memory: $2"

Here is the prototype to the GetAvailableTextureMem function:

UINT GetAvailableTextureMem();

The function call does not work as is because the GetAvailableTextureMem function needs to be accessed from a IDirect3DDevice8 object. Is there a way in NSIS to access the function that I need or do I need to create my own dll that creates the needed objects to access the needed function.

Thanks for any advice or feedback.

MWT


I think you'll need a DLL. I say this because you can't just call that function on it's own like you realised, and in fact it's quite involved. You have to (I think) create a window, initialise Direct 3D 8, create the device, query it, release the device, release D3D, destroy the window. You might be able to skip the window creation step, and since you are only querying the device you might be able to do that without creating the device, but you still need to initialise Direct 3D and get a D3D8 device pointer at the minimum.

Microsoft give a crappy example of the basic D3D8 device creation steps here.


Cool! So I have the DLL built and I can call it from a Win32 Client program that I also put together. I can't for some reason seem to be able to call if from NSIS. If I try to return a variable the variable is always error. It does not seem like it is accessing the DLL at all.

Here is the function calls I have been making from my NSIS script:

System::Call 'SystemRequirements::GlobalGetTextureMemory(v) v()'
System::Call 'SystemRequirements::GlobalGetTextureMemory(v) 1() .r2'

Here are the function prototypes that I have been trying:

void GlobalGetTextureMemory() //I just had this spawn a message box for testing but not successfully
int GlobalGetTextureMemory()

I created a function that can be accessed globally which returns the TextureMemory of a users computer.

I checked through System.txt and a lot of other forum postings but did not see anything obvious that I should be doing in order to get this to work.

Thanks a lot for any help!

Thanks,

MWT


First of all, it should be GlobalGetTextureMemory(v) i() .r2 not GlobalGetTextureMemory(v) 1() .r2 [notice the i instead of 1].

System usually fails when it can't find the plug-in or can't find the exported function in it. Since you've said you've called from another client program it must be the first reason.

But why would you want to use System.dll to call a function from your own plug-in? Why not just create a NSIS plug-in? Have a look at Contrib\ExDLL for a plug-in skeleton and other directories for more examples.


err... that "1" was a typo.. thanks for catching it.

I have the project from Contrib\ExDLL open and I have been playing around with it. I am still having some problems connecting to it from NSIS.

From the ExDLL project in the function "myFunction" I think I can see how variables are returned through double pointers but I am having some trouble getting it to work though.

where it says "// do your stuff here" I added the following lines for testing purposes:

DWORD dwStringSize = g_stringsize;
stack_t *th;
if (!g_stacktop) return;
th = (stack_t*) GlobalAlloc(GPTR, sizeof(stack_t) + g_stringsize);

strcpy(th->text, "Hello There!");

th->next = *g_stacktop;
*g_stacktop = th;

(the UserInfo plugin code was very helpful)

When I try to compile the NSI script I get an error on the line where I try to access exdll::myFunction

ClearErrors
exdll::myFunction
IfErrors done

pop $0
MessageBox MB_OK "test function2 $0"
done:

From the sample code that I checked out in some of the other projects it looks like this should work. There must be something that I am not doing in order to link the NSIS setup executable to my dll.


You don't really need all that code. exdll.h contains functions to interact with the stack. UserInfo just uses optimized code to its purpose. Use pushstring and popstring instead.

To make NSIS recognize your plug-in put it in <nsis dir>\plugins. Make sure your function appears on the list on the top of the compiler output along with all of the other plug-in functions.


Thank you for all of your help! I am very close now.

I can see my function processed in the compiler output although it looks different from the others. Here is how it looks:

exdll::?myFunction@@YAXPAUHWND__@@HPADPAPAU_stack_t@@@Z

The others don't have the '?' and the '@@YAXPAUHWND__@@HPADPAPAU_stack_t@@@Z' attached to them.

Right now it is in the middle of the compiler output. (it looks like it goes alphabetically) How can I make sure that mine is at the top? (should I just rename it aaExDll?)

Also, when I try to compile my NSI script I get a "Invalid command: exdll::myFunction" when I try to access the function in the NSI script.

Thanks in advance for any more help.

MWT

---addition a few minutes later---

I got it to work by pasting

exdll::?myFunction@@YAXPAUHWND__@@HPADPAPAU_stack_t@@@Z

into the NSI script as my function call. I suspect that the extended function name is because I changed the exdll.c file to a exdll.cpp file. Is that a bad idea?

The installer is throwing an error in it execution. It spawns a messagebox entitled "Error" and the text reads "$0=" it happens before the MessageBox that I spawn in the following code: (perhaps something to do with the pop command)

Section "" ;No components page, name is not important

ClearErrors
exdll::?myFunction@@YAXPAUHWND__@@HPADPAPAU_stack_t@@@Z
IfErrors done
pop $0
MessageBox MB_OK "test function2 $0"
done:
SectionEnd ; end the section

Am I illegally using the pop command here?

Thanks again!

MWT

-----------another addition--------------

I changed exdll.cpp back to exdll.c and I still get the same error. By placing messageboxes I can tell that the error is thrown with my function call. Here are the additions that I made to the exdll.c file in order to get it wo work:

// do your stuff here

pushstring( "Testing");


I got the error to go away by calling "return;" right after "pushstring("Testing")" in my dll code.

Sorry for the long-ass posts and thanks for all of your help!


The first error (with the function name) was indeed caused because you have changed the the file extension to .cpp. If you want to use .cpp add 'extern "C"' before the function declaration to make it a C export and not C++ export (take a look at InstallOptions for an example).

The second error is not actually an error but the code itself in the plug-in:

char buf[1024];
wsprintf(buf,"$0=%s\n",getuservariable(INST_0));
MessageBox(g_hwndParent,buf,0,MB_OK);


This code copies the string "$0=$0" where the second $0 is the actual value of $0, and then pops up a message box with that string. It's not a bug in your code.