We help IT Professionals succeed at work.

A C++ service keeping a VB object alive after the user has logged off

ZANTAR
ZANTAR asked
on
Medium Priority
271 Views
Last Modified: 2010-04-02
Hello,

I have a Visual C++ service that is using an ActiveX Exe (Similar to an ActiveX Dll). The service needs to run the following code and create an instance of a connector object from the Active exe. This code is currently working 100%.

The problem:
If the user starts the service, which calls the RUN command, the connector object gets created correctly. However, if the user logs off the machine while the service is running, the connector object is killed and the service continues to operate. My guess is that I need to specify the Windows NT login when creating the connector object. So if the service is started up by USER1, and the machine is logged in as USER2, the connector object will belong to USER1. That way if the USER2, logs off, the service and connector object still exist.

A couple of ideas that might be part of the solution:
-     CREATEPROCESS()?
-     COCREATEINSTANCE()?

Here is the procedure that creates the connector object in C++.

// I have removed the catch code and I only am showing the try code.

void MyApp::CMyAppService::Run()
{
   long iLoopCount;  //a loop  counter  
   long iRetryCount; //a retry counter  
   long iStart;   //a Return Code for Start MyServer
   long iRefresh; //a Return Code for Refresh MyServer
   long iStop;
   std::wstring aMsg;
   std::wstring aPrtMsg;

    HRESULT hr;    //a Return Code of COM

   //The following code is to call a VB ActiveX Exe
   CoInitialize(NULL);                             //open a COM thread
               
   _ConnectorPtr aConnector;                       //a smart point to the VB object
   hr = aConnector.CreateInstance(__uuidof(Connector)); //create an instance of a connector object
         
   // Check the status of ?hr? here to ensure that the connector was created

   //Start the MyServer
   iStart=(long)aConnector->ConnStartMyServer();
}

I have lots of experience with VB and RDBMS, but I only have 1 year of C++ knowledge. If your solution requires many steps, please document clearly, as it will help immensely.

Thank you very much for your time,

Dave Hall

Comment
Watch Question

Commented:
Is it possible to stop the server explicitly. So that when you stop the conenctor, it stops the server also. Try to release the server explicitly.

This may works out for you.

Thangs

Author

Commented:
If the user logs off the machine, I want the connector object and the services to continue to run. I have other services which run no problem if the user is not logged on.

Author

Commented:
I need a solution quickly as possible.

Commented:
1.If the activeX control also developed by yourself, you can change it to a Service.
2.Use RegisterServiceProcess register your ActiveX Exe as service.
i.e.
// ....
_ConnectorPtr aConnector;                       //a smart point to the VB object
  hr = aConnector.CreateInstance(__uuidof(Connector)); //create an instance of a connector object
// Now you can register the ActiveX exe server as a service.
// so it will not be close when log off
....
RegisterServiceProcess(...);        
//...
 
Commented:
You can also use CREATEPROCESS()
i.e
typedef DWORD (WINAPI *FNRegisterServiceProcess)( DWORD dwProcessId, DWORD dwType );

FNRegisterServiceProcess pRegService;
pRegService = (FNRegisterServiceProcess )GetProcAddress(GetModuleHandle("KERNEL32"), "RegisterServiceProcess");
     
CreateProcess("ActiveX exe server.exe", _T(".."),  NULL, NULL, FALSE, 0, NULL, NULL, &StartInfo, &ProcessInfo);

pRegService (ProcessInfo.dwProcessId, 1);

// then create instance... it will use the created process
// but it depend on the ActiveX exe server's implementation

otherwise you should find the processID.

Author

Commented:
BeyondWu,

Both the Visual C++ service and the Visual Basic ActiveX Exe have been written by myself. With that in mind, which solution would you recommend to implement?

The "Connector" is a VB class that belongs to the ActiveX Exe and needs to be created from the VC++ service and kept alive even after the user logs off.

I have seen CreateProcess used to startup applications (.exe) from with C++ code. However, how do you ensure that if the user logs off the machine, that the process is not killed? Or is this not a concern?

Thanks for the feedback and I will attempt to try both solutions.

Author

Commented:
Also,

If this helps.... The current code does an import in the header file so that the createinstance code does not need the GUID, because the import gets it automatically. So if I try using the createprocess, should I then get rid of the import?

#import "MyServer.exe" no_namespace //import the interface of ActiveX MyServer.Exe
le

Commented:
Run the aervice on LOcal System Account (this is default), but on "This user account"

Author

Commented:
The service must run on the domain account and under a different user account than that which is logging on/off to start up the service.

If the machine reboots, the service will startup automatically even if the user does not start up the service. This is already implemented.

Commented:
ZANTAR:
If you develop under win9x, you can use RegisterServiceProcess to register your activex component as a service, but you can't use it on Win2K or NT.
Maybe you can use OpenSCManager to install it, but i don't ensure.

If your activex is not very complex, I recommend you change to use VC/ATL wizard to convert it to a service.
I think it's the easiest way.

Author

Commented:
The VB ActiveX exe is very complex and does tons of calculations and database calls. It currently runs on Win NT and after searching on the web about using RegisterServiceProcess in VB. I found out that RegisterServiceProcess does not exist in Kernel32 for Win Nt.

I can't use RegisterServiceProcess on NT (not in VC++ or VB). But, can I use CreateProcess to start up the VB ActiveX exe using the same user account that the VC++ service was started up by? Then create the instance of the connector object?

Commented:
I'm not very familiar VB,
Do you know is there some options that can create your component as a service in VB?
Do you can change your component to DLL?
And I don't ensure if the CreateProcess can help you.

Author

Commented:

Author

Commented:

Author

Commented:
Unfortunately, the ActiveX exe must remain as one, because it acts as an OLE SERVER between the client software and the service.

Is there anyway to startup the ActiveX exe using createprocess?

Author

Commented:
When I'm asking about using CreateProcess, I mean startup the ActiveX exe using CreateProcess from in C++

Author

Commented:
I just want to thank you for your help. The final solution was that I didn't need to do anything with the C++ or VB active X exe. It turned out that the DCOM configuration was the problem. I needed to setup the service and the VB active X exe to use a specific user account rather than letting it decide which to use.

However, I found a lot of useful things to do with createprocess and registerserviceprocess functions.

Commented:
Thanks and Congratulations!
Can you tell me the detail how you resolve your problem?
Thanks!

Author

Commented:
Here are the steps:

1. Click Start-> Settings -> Control Panel
2. Open Services
3. Scroll down to "MyService" and highlight it.
4. Ensure that it is STOPPED.
5. Select the startup button
6. In the "Log on as" frame, Select "This account" and enter the following:

     This Account: <Enter the Domain>\SharedServiceAccount
     Password: <Enter SharedServiceAccount password here, case sensitive>
     Confirm Password: <Enter SharedServiceAccount password here, case sensitive>

7. In the "Startup Type" frame, Select "Automatic". This way when the computer starts, so will start the service when the machine fails.
8. Click Ok to save the changes
9. Click Close, to close the services window.
10. Click Start->Run
11. Enter "dcomcnfg" and OK
12. Click the "Default Security" tab.
13. Ensure that Domain users have "Allow Access" under "Access permissions" by clicking "Edit default" permissions.
14. Ensure that Domain users have "Allow Launch" under "Launch permissions" by clicking "Edit default" permissions.
15. Under the "Applications" tab, scroll down to "MyActiveXexe.xxxxx" and highlight it.
16. Click the "Properties..." button
17. Under the "General" tab, Authentication level should be "Connect"
18. Under the "Location" tab, only "Run on this computer" should be checked.
19. Under the "Security" tab, confirm the following:

     Use default access permissions, is selected.
     Use default launch permissions, is selected.
     Use custom configuration permissions, is selected.

20. Under the "Identity" tab, select "This user" and ener the following:

     User: <Enter the Domain>\SharedServiceAccount
     Password: <Enter SharedServiceAccount password here, case sensitive>
     Confirm Password: <Enter SharedServiceAccount password here, case sensitive>

21. Click OK to save the DCOM changes of the MyActiveXexe.xxxx .
22. Click OK to close the "Distributed COM Configuration"
23. Click Start-> Settings -> Control Panel
24. Scroll down to "MyService" and highlight it.
25. Click the "Start" button, to start the service.

Next, on ALL client computers where the client VB software is installed, do the following:

Note: The following steps do not need to be done on the computer with the MyService, as they have already been performed.

1. Click Start->Run
2. Enter "dcomcnfg" and OK
3. Click the "Default Security" tab.
4. Ensure that Domain users have "Allow Access" under "Access permissions" by clicking "Edit default" permissions.
5. Ensure that Domain users have "Allow Launch" under "Launch permissions" by clicking "Edit default" permissions.
6. Under the "Applications" tab, scroll down to "MyActiveXexe.xxxxx" and highlight it.
7. Click the "Properties..." button
8. Under the "General" tab, Authentication level should be "Connect"
9. Under the "Location" tab, only "Run on this computer" should be checked.
10. Under the "Security" tab, confirm the following:

     Use default access permissions, is selected.
     Use default launch permissions, is selected.
     Use custom configuration permissions, is selected.

11. Under the "Identity" tab, select "This user" and ener the following:

     User: <Enter the Domain>\SharedServiceAccount
     Password: <Enter SharedServiceAccount password here, case sensitive>
     Confirm Password: <Enter SharedServiceAccount password here, case sensitive>

12. Click OK to save the DCOM changes of the MyActiveXexe.xxxx .
13. Click OK to close the "Distributed COM Configuration"
14. Now startup the client VB software and point to the server running the MyService. It will now connect successfully.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.