?
Solved

Shelling an Exe from non-interactive service? VB6

Posted on 2004-11-02
28
Medium Priority
?
552 Views
Last Modified: 2012-06-21
Hello,

Trying to call another app from my non interactive system service (program =a service frontend =a normal exe).  I would like the service to call the front end upon startup but shell is not going to cut it, it appears the shell runs it under the system user account (same as the service is running under).  I don't want to have to feed it any usernames or passwords.  is there any way to make it run visibly, being called from the service??

Don't really want to use reg run or start menu startup if I can help it...
0
Comment
Question by:bluedragon99
  • 9
  • 8
  • 3
  • +3
25 Comments
 
LVL 19

Expert Comment

by:RanjeetRain
ID: 12475841
Use a timer event. Launch your interface app a few seconds/minutes later the service started. By that time you will have the shell.

Also, you may use CreateProcess windows API call: http://www.cpcug.org/user/clemenzi/technical/Languages/Execute_Shell.htm
0
 
LVL 19

Expert Comment

by:RanjeetRain
ID: 12475869
One good example you can find here: http://www.mentalis.org/apilist/CreateProcess.shtml
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12476108
wow thats some aweful syntax but I like that it creates a new process on it's own...working on it now.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 1

Author Comment

by:bluedragon99
ID: 12476387
no luck yet still workin...
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12476432
it is only opening dos style exe's.
0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12476866
A little more information here would be nice, as in what is the goal of this EXE that you want to spawn.  The issues is on an NT/2k/XP machine if you create a process from the system account it will run on system's desktop.  MOre often than not you will have to "impersonate the logged on user."  Another option would be to have a helper application running (via the startup folder or the reg run key) so that it runs in the current users context.  Then you could use either a named event to signal this app or a global message (broadcast message) to signal your helper to spawn your service requested application.

Jake
0
 
LVL 5

Expert Comment

by:naiea1231
ID: 12480426
If you want to be able to launch windows forms from a service you need to check the "allow interaction with desktop" in it's properties, this can be found by right clicking on the service in the services control panel. This allows launched windows to be visible, otherwise, as you stated, you will be limited to dos command prompt style applications.
0
 
LVL 5

Expert Comment

by:naiea1231
ID: 12480430
Just a note, the "allow service to interact with desktop" is in the log on tab in the service properties.

Let us know how it goes.

James
0
 

Expert Comment

by:vikrant_kpr
ID: 12492484
Delete the service
and then While installing the service use the service type as
SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS
and also when calling RegisterServiceCtrlHandlerand filling the service type use the same above specified service type.
Whenever u launch the application it will be visible.
0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12497730
I'm still concerned that everyone is happily suggesting that it's "Ok" to run his interactive application from the Local System account.  Local System has more privliges than Administrator, so if this application is intended to be sold it will be a MAJOR security hole.  It isn't at all hard to inject your own code into another interactive process (Easily done with settimer and any edit control...).  Just look at all the processes running on your machine that do have a tray icon, 100% of them should be running in your user context.  As an alternative, .Net offers some nice classes to start a process using the currently logged on users credentials.

Jake
0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12497739
Another note, if it's run from the System account it will NOT have access to any network drives.
0
 
LVL 22

Expert Comment

by:cookre
ID: 12498403
CreateProcess() uses the calling processes security context.  Use CreateProcessAs() to use a different one.

CreateProcess() can run windowed programs as well console programs, but you do have to fiddle with STARTUPINFO.

If the calling process is a non-interactive service, you can specify the target station and desktop in the new process' STARTUPINFO.

0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12499363
Correct, but in order to change the security context you would have to have one (LPSECURITY_ATTRIBUTES) of the currently logged in user.  Even then, I feel it would be lot more work to do it this way (if it's even possible to acquire the user's token w/ out knowing it's name/pass)instead of using a helper application as the author stated he didn't want to have to know the user/pass.
0
 
LVL 22

Expert Comment

by:cookre
ID: 12499600
>>currently logged in user
...if there is one.  But, given that bludragon99 mentioned the spawned app was to be visible, I suppose it's safe to presume the service doesn't start the process until a user has logged on.

Actually, I got the impression that his using LocalSystem was acceptable as long as the app would be visible, but then, being and old fart with coke bottle bottom bifocals, I could very well have missed something.

0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12499821
As am I taking the assumption that it will be running on NT/2k/XP/2k3...  Now trying to run an application in interactive mode without a currently logged on user is more difficult than one may think, as there are numerous hoops one has to jump through in order to be able to do it.  Also, as he's stating it's VB6 I don't think he would be able to create a window without an existing desktop.  I do remember trying to create a similar service for an in house application that would just have to inform the user if an error occured, and if no user was logged on to pop it up on the "Default" desktop.  I can't remember the specifics but I don't think VB is capable of creating a window when there is no user logged on....

  I guess we should just wait for some author feedback.  Again, a little more information on what this "spawned" application is accomplishing would be nice.

Jake
0
 
LVL 22

Expert Comment

by:cookre
ID: 12499983
>>> in interactive mode without a currently logged on user is more difficult than one may think
Actually, more difficult than that.  Or not, depending on your outlook.  

An interactive app would seem to imply a user is present.  
An interactive service just means it's associated with WinSta0\Default.

Here's a snippet to show how to start a windowed program from a non-interactive service - presuming someone has logged on to see it.  The only real difference difference is that in this case, StartInfo.lpDesktop gets the name of the windows station and desktop to be associated with the started process.  If not specified, the started process is associated with the windows station and desktop of the starting process which, in the case of a non-interactive service are not visible.

(Yes, Blue, it does look vaguely like C, doesn't it)

STARTUPINFO          StartInfo;
PROCESS_INFORMATION  ProcInfo;
char                 WinSta0Default[512];
char                 CommandStr[512];

memset(&StartInfo,0,sizeof(StartInfo));
strcpy(CommandStr,"c:\\windows\\notepad.exe");
strcpy(WinStaAndDesktop,"WinSta0\\Default");

StartInfo.cb=sizeof(StartInfo);
StartInfo.dwFlags=STARTF_USESHOWWINDOW;
StartInfo.wShowWindow=SW_SHOWMAXIMIZED;
StartInfo.lpDesktop=WinStaAndDesktop;                     <<<<<------------------------
if (0==CreateProcess(NULL,CommandStr,NULL,NULL,FALSE,0,NULL,NULL,&StartInfo,&ProcInfo))
   {
   oopsie...
   }
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12504608
sorry it took me so long to get back..

Here's what I've done

Service = non-interactive
Front end = not a service, interactive, loads from "run" in registry
console = talks to service over network ports

front end and service talk over local ports


This seems to work but now when the machine is logged in the service stops responding to console commands for some reason.  before login the service communicates with the console fine.  upon login service IS still running but won't respond to any console commands at all.  very odd
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12504956
It's the actual ACT of logging in that makes it unresponsive too.  If I restart the services after logging in it runs forever.
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12505025
Actually just found out the service is still functioning and doing it's job just no comm. with console after login...very weird why would a service be affected by user login?? (even removed the front end from the reg, problem persists)
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12505072
Service form load event:

Private Sub Form_Load()
AString = "teststring"
NTService.StartService

Dim strDisplayName As String

On Error GoTo CreateNewLog
Open OptionsFrm.LoggingPath.Text For Append As #31
    Print #31, "Starting - " & Time & " " & Date
Close #31
On Error GoTo 0






strDisplayName = "Service"

NTService.ServiceName = strDisplayName
NTService.DisplayName = strDisplayName
NTService.Interactive = False
NTService.StartMode = svcStartAutomatic

On Error GoTo CreateNewLog
Open OptionsFrm.LoggingPath.Text For Append As #83
    If NTService.Interactive = True Then
        Print #83, "Running In Interactive Mode - " & Time & " " & Date
    Else
        Print #83, "Non-Interactive Mode - " & Time & " " & Date
    End If

    If NTService.StartMode = svcStartAutomatic Then
        Print #83, "Starting Automatically - " & Time & " " & Date
    Else
        Print #83, "Starting Manually Only - " & Time & " " & Date
    End If
Close #83
On Error GoTo 0


IsServiceInstalled
If ServiceInstalled = False Then
    NTService.Install
    On Error GoTo CreateNewLog
    Open OptionsFrm.LoggingPath.Text For Append As #61
        Print #61, "Service Installed Successfully - " & Time & " " & Date
    Close #61
    On Error GoTo 0
    Call CreateStartupKey
End If
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12506287
Ah! Found it.  When the service talks to the "localhost" I had hard coded remotehost = "LocalHost".  Well this was killing communication from console to service and vice versa because it was talking to localhost not the console.  How do I get around this??? is there a way to negate the remotehost = "localhost" and make it talk to who spoke to it?  I don't want to have to hardcode the console machine's ip into the program.
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 12506320
Form1.Winsock1.RemoteHost = "" ??
0
 
LVL 7

Accepted Solution

by:
jacobhoover earned 2000 total points
ID: 12509787
In a module use:

Declare Function ApiGetComputerName Lib "KERNEL32" Alias "GetComputerNameA" _
    (ByVal lpBuffer As String, nSize As Long) As Long
   
   
Public Function GetComputerName() As String
  Dim strBuffer As String * 255
  Dim lngBufferLength As Long
  Dim lngRet As Long
  Dim StrTemp As String
  lngBufferLength = 255
  lngRet = ApiGetComputerName(strBuffer, lngBufferLength)
  StrTemp = UCase(Trim$(strBuffer))
  GetComputerName = Left$(StrTemp, lngBufferLength)
End Function

Then in the form, Form1.Winsock1.RemoteHost = GetComputerName()
0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12509960
That "should" resolve to the true IP, if not one can use a more complex method to get the machine's IP address.  

Ie, in a module...: (Works on Windows 98, Windows 2000, Windows XP)

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2004 VBnet, Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce
'               or publish this code on any web site,
'               online service, or distribute as source
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'// SLIGHT MODIFICATION DONE IN ORDER TO ACCOMIDATE FIRST ADAPTER
'// BEING DISCONECTED
Private Const MAX_ADAPTER_NAME_LENGTH As Long = 256
Private Const MAX_ADAPTER_DESCRIPTION_LENGTH As Long = 128
Private Const MAX_ADAPTER_ADDRESS_LENGTH As Long = 8
Private Const ERROR_SUCCESS As Long = 0

Private Type IP_ADDRESS_STRING
   IpAddr(0 To 15) As Byte
End Type

Private Type IP_MASK_STRING
   IpMask(0 To 15) As Byte
End Type

Private Type IP_ADDR_STRING
   dwNext As Long
   IpAddress As IP_ADDRESS_STRING
   IpMask As IP_MASK_STRING
   dwContext As Long
End Type

Private Type IP_ADAPTER_INFO
   dwNext As Long
   ComboIndex As Long  'reserved
   sAdapterName(0 To (MAX_ADAPTER_NAME_LENGTH + 3)) As Byte
   sDescription(0 To (MAX_ADAPTER_DESCRIPTION_LENGTH + 3)) As Byte
   dwAddressLength As Long
   sIPAddress(0 To (MAX_ADAPTER_ADDRESS_LENGTH - 1)) As Byte
   dwIndex As Long
   uType As Long
   uDhcpEnabled As Long
   CurrentIpAddress As Long
   IpAddressList As IP_ADDR_STRING
   GatewayList As IP_ADDR_STRING
   DhcpServer As IP_ADDR_STRING
   bHaveWins As Long
   PrimaryWinsServer As IP_ADDR_STRING
   SecondaryWinsServer As IP_ADDR_STRING
   LeaseObtained As Long
   LeaseExpires As Long
End Type

Private Declare Function GetAdaptersInfo Lib "iphlpapi.dll" _
  (pTcpTable As Any, _
   pdwSize As Long) As Long
   
Private Declare Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (dst As Any, _
   src As Any, _
   ByVal bcount As Long)

Public Function LocalIPAddress() As String
   
  'api vars
   Dim cbRequired  As Long
   Dim buff()      As Byte
   Dim Adapter     As IP_ADAPTER_INFO
   Dim AdapterStr  As IP_ADDR_STRING
   
  'working vars
   Dim ptr1        As Long
   Dim sIPAddr     As String
   Dim found       As Boolean
   
   Call GetAdaptersInfo(ByVal 0&, cbRequired)

   If cbRequired > 0 Then
   
      ReDim buff(0 To cbRequired - 1) As Byte
     
      If GetAdaptersInfo(buff(0), cbRequired) = ERROR_SUCCESS Then
     
        'get a pointer to the data stored in buff()
         ptr1 = VarPtr(buff(0))

         Do While (ptr1 <> 0) 'And (found = False)
         
           'copy the data from the pointer to the
           'first adapter into the IP_ADAPTER_INFO type
            CopyMemory Adapter, ByVal ptr1, LenB(Adapter)
         
            With Adapter
                       
              'the DHCP IP address is in the
              'IpAddress.IpAddr member
                 
               sIPAddr = TrimNull(StrConv(.IpAddressList.IpAddress.IpAddr, vbUnicode))
                 
               '// MODIFIED HERE IN CASE THERE IS A DISCONNECTED ADAPTER
               '// ON MY MACHINE, XP Pro, THE FIRST ADAPTER IS DHCP CONFIGURED
               '// AND IT'S DISCONECTED, RESULTING IN AN IP OF 0.0.0.0
               If Len(sIPAddr) > 0 And (sIPAddr <> "0.0.0.0") Then
                  found = True
                  Exit Do
               End If

               ptr1 = .dwNext
                             
            End With  'With Adapter
           
        'ptr1 is 0 when (no more adapters)
         Loop  'Do While (ptr1 <> 0)

      End If  'If GetAdaptersInfo
   End If  'If cbRequired > 0

  'return any string found
   LocalIPAddress = sIPAddr
   
   
End Function


Private Function TrimNull(item As String)

    Dim pos As Integer
   
   'double check that there is a chr$(0) in the string
    pos = InStr(item, Chr$(0))
    If pos Then
       TrimNull = Left$(item, pos - 1)
    Else
       TrimNull = item
    End If
 
End Function

0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 12550150
@bluedragon99
  Any feedback?
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
When you discover the power of the R programming language, you are going to wonder how you ever lived without it! Learn why the language merits a place in your programming arsenal.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question