views:

74

answers:

0

Hi, I have a pretty basic vc++/vs question, but the googles are failing me. I've seen this question posed before, but none of the proposed solutions work for me. I come from a very high-level language background (java/c#), so these pesky linking issues are alien to me. I appreciate your patience...

My problem is that when I send my exe to other folks, they cannot run the exe.

It works fine on my machine, presumably because I have all the vc++/vs build tools and libs. I think that I understand what's going on, but I don't know how to fix it.

The app is a java webapp, that runs under jetty, that I would like to distribute as a completely standalone windows exe and nt service. As simply as possible.

I have one c++ class that I wrote that loads the jvm and calls into the main() of my my java app.

I'm quite sure I just need to tweak something in my sln/vcproj file, but I'm not sure what.

I'm building via ant (yes, it is indeed strange to see msbuild output from an ant build... :)

tia, -neil

"C++ Command Line":

/O2 /Oi /GL /D "_MBCS" /FD /EHsc /MT /Gy /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /TP /errorReport:prompt

"Linker Command Line":

/OUT:"<myExe>" /NOLOGO /MANIFEST /MANIFESTFILE:"Release\<myExe>.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\<myPdb>" /OPT:REF /OPT:ICF /LTCG /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

"Manifest Command Line":

/nologo /outputresource:"<myExe>;#1"

Code:

#include <iostream>
#include <string>
#include <tchar.h>
#include <windows.h>
#include <winbase.h>
#include "include/jni.h"

using namespace std;

#define CLASS_NAME "<my class that has a main()>"
#define CLASS_PATH "-Djava.class.path=<all of my jars>"

typedef jint (JNICALL *CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
CreateJavaVM createJVM;

class Runner {
public:
 int Run() {
  JavaVM *vm;
  JavaVMInitArgs vm_args;
  JavaVMOption options[1];
  jint res;
  JNIEnv *env;
  jclass cls;
  jmethodID mid;

  options[0].optionString = CLASS_PATH;
  vm_args.version = JNI_VERSION_1_4;
  vm_args.options = options;
  vm_args.nOptions = 1;
  vm_args.ignoreUnrecognized = JNI_FALSE;

  HINSTANCE handle = GetJvmLibrary();
  if( handle == 0) {
   printf("Failed to load the jvm.");
   return -1;
  }

  createJVM = (CreateJavaVM)GetProcAddress(handle, "JNI_CreateJavaVM");

  res = createJVM(&vm, (void **)&env, &vm_args);
  if (res < 0)  {
   printf("JVM could not be loaded.");
   return -1;
  }

  cls = env->FindClass(CLASS_NAME);
  if(cls == 0) {
   printf("Exception in thread \"main\" java.lang.NoClassDefFoundError: %s\n", CLASS_NAME);
   return -1;
  }

  mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
  if(mid == 0) {
   printf("Exception in thread \"main\" java.lang.NoSuchMethodError: main\n");
   return -1;
  }

  env->CallStaticVoidMethod(cls, mid, "");
  if(env->ExceptionCheck()) {
   env->ExceptionDescribe();
   return -1;
  }
  return 0;
 }

private:
 static HINSTANCE GetJvmLibrary()
 {
  char lszVersionValue[8192];
  char lszPathValue[8192];
  HKEY hKey;
  LONG returnStatus;
  DWORD dwType=REG_SZ;
  DWORD dwSize=8192;

  returnStatus = RegOpenKeyEx(
       HKEY_LOCAL_MACHINE, 
       "SOFTWARE\\JavaSoft\\Java Runtime Environment", 
       NULL,  
       KEY_ALL_ACCESS, 
       &hKey);

  if (returnStatus == ERROR_SUCCESS)
  {
   returnStatus = RegQueryValueEx(
        hKey, 
        TEXT("CurrentVersion"), 
        NULL, 
        &dwType, 
        (LPBYTE)&lszVersionValue, 
        &dwSize);

   if (returnStatus == ERROR_SUCCESS)
   {
    // error.  need to figure out what TODO here.
   }
  }

  char buff[8192];
  memset(buff,0,sizeof(char)*8192);
  sprintf(buff, "SOFTWARE\\JavaSoft\\Java Runtime Environment\\%s", lszVersionValue);

  printf(buff);

  returnStatus = RegOpenKeyEx(
   HKEY_LOCAL_MACHINE, 
   buff, 
   NULL, 
   KEY_ALL_ACCESS, 
   &hKey);

  if (returnStatus == ERROR_SUCCESS)
  {
   returnStatus = RegQueryValueEx(
    hKey, 
    TEXT("RunTimeLib"), 
    NULL, 
    &dwType, 
    (LPBYTE)&lszPathValue, 
    &dwSize);

   while (returnStatus == ERROR_MORE_DATA)
   {
    returnStatus = RegQueryValueEx(
     hKey, 
     TEXT("RunTimeLib"), 
     NULL, 
     &dwType, 
     (LPBYTE)&lszPathValue, 
     &(dwSize+=4096));
   }

   if (returnStatus != ERROR_SUCCESS)
   {
    printf("failed to read the path to the jvm dll because of: %d",returnStatus);
   }
  }

  RegCloseKey(hKey);

  HINSTANCE handle = LoadLibrary(lszPathValue);
  if( handle == 0) {
   printf("Failed to LoadLibrary(jvm).\n");
  } else {
   printf("succussfully loaded the jvm.\n");
  }
  return handle;
 }
};

int main()
{
 return Runner().Run();
}