Solved

problem in windows service in windows 7

Posted on 2011-09-27
18
325 Views
Last Modified: 2012-05-12
Dear Experts,

i have a window service which would call an exe(my application) in a timely manner.
(Note : this service has been developed in VS2008 C#.My application is developed in
VS2003 C#).
In windows XP,this service is working perfectly.
In windows 7, whenever my service calls my exe ,windows 7 prompt a pop up( as i attached image). (but if i directly run the exe it is working in the same desktop without any issue.)
Win 7 Service Problem

 if i click 'view message',  my exe ( application) is running in different environment unlike desktop along with one more small window(i couldn't able take even screen shot of that environment) .

I am using following code to call my exe(application)

 
Process lobj_process = new Process();
                lobj_process.StartInfo.FileName = "MyApp.exe";
                lobj_process.StartInfo.WorkingDirectory = ls_path;
                lobj_process.StartInfo.RedirectStandardInput = true;
                lobj_process.StartInfo.UseShellExecute = false;

                lobj_process.StartInfo.CreateNoWindow = false;
                lobj_process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
                lobj_process.Start();
                ProcessWindowStyle ws = lobj_process.StartInfo.WindowStyle;
                if (ws == ProcessWindowStyle.Hidden)
                    lobj_process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

                
                lobj_process.WaitForExit();
                lobj_process.Close();

Open in new window


kindly suggest me solution  to run my application properly via my service.

Thanks
0
Comment
Question by:mahmood66
  • 8
  • 6
  • 4
18 Comments
 
LVL 8

Expert Comment

by:jagrut_patel
ID: 36708597
Launching an interactive application via Windows Service is not recommended.

Still to do so you can try this option and check.

In Property of your service > LogOn tab > Select Local System Account > Check "Allow service to interact with desktop" option.
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36708830
Windows Vista and later interactive services has been disabled by default. Instead of using the Process Class to open your executable use the following ServiceShell.Start() method will get the token of the current user and open the executable onto the users desktop instead of the services session. Your service can be set to LocalSystem
Imports System.Runtime.InteropServices
Imports System.Text

Public NotInheritable Class ServiceShell
    Private Sub New()
    End Sub
    
    Private Const CreateUnicodeEnvironment As Integer = &H400

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Private Structure StartupInfo
        Dim cb As Integer
        <MarshalAs(UnmanagedType.LPTStr)> Dim lpReserved As String
        <MarshalAs(UnmanagedType.LPTStr)> Dim lpDesktop As String
        <MarshalAs(UnmanagedType.LPTStr)> Dim lpTitle As String
        Dim dwX As Integer
        Dim dwY As Integer
        Dim dwXSize As Integer
        Dim dwXCountChars As Integer
        Dim dwYCountChars As Integer
        Dim dwFillAttribute As Integer
        Dim dwFlags As Integer
        Dim wShowWindow As Short
        Dim cbReserved2 As Short
        Dim lpReserved2 As IntPtr
        Dim hStdInput As IntPtr
        Dim hStdOutput As IntPtr
        Dim hStdError As IntPtr
    End Structure

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Private Structure ProcessInformation
        Dim hProcess As IntPtr
        Dim hThread As IntPtr
        Dim dwProcessID As Integer
        Dim dwThreadID As Integer
    End Structure

    <DllImport("Advapi32.dll", ExactSpelling:=False, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function CreateProcessAsUser(ByVal hToken As IntPtr, ByVal lpApplicationName As String, <[In](), Out(), [Optional]()> ByVal lpCommandLine As StringBuilder, ByVal lpProcessAttributes As IntPtr, ByVal lpThreadAttributes As IntPtr, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandles As Boolean, ByVal dwCreationFlags As Integer, ByVal lpEnvironment As IntPtr, ByVal lpCurrentDirectory As String, <[In]()> ByRef lpStartupInfo As StartupInfo, <Out()> ByRef lpProcessInformation As ProcessInformation) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("Userenv.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function CreateEnvironmentBlock(ByRef lpEnvironment As IntPtr, ByVal hToken As IntPtr, <MarshalAs(UnmanagedType.Bool)> ByVal bInherit As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("Userenv.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function DestroyEnvironmentBlock(ByVal lpEnvironment As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("Wtsapi32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function WTSQueryUserToken(ByVal SessionId As Integer, ByRef phToken As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("Kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function WTSGetActiveConsoleSessionId() As Integer
    End Function
    <DllImport("Kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Public Shared Sub Start(ByVal filename As String, ByVal commandLine As String, ByVal workingDirectory As String, Optional ByVal sessionId As Integer = -1)

        Dim hToken As IntPtr
        Dim pEnvBlock As IntPtr
        Dim dwSessionId As Integer
        Dim pi As ProcessInformation = Nothing
        Dim si As StartupInfo = Nothing

        '   If no session Id was specified defaults to using the session Id
        '   that is currently attached to the physical console.
        If sessionId = (-1) Then

            dwSessionId = WTSGetActiveConsoleSessionId()

        Else

            dwSessionId = sessionId

        End If


        '   Obtain the primary access token of the logged-on user specified by the session
        '   * Note: This can only be called successfully under LocalSystem context.
        If WTSQueryUserToken(dwSessionId, hToken) Then

            '   Get the enviorment block pointer for the user session.
            If CreateEnvironmentBlock(pEnvBlock, hToken, False) Then

                ' Setup command line buffer for unicode version
                Dim cmdLine As New StringBuilder(commandLine, 32768)

                If CreateProcessAsUser(hToken, filename, cmdLine, IntPtr.Zero, IntPtr.Zero, False, _
                                       CreateUnicodeEnvironment, pEnvBlock, workingDirectory, si, pi) Then

                    '   cleanup handle information
                    CloseHandle(pi.hProcess)
                    CloseHandle(pi.hThread)

                End If

                '   Destroy enviorment block pointer.
                DestroyEnvironmentBlock(pEnvBlock)

            End If

            '   cleanup user session token handle.
            CloseHandle(hToken)

        End If

    End Sub

End Class

Open in new window

'// usage
ServiceShell.Start("c:\myapp.exe", " -commandlines", "c:\")
ServiceShell.Start("c:\myapp.exe", nothing, nothing)

Open in new window

0
 

Author Comment

by:mahmood66
ID: 36714605
Dear egl1044,

i converted above code to C# as my code is in C#.
while calling Start() function

dwSessionId = WTSGetActiveConsoleSessionId()

the above function always returns '0'.so my application is not opening.
kindly suggest me what i need to do.

thanks
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36715598
Is your service set to LocalSystem?
0
 

Author Comment

by:mahmood66
ID: 36715613
Deat eg1044,

how can i set my service to localsystem?
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36715633
Check the properties section of your service and service installer files. The option should be in there
0
 

Author Comment

by:mahmood66
ID: 36716089
dear eg1044,

i couldn't able find where i can set my service to local system?
(except the place which i have mentioned in attached screen shot.)

 ServiceProperty

kindly suggest me.

thanks


 

0
 
LVL 8

Expert Comment

by:jagrut_patel
ID: 36716121
Just a note. This was the place I referrred to in my post 36708597.
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36716162
Yes. I'm referring to your actual service not the services.msc console but your service application within .NET. In Vista and later interactive services are disabled by default so you don't want to select "Interact with desktop option". You need to open your service in .NET and go to the properties section and turn off "interact with desktop" and only select LocalSystem.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36716188
Have a look here http://msdn.microsoft.com/en-us/library/zt39148a(v=vs.80).aspx and scroll to the section "To create the installers for your service"

" In the designer, click ServiceProcessInstaller1 (for a Visual Basic project), or serviceProcessInstaller1 (for a Visual C# or Visual J# project). Set the Account property to LocalService. This will cause the service to be installed and to run on a local service account. "

Make sure you don't have interact with desktop enabled. You may have to un-install your service first, compile the changes and then re-install.
0
 

Author Comment

by:mahmood66
ID: 36716217
Dear jagrut & eg1044,

1) i already set the above mentioned property.still my application opening in such environement in windows 7.


2) while debugging below code(which is suggested by you [ eg1044]),
 
 Public Shared Sub Start(ByVal filename As String, ByVal commandLine As String, ByVal workingDirectory As String, Optional ByVal sessionId As Integer = -1)

        Dim hToken As IntPtr
        Dim pEnvBlock As IntPtr
        Dim dwSessionId As Integer
        Dim pi As ProcessInformation = Nothing
        Dim si As StartupInfo = Nothing

        '   If no session Id was specified defaults to using the session Id
        '   that is currently attached to the physical console.
        If sessionId = (-1) Then

            dwSessionId = WTSGetActiveConsoleSessionId()

        Else

            dwSessionId = sessionId

        End If


        '   Obtain the primary access token of the logged-on user specified by the session
        '   * Note: This can only be called successfully under LocalSystem context.
        If WTSQueryUserToken(dwSessionId, hToken) Then

            '   Get the enviorment block pointer for the user session.
            If CreateEnvironmentBlock(pEnvBlock, hToken, False) Then

                ' Setup command line buffer for unicode version
                Dim cmdLine As New StringBuilder(commandLine, 32768)

                If CreateProcessAsUser(hToken, filename, cmdLine, IntPtr.Zero, IntPtr.Zero, False, _
                                       CreateUnicodeEnvironment, pEnvBlock, workingDirectory, si, pi) Then

                    '   cleanup handle information
                    CloseHandle(pi.hProcess)
                    CloseHandle(pi.hThread)

                End If

                '   Destroy enviorment block pointer.
                DestroyEnvironmentBlock(pEnvBlock)

            End If

            '   cleanup user session token handle.
            CloseHandle(hToken)

        End If

    End Sub


 this function("WTSGetActiveConsoleSessionId()") always returns '0 ' as sessionId.
so my application is not opening(if i use that code)...



3) is there any other way to avoid opening of my application in such environment in windows 7?
should i approach some other method specially for windows 7.?
because my service opens the same application in XP without any problem, as i mentioned in my question


kindly suggest me..

thanks
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 36716254
This is the correct way to launch an application from a service onto the desktop. The example provided works as intended but there must be some minor problem on your side. In XP the option "interact with desktop" is what allows the service to display the application on the desktop however on Vista and later this has been removed. The easiest way to make it work for XP, Vista , Win7 is to NOT enable "interactive with desktop" option and use the example code to launch your application. The example code will open your program on the current desktop.
0
 

Author Comment

by:mahmood66
ID: 36938363
Dear (egl1044) Experts,

i have created a new service as suggested in previous post(ID: 36716188).
i followed the instruction and i did the code.
i used the suggested code to call an exe.(suggested By egl1044 ID :36708830)
(but i have converted the code into c#.)
still this is not working..

kindly send me one sample project to achieve my target..


thanks


0
 
LVL 8

Expert Comment

by:jagrut_patel
ID: 36947962
mahmood66, just to re-emphasis my point I would like to repeat that services are not meant to open a windows form. Just consider the case where computer is started but user does not log-in. Service is started in such case but how can it show the UI.

It is my suggestion that if possible you should think of other alternative like having a System tray application that can start automatically when application starts.

0
 

Author Comment

by:mahmood66
ID: 37029565
can you give me coding example for that.
0
 
LVL 8

Accepted Solution

by:
jagrut_patel earned 500 total points
ID: 37037123
This explains how to create a system tray application.

See this to understand how to start a program on Windows start-up.
0
 

Author Comment

by:mahmood66
ID: 37061937
Dear Jagrut,

Thanks for your suggestion.it works.
0
 

Author Closing Comment

by:mahmood66
ID: 37061938
it works
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This Micro Tutorial will give you a introduction in two parts how to utilize Windows Live Movie Maker to its maximum editing capability. This will be demonstrated using Windows Live Movie Maker on Windows 7 operating system.
The viewer will learn how to successfully download and install the SARDU utility on Windows 7, without downloading adware.

762 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now