Run .exe not working when Yawcam is running as service

Questions? Suggestions? Need help? Talk about anything related to Yawcam...
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Run .exe not working when Yawcam is running as service

Post by Michionlion »

Title...

I'm on Windows 10, using a microsoft lifecam 3000. I can run a stream perfectly fine in service mode, and the motion detect sound will play as well when activated - the .exe just isn't run, no matter what permissions it requires or where it is located. This only happens when Yawcam is running as a service, when the UI is up it works fine. This is practically identical to an older problem I found here: http://www.yawcam.com/forum/viewtopic.php?t=2323, but no solution was proposed. Are there any fixes or workarounds people have? I'm trying to run a script (.wsf) that will wake the screen up when motion is detected.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

I don't think you can do that since the .exe run is not interactive, so it can't perform any visible tasks to wake the screen up.

I can however provide a script that allows a service to create a process in the user session to wake up the screen.

If you are interested, let me know and we can discuss as this would be a custom script.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

I already have that part - I'm not too bad at scripting, although it is new for me. The problem is that ANY .exe will not run when it is run as a service. Even if the computer is on and fully functioning.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

Have you ever used Process Monitor? It's a tool part of the free Sysinternals suite by Microsoft.

If you can:
Launch Process Monitor, set a filter for the process "Yawcam_Service.exe" this way you elimintate alot of the useless logs.
Stop the Process Monitor capture, it's the little magnifying glass icon
Run Yawcam as a Service
Wait a minute or two
Start the Process Monitor capture, click on the magnifying glass again
Set off the motion however you want
Wait a few seconds
Stop the Process Monitor capture

You should now see lots of logs from Yawcam_Service.exe

Filter the logs again for "Operation" is "Process Create", which should give you a single log.

If you don't see this, save the logs so I can review them and see where it fails.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

Okay, that log does show up. Attached is that, along with the rest filtered under Yawcam_Service.exe. .PML files are apparently not allowed, so I just renamed them .txt - you'll need to change them back.

EDIT: after a bit of digging (opening that log file...) the program is trying to start C:\Users\--\Desktop Rainpad.exe, which is the correct path for the input. when I run 'start "Yawcam Motion Detection" /D C:\Users\--
\Desktop Rainpad.exe' the exe executes. Soo....?
Last edited by Michionlion on Fri Sep 11, 2015 1:28 am, edited 2 times in total.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

I can't see the logs, but the fact that you see that entry tells me Yawcam is actually trying to execute it.

Can you remove the "Process Create" filter and scroll down to see if you see your exe running or anything else that points to your exe?

If you can't post the attachment here, I have an FTP server or you can send me a link to a file sharing website or something.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

http://michionlion.no-ip.org/stuff that's a quick upload for you then.

EDIT: also added logs with the stuff that showed up from Rainpad.exe, the one I tried to run. something happened, it seems, so I'll do it with a different exe and see if something else happens. And then I'll do it with my script and see if that changes. All those logs will be posted in that link, not that you'll need them all though.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

I see rainpad.exe running and loading .Net and all, so as far as I can tell, it's running. I'm not sure what it's supposed to be doing though.

Also, why don't you call the rainpad.exe directly rather than start.exe?

EDIT: In your Yawcam_logs.PML, I see cmd.exe, but it never actually starts, unless the logs got cut off early, otherwise that could point to my second point above.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

Well, It hasn't started - atleast, no UI generated or anything. Tried it on procexp.exe (Process Explorer, from same package as monitor), and same result - showed up, but no UI feedback. That log along with a run of a wsf file (which I think I filtered wrong), is on the site above now. Rainpad.exe isn't mine - no idea what start.exe is.

EDIT: no, that was a good 2-5 seconds afterward. It may have cut off, but there are other logs up there now.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

So it looks like everything is running fine, (rainpad,procexp,...) I didn't see any logs for the WSF, it probably would've launched wscript.exe or something to execute it.

But based on what you're saying is that although everything launches there is still no UI feedback, correct?
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

Yes, that is what happens - it doesn't appear to be related to the exe either, since it happened with both.
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

In that case, I do have a powershell script I wrote, I'll send it to you tomorrow, as long as I don't forget to get it from the office.

Basically the script uses PInvoke, to access the "CreateProcessAsUser" API from Windows. Then it uses the function to create the process under the user profile which does have a UI. The only downside is you have to hardcode the path to the executable you want to launch. You could always call a dummy exe that launches something else though.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

That would be great! I guess that makes sense - since the service isn't attached to a user, the exe is executed in some sort of 'limbo' space, if at all. Maybe that should be a warning somewhere? In any case, thanks!
z3r0c00l12
Moderator
Posts: 1210
Joined: Wed Jan 14, 2009 3:50 am

Re: Run .exe not working when Yawcam is running as service

Post by z3r0c00l12 »

Here it is:

Code: Select all

Function Invoke-ProcessAsInteractiveUser {
    [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact="Low")] # Terminate CmdletBinding
    Param (
        [Parameter(Mandatory=$True,ValueFromPipeLine=$False)]
        [String]$Command,
        [Parameter(Mandatory=$True,ValueFromPipeLine=$False)]
        [String]$TempProcessName)
    Begin {
        $ScriptDir = "$((Get-Location).Path)\"
        if ($TempProcessName -match "(?i)^.+\.exe$") {$TempProcessName = $TempProcessName.SubString(0,$TempProcessName.Length - 4)}
    } # Terminate Begin
    Process {
        $ProgramSource = @"
            using System;
            using System.Text;
            using System.Runtime.InteropServices;
            using System.ServiceProcess;
            using System.Diagnostics;
 
            namespace PS
            {
                public class Emulate {
               
                    static int Main(string[] args) {
                        int iRet = 0;
                        Process pid = EmulateSession.StartProcessInSession(1, @"$command");
                        iRet = pid.Id;
                        return iRet;
                    }
 
                    public static void WriteToEventLog(string message) {
                        string cs = "Interactive_Launcher";
                        EventLog elog = new EventLog();
                        if (!EventLog.SourceExists(cs))
                        {
                            EventLog.CreateEventSource(cs, "Application");
                        }
                        elog.Source = cs;
                        elog.EnableRaisingEvents = true;
                        EventLog.WriteEntry(cs, message, EventLogEntryType.Information);
                    }
                }
 
                static public class EmulateSession
                {
                    /* structs, enums, and external functions defined at end of code */
 
                    public static System.Diagnostics.Process StartProcessInSession(int sessionID, String commandLine)
                    {
                        Emulate.WriteToEventLog("Inside StartProcessInSession");
                        Emulate.WriteToEventLog("Session ID: " + sessionID.ToString());
                        IntPtr userToken;
                        if (WTSQueryUserToken(sessionID, out userToken))
                        {
                            //note that WTSQueryUserToken only works when in context of local system account with SE_TCB_NAME
                            IntPtr lpEnvironment;
                            Emulate.WriteToEventLog("Token: " + userToken.ToString());
                            if (CreateEnvironmentBlock(out lpEnvironment, userToken, false))
                            {
                                Emulate.WriteToEventLog("User Env: " + lpEnvironment.ToString());
                                StartupInfo si = new StartupInfo();
                                si.cb = Marshal.SizeOf(si);
                                si.lpDesktop = "winsta0\\default";
                                si.dwFlags = STARTF.STARTF_USESHOWWINDOW;
                                // Using the SW_HIDE will make the window hidden, see in the bottom section for more commands
                                si.wShowWindow = ShowWindow.SW_HIDE;
                                ProcessInformation pi;
                                // Note the CreationFlags, they make this work as it must have both the CREATE_NEW_CONSOLE and CREATE_UNICODE_ENVIRONMENT
                                if (CreateProcessAsUser(userToken, null, new StringBuilder(commandLine), IntPtr.Zero, IntPtr.Zero, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref si, out pi))
                                {
                                    //CloseHandle(pi.hThread);
                                    //CloseHandle(pi.hProcess);
                                    //context.Undo();
                                    try
                                    {
                                        Emulate.WriteToEventLog("Launched PID: " + pi.dwProcessId.ToString());
                                        return System.Diagnostics.Process.GetProcessById(pi.dwProcessId);
                                    }
                                    catch (ArgumentException)
                                    {
                                        // I had to remove the ArgumentException e (I removed the e), it threw up a compiler warning
                                        //The process ID couldn't be found - which is what always happens because it has closed
                                        return null;
                                    }
                                }
                                else
                                {
                                    Emulate.WriteToEventLog("Could Not Create Process.");
                                    int err = Marshal.GetLastWin32Error();
                                    throw new System.ComponentModel.Win32Exception(err, "Could not create process.\nWin32 error: " + err.ToString());
                                }
                            }
                            else
                            {
                                Emulate.WriteToEventLog("Could not create environment block.");
                                int err = Marshal.GetLastWin32Error();
                                throw new System.ComponentModel.Win32Exception(err, "Could not create environment block.\nWin32 error: " + err.ToString());
                            }
                        }
                        else
                        {
                            Emulate.WriteToEventLog("No Token");
                            int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                            if (err == 1008) return null; //There is no token
                            throw new System.ComponentModel.Win32Exception(err, "Could not get the user token from session " + sessionID.ToString() + " - Error: " + err.ToString());
                        }
                    }
                       
                    [DllImport("wtsapi32.dll", SetLastError = true)]
                    static extern bool WTSQueryUserToken(Int32 sessionId, out IntPtr Token);
 
                    [DllImport("userenv.dll", SetLastError = true)]
                    static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
 
                    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
                    static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, [In] StringBuilder lpCommandLine, IntPtr /*to a SecurityAttributes struct or null*/ lpProcessAttributes, IntPtr /*to a SecurityAttributes struct or null*/ lpThreadAttributes, bool bInheritHandles, CreationFlags creationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);
 
                    [DllImport("kernel32.dll", SetLastError = true)]
                    static extern bool CloseHandle(IntPtr hHandle);
 
                    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
                    struct StartupInfo
                    {
                        public Int32 cb;
                        public String lpReserved;
                        public String lpDesktop;
                        public String lpTitle;
                        public Int32 dwX;
                        public Int32 dwY;
                        public Int32 dwXSize;
                        public Int32 dwYSize;
                        public Int32 dwXCountChars;
                        public Int32 dwYCountChars;
                        public Int32 dwFillAttribute;
                        public STARTF dwFlags;
                        public ShowWindow wShowWindow;
                        public Int16 cbReserved2;
                        public IntPtr lpReserved2;
                        public IntPtr hStdInput;
                        public IntPtr hStdOutput;
                        public IntPtr hStdError;
                    }
 
                    [StructLayout(LayoutKind.Sequential)]
                    internal struct ProcessInformation
                    {
                        public IntPtr hProcess;
                        public IntPtr hThread;
                        public int dwProcessId;
                        public int dwThreadId;
                    }
 
                    /// <summary>
                    /// The following process creation flags are used by the CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, and CreateProcessWithTokenW functions. They can be specified in any combination, except as noted.
                    /// </summary>
                    [Flags]
                    enum CreationFlags : int
                    {
                        NONE = 0,
                        DEBUG_PROCESS = 0x00000001,
                        DEBUG_ONLY_THIS_PROCESS = 0x00000002,
                        CREATE_SUSPENDED = 0x00000004,
                        DETACHED_PROCESS = 0x00000008,
                        CREATE_NEW_CONSOLE = 0x00000010,
                        CREATE_NEW_PROCESS_GROUP = 0x00000200,
                        CREATE_UNICODE_ENVIRONMENT = 0x00000400,
                        CREATE_SEPARATE_WOW_VDM = 0x00000800,
                        CREATE_SHARED_WOW_VDM = 0x00001000,
                        CREATE_PROTECTED_PROCESS = 0x00040000,
                        EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
                        CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
                        CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
                        CREATE_DEFAULT_ERROR_MODE = 0x04000000,
                        CREATE_NO_WINDOW = 0x08000000,
                    }
 
                    [Flags]
                    public enum STARTF : uint
                    {
                        STARTF_USESHOWWINDOW = 0x00000001,
                        STARTF_USESIZE = 0x00000002,
                        STARTF_USEPOSITION = 0x00000004,
                        STARTF_USECOUNTCHARS = 0x00000008,
                        STARTF_USEFILLATTRIBUTE = 0x00000010,
                        STARTF_RUNFULLSCREEN = 0x00000020,  // ignored for non-x86 platforms
                        STARTF_FORCEONFEEDBACK = 0x00000040,
                        STARTF_FORCEOFFFEEDBACK = 0x00000080,
                        STARTF_USESTDHANDLES = 0x00000100,
                    }
 
                    public enum ShowWindow : short
                    {
                        SW_HIDE = 0,
                        SW_SHOWNORMAL = 1,
                        SW_NORMAL = 1,
                        SW_SHOWMINIMIZED = 2,
                        SW_SHOWMAXIMIZED = 3,
                        SW_MAXIMIZE = 3,
                        SW_SHOWNOACTIVATE = 4,
                        SW_SHOW = 5,
                        SW_MINIMIZE = 6,
                        SW_SHOWMINNOACTIVE = 7,
                        SW_SHOWNA = 8,
                        SW_RESTORE = 9,
                        SW_SHOWDEFAULT = 10,
                        SW_FORCEMINIMIZE = 11,
                        SW_MAX = 11
                    }
                }
            }
"@
        # Using the OutputAssembly and OutputType we can make an executable out of this.  It requires the System.ServiceProcess assembly also to inherit the ServiceBase class.
        Add-Type -TypeDefinition $ProgramSource -Language CSharpVersion3 -OutputAssembly ("$ScriptDir$TempProcessName.exe") -OutputType ConsoleApplication -ReferencedAssemblies "System.ServiceProcess"
        Remove-Item -Path ("$ScriptDir$TempProcessName.pdb") -Force
    } # Terminate Process     
}

Invoke-ProcessAsInteractiveUser "C:\Windows\regedit.exe" "Launch_Regedit.exe"
You'll notice the last line, I made an example that launches "C:\Windows\Regedit.exe" and compiles as "Launch_Regedit.exe". Change the last line to whatever you want and execute it in Powershell, it will compile the exe for you then give it a try with Yawcam.
Michionlion
Posts: 14
Joined: Thu Sep 10, 2015 6:22 pm

Re: Run .exe not working when Yawcam is running as service

Post by Michionlion »

Thanks! I'm not very well versed with Powershell stuff, but I gave it a go...

I copied the text over to a .ps1 file, and ran that with admin privileges from a powershell terminal. Initial that had some red text complaining about not finding a Launch_Regedit.pdb (line 214, char 9) to delete. I went and commented out that line, and then it worked and compiled an exe. However, launching that exe by double-clicking throws up the blank has stopped working dialog, and running it through powershell produced this error:

Code: Select all

Unhandled Exception: System.ComponentModel.Win32Exception: Could not get the user token from session 1 - Error: 0
   at PS.EmulateSession.StartProcessInSession(Int32 sessionID, String commandLine)
   at PS.Emulate.Main(String[] args)
So, I assumed it could not get the job done when not run from a service, so I went ahead and pointed Yawcam at that exe and ran it as a service, along with the play a sound thing so I knew when it was triggered. I triggered it, but no feedback, UI or otherwise, besides the sound. Not sure what to do to fix that.
Post Reply