murrayju / CreateProcessAsUser

Creates a process in a different Windows session
MIT License
369 stars 114 forks source link

Unhandled Exception #4

Closed pyed closed 8 years ago

pyed commented 9 years ago

I couldn't get this to work for me, I'm new to C# so maybe I'm doing something wrong, here's the code

using System;
using murrayju.ProcessExtensions;

namespace spawnproc
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Starting calc.exe");
            ProcessExtensions.StartProcessAsCurrentUser("calc.exe");
        }
    }
}

trying to run this will return the following error, with exit status code 255

Unhandled Exception: System.Exception: StartProcessAsCurrentUser: CreateProcessAsUser failed.

   at murrayju.ProcessExtensions.ProcessExtensions.StartProcessAsCurrentUser(String appPath, String cmdLine, String workDir, Boolean visible)
   at spawnproc.Program.Main()
murrayju commented 9 years ago

Are you running your application with admin privileges?

pyed commented 9 years ago

Yes, right click run as admin will show the same message, also cmd.exe will stop working after it.

And I tried calling it from a windows service I'm running, which runs under the account "SYSTEM" and the same error occurred

murrayju commented 9 years ago

Did you try running the demo service in the repo? That works for me...

pyed commented 9 years ago

What will the demo service do when I install it as a service ?

I'm interested to have a command-line executable that uses ProcessExtensions which other installed services will call to run something like calc.exe on the active user session, is that possible ?

murrayju commented 9 years ago

Look here. All it does is launch calc.exe when it starts.

What you are proposing should be possible, yes. So long as the cmd line process is started with the same permissions that the service has, it should be good.

pyed commented 9 years ago

I tried to install the demo using installutil and I got the following in the InstallLog file

Installing assembly 'C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.exe'.
Affected parameters are:
   logtoconsole = 
   logfile = C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.InstallLog
   assemblypath = C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.exe
Installing service DemoService...
Creating EventLog source DemoService in log Application...
Rolling back assembly 'C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.exe'.
Affected parameters are:
   logtoconsole = 
   logfile = C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.InstallLog
   assemblypath = C:\Users\pyed\Desktop\CreateProcessAsUser\DemoService\bin\DemoService.exe
Restoring event log to previous state for source DemoService.
An exception occurred during the Rollback phase of the System.Diagnostics.EventLogInstaller installer.
System.Security.SecurityException: The source was not found, but some or all event logs could not be searched.  Inaccessible logs: Security.
An exception occurred during the Rollback phase of the installation. This exception will be ignored and the rollback will continue. However, the machine might not fully revert to its initial state after the rollback is complete.

and yes, my service will run the cmd with the services account which is "SYSTEM", this would be awesome.

murrayju commented 9 years ago

Make sure you successfully built the project (in visual studio), and that your are running createservice.bat as an admin.

pyed commented 9 years ago

well, I built it in visual studio sure, and I ran createservice.bat as admin, I got a cmd.exe window for a split of a second and nothing happened after, I opened the services application, there's no service with the word demo in it

murrayju commented 9 years ago

Ok, I'll look into it more tomorrow.

pyed commented 9 years ago

I really appreciate your time, this is important for me, I will work more on it, and I will report back

murrayju commented 9 years ago

Ok, just tried running the demo from scratch, it definitely works. Try following these steps exactly:

  1. Open a cmd.exe as Administrator
  2. git clone https://github.com/murrayju/CreateProcessAsUser
  3. cd CreateProcessAsUser
  4. %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe solution.sln
  5. cd DemoService
  6. createService.bat
  7. You should see calc.exe open

I just ran this on Windows 8.1 x64. If it doesn't work for you, there must be something different about your environment. Let me know.

pyed commented 9 years ago

I really appreciate your time, I followed your steps and indeed the Demo worked for me on a Windows 7.

But I'm still not able to achieve the command-line program that I need, I created a new repo with my code in it, it's a C# command-line project with ProcessExtensions.cs included, I would like you to take a look at it : https://github.com/pyed/spawnproc

when I try to run it, I hit this exception:

                if (!GetSessionUserToken(ref hUserToken))
                {
                    throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");
                }
AndrewSav commented 9 years ago

You need SE_TCB_NAME privilege. If you ran from a service (LocalSystem) it's held by default, if you are running it from command line, like you do, it's up to you to obtain it.

murrayju commented 9 years ago

Yes, what @AndrewSav said. If you intend to run your code from the system account, you should just do your testing in that same environment and it should work. Otherwise, as an admin you will be able to acquire the necessary permissions, but you'll have to figure out the necessary win32 calls to do so.

Also, that is not the only privilege that you will need, the CreateProcessAsUser doc lists others.

pyed commented 9 years ago

Okay, I'm not a Windows guy, but I have this service that I'm executing commands from, so when I execute whoami I will get nt authority/system, but when I try to execute spawnproc.exe I will hit the same exception, aren't I running spawnproc.exe via the nt authority/system account which should have the privileges I need ?

murrayju commented 9 years ago

Well yes and no. It will be the same user account, but C# by default does not spawn the child process with all of the same privileges. Windows services are special, and are granted privileges by default that other processes are not. This isn't something that I've personally tried to do, so I'm not sure if there is a C# way, but I'm guessing that you'll have to call the win32 apis I linked above (via pinvoke).

Honestly, it would probably be easier to just modify the service(s) to use my library directly, rather than hand off to another process.

AndrewSav commented 9 years ago

What I'd suggest doing is trying your best, and then posting your failed attempt at Stack Overflow. I'm sure helpful folk there will be able to give a hand, you just would need to demonstrate that you've put enough efforts in it yourself and not just asking people to write your code for you.

pyed commented 9 years ago

@murrayju okay, one last question, is your DemoService designed to "only" run calc.exe ?

this may sound weird, but changing only line 15 in this file from calc.exe to something like stikynot.exe or osk.exe will not have the same effect as having calc.exe there !! and just by changing the source to calc.exe again will show the Calculator, but for the Sticky Note and other apps it will not show them !! is the PATH that the service calling calc.exe differ from the global path "which is usually C:\Windows\System32\calc.exe"

murrayju commented 9 years ago

@pyed No it should work with any process. It will resolve the process path using the system %PATH% variable. If all else fails, just use the absolute path.

You could be running into 32/64 bit problems, or even string encoding problems. If you can't get it to work, let me know and I'll dig deeper.

pyed commented 9 years ago

@murrayju I'm sure that this worth your time to dig into, I used absolute paths and it's not working, only calc.exe works !

pyed commented 9 years ago

@murrayju I'm still interested to know your answer, just change calc.exe in the DemoService to any application in the %PATH% and try to run it, it won't work ¯\_(ツ)_/¯

AndrewSav commented 9 years ago

This is the description of CreateProcessAsUser https://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx It explicitly says, that if you use lpApplicationName parameter then:

The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. This parameter must include the file name extension; no default extension is assumed.

If you want path, use lpCommandLine parameter that is described in the same article below.

pyed commented 9 years ago

@AndrewSav Okay I see now, but it still does NOT work, even with absolute paths, it only works with calc.exe, try it yourself, change "calc.exe" in the file DemoService/DemoService.cs to C:/Windows/System32/StikyNot.exe, the question is simple, after running createService.bat Are You Getting A Sticky Note ??

AndrewSav commented 9 years ago

I tried. Works fine. Not with a sitky, but with a handful of other programs in different folders. I'm not sure what the stiky is.

pyed commented 9 years ago

@AndrewSav I see that it works for some applications, and doesn't for others, I'm not sure about the reason tho.

AndrewSav commented 9 years ago

Perhaps you are running on 64 bit system and trying to run a program from system folder with file system redirection on. If after redirection the program is not in the redirected folder (calc.exe is stikyno.exe is not) it cannot find it. Copy your stickynot to C:\Windows\SysWOW64 or for that matter anywhere else and run it from there. Reading: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187

kukucz commented 9 years ago

@pyed Maybe you don't use double backslashes in full path (in example you must set path to mspaint like this: "C:\Windows\System32\mspaint.exe".

And remember that you can always use murrayju DemoService to run application from another system account service. In Demo service code just replace application to run (set proper path), compile solution. Don't use attached createService.bat but install DemoService by running %windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe bin\DemoService.exe. Set your service to run some cmd script (in example RunApp.cmd filed with this commands:

sc start DemoService sc stop DemoService

). When your service (working with system accounts rights) run RunApp.cmd , this script will run DemoService, Demo service at start will run your application as user, script will stop DemoService ( by sc stop DemoService command) and will be ready to run your application next time ;)

pyed commented 9 years ago

@murrayju @kukucz @AndrewSav thanks for helping.

I got it to work the way I want it to work, I didn't want to use full-paths to run my application, I wanted to run it just how calc.exe was running, including my application in the %PATH% wasn't a solution as @AndrewSav explained that earlier, so I moved my application to C:/Windows/SysWOW64 and now I can call it just like calc.exe. ¯\_(ツ)_/¯

murrayju commented 8 years ago

Closing as resolved.

mughil commented 7 years ago

Hi i also getting the following error: StartProcessAsCurrentUser: GetSessionUserToken failed. at ProcessExtension.ProcessExtensions.StartProcessAsCurrentUser(String appPath, String cmdLine, String workDir, Boolean visible) at Scheduler_Service.Service1.StartEXE(String s) at Scheduler_Service.Service1.folderfound(String path)

Iam using this in the network drive location

hmirheydari commented 5 years ago

Hi Justin,

Thanks for your useful piece of code. I am to capture the standard output of the program which is executed with ProcessExtensions.StartProcessAsCurrentUser. Could you add a return value StartProcessAsCurrentUser that returns the standard output of program who is executed?

ranand29 commented 2 months ago

Hi murrayju, I am trying to use the ProcessExtnesions.StartProcessAsCussrentUser in window application (.net framework 4.8 and windows 10). I want to start a pinned web application in task bar if someone closed it and using the following code var app_key = "nfhlhahcgkadabofgdcfegfbdcbdghgg";

            var path = @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge_proxy.exe";
            var arg1s = $"--profile-directory=Default --app-id={app_key} --app-url=https://myapp/auth/realms/abc_Org/protocol/openid-connect/auth?response_type=code&client";
            var str = $"\"{path}\" {arg1s}";

            ProcessExtensions.StartProcessAsCurrentUser(str);

I am getting unable to ger GetSessionTokenUser. IT works fine with calling "calc.exe". Please advise. Thanks.

murrayju commented 2 months ago

Hi folks. This isn't the place to get support. Try stack overflow for that.

If you have reproducible steps for a bug, please make a new ticket.