Windows 7计划程序与System.Diagnostics.Process - dot net有关 [英] Windows 7 Scheduler issues with System.Diagnostics.Process - dot net

查看:106
本文介绍了Windows 7计划程序与System.Diagnostics.Process - dot net有关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我写了一个.net应用程序,直到最近,它还安装在XP PC上并在Windows Scheduler下运行。这非常有效。



我们刚刚将应用程序迁移到Windows 7 PC上,当作为标准应用运行时,该应用程序运行良好。单击它然后运行。



但是当我尝试通过Win 7 Scheduler运行它时,它无法正常工作。



在某种程度上,代码使用'System.Diagnostics.Process'来启动ffmpeg.exe作为外部进程。

这是Scheduler行为不端而不让外部进程的地方进程运行。

正如我所说,它在Win 7上完美运行,只是不在Scheduler下。



我想这是一个权限/安全的事情,但该怎么办呢?

schedlue设置的任务运行最高的priveledges。



任何人都有这方面的经验吗?



问候

Malcom

Hi
I have written a .net application which, up till recently, was installed on a XP PC and run under Windows Scheduler. That worked perfectly.

We have just migrated the app to a Windows 7 PC on which runs perfectly when run as astandard app. Click it and it runs.

However when I try and run it via teh Win 7 Scheduler, it does not work correctly.

In part, the code it uses 'System.Diagnostics.Process' to start ffmpeg.exe as an external process.
This is where Scheduler is misbehaving and not letting the external process run.
As I said, it runs perfectly on Win 7, just not under Scheduler.

I guess this is a permissions/security thing but what to do about it?
The schedlue settings have the task runningwith teh highest priveledges.

Anyone have any experience with this at all?

Regards
Malcom

推荐答案

似乎您需要以登录用户身份运行该流程。此代码应该这样做(将其放入新模块中):



Seems like you need to run the process as the logged in user. This code should do it (drop it in a new module):

Imports System.Runtime.InteropServices

Module modProcessAsUser

    <structlayout(layoutkind.sequential)> _
    Private Structure STARTUPINFO
        Public cb As Int32
        Public lpReserved As String
        Public lpDesktop As String
        Public lpTitle As String
        Public dwX As Int32
        Public dwY As Int32
        Public dwXSize As Int32
        Public dwYSize As Int32
        Public dwXCountChars As Int32
        Public dwYCountChars As Int32
        Public dwFillAttribute As Int32
        Public dwFlags As Int32
        Public wShowWindow As Short
        Public cbReserved2 As Short
        Public lpReserved2 As IntPtr
        Public hStdInput As IntPtr
        Public hStdOutput As IntPtr
        Public hStdError As IntPtr
    End Structure

    <structlayout(layoutkind.sequential)> _
    Friend Structure PROCESS_INFORMATION
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As Int32
        Public dwThreadId As Int32
    End Structure

    <structlayout(layoutkind.sequential)> _
    Friend Structure SECURITY_ATTRIBUTES
        Public nLength As Int32
        Public lpSecurityDescriptor As IntPtr
        Public bInheritHandle As Boolean
    End Structure

    Public Enum SECURITY_IMPERSONATION_LEVEL
        SecurityAnonymous
        SecurityIdentification
        SecurityImpersonation
        SecurityDelegation
    End Enum

    Public Enum TOKEN_TYPE
        TokenPrimary = 1
        TokenImpersonation
    End Enum

    Private Declare Auto Function CreateProcessAsUser Lib "advapi32" ( _
            ByVal hToken As IntPtr, _
            ByVal strApplicationName As String, _
            ByVal strCommandLine As String, _
            ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
            ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
            ByVal bInheritHandles As Boolean, _
            ByVal dwCreationFlags As Integer, _
            ByVal lpEnvironment As IntPtr, _
            ByVal lpCurrentDriectory As String, _
            ByRef lpStartupInfo As STARTUPINFO, _
            ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean

    Declare Function DuplicateTokenEx Lib "advapi32.dll" (ByVal hExistingToken As IntPtr, _
        ByVal dwDesiredAccess As System.UInt32, ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
        ByVal ImpersonationLevel As Int32, ByVal dwTokenType As Int32, ByRef phNewToken As IntPtr) As Boolean

    Declare Function CreateEnvironmentBlock Lib "userenv.dll" (ByRef lpEnvironment As IntPtr, _
                                                ByVal hToken As IntPtr, ByVal bInherit As Boolean) As Boolean

    Public Class ProcessAsUser

        Private Const SE_FILE_OBJECT = 1&
        Private Const OWNER_SECURITY_INFORMATION = &H1
        Private Const NAME_SIZE = 64
        Private Const SID_SIZE = 32
        Private Const STARTF_USESHOWWINDOW As Integer = &H1&
        Private Const STARTF_FORCEONFEEDBACK = &H40
        Private Const SW_SHOW = 5
        Private Const CREATE_UNICODE_ENVIRONMENT As Long = &H400&
        Private Const TOKEN_DUPLICATE = &H2
        Private Const TOKEN_ASSIGN_PRIMARY = &H1
        Private Const TOKEN_QUERY = &H8


        Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
        ByVal ProcessHandle As IntPtr, _
        ByVal DesiredAccess As Integer, _
        ByRef TokenHandle As IntPtr) As Boolean

        Declare Function DestroyEnvironmentBlock Lib "userenv.dll" (ByVal lpEnvironment As IntPtr) As Boolean

        Private Shared Function LaunchProcessAsUser(ByVal cmdLine As String, ByVal token As IntPtr, ByVal envBlock As IntPtr) As Boolean
            Dim result As Boolean = False
            Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
            Dim saProcess As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
            Dim saThread As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES

            saProcess.nLength = Runtime.InteropServices.Marshal.SizeOf(saProcess)
            saThread.nLength = Runtime.InteropServices.Marshal.SizeOf(saThread)
            Dim si As STARTUPINFO = New STARTUPINFO
            si.cb = Runtime.InteropServices.Marshal.SizeOf(si)
            si.lpDesktop = Nothing
            si.wShowWindow = 1
            si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_FORCEONFEEDBACK
            si.wShowWindow = SW_SHOW
            result = CreateProcessAsUser(token, cmdLine, "", saProcess, saThread, False, CREATE_UNICODE_ENVIRONMENT, envBlock, Nothing, si, pi)
            If result = False Then
                Dim iError As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error
                Dim message As String = String.Format("CreateProcessAsUser Error: {0}", iError)
                Debug.WriteLine(message)
            End If
            Return result
        End Function

        Private Shared Function GetPrimaryToken(ByVal processId As Integer) As IntPtr
            Dim token As IntPtr = IntPtr.Zero
            Dim primaryToken As IntPtr = IntPtr.Zero
            Dim retVal As Boolean = False
            Dim p As Process = Nothing
            Try
                p = Process.GetProcessById(processId)
            Catch generatedExceptionVariable0 As ArgumentException
                Dim details As String = String.Format("ProcessID {0} Not Available", processId)
                Debug.WriteLine(details)
                Return primaryToken
            End Try
            retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, token)
            If retVal = True Then
                Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
                sa.nLength = Runtime.InteropServices.Marshal.SizeOf(sa)
                retVal = DuplicateTokenEx(token, TOKEN_ASSIGN_PRIMARY Or TOKEN_DUPLICATE Or TOKEN_QUERY, sa, CType(SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Integer), CType(TOKEN_TYPE.TokenPrimary, Integer), primaryToken)
                If retVal = False Then
                    Dim message As String = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error)
                    Debug.WriteLine(message)
                End If
            Else
                Dim message As String = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error)
                Debug.WriteLine(message)
            End If
            Return primaryToken
        End Function

        Private Shared Function GetEnvironmentBlock(ByVal token As IntPtr) As IntPtr
            Dim envBlock As IntPtr = IntPtr.Zero
            Dim retVal As Boolean = CreateEnvironmentBlock(envBlock, token, False)
            If retVal = False Then
                Dim message As String = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error)
                Debug.WriteLine(message)
            End If
            Return envBlock
        End Function

        Public Shared Function Launch(ByVal appCmdLine As String, Optional ByVal processName As String = "explorer") As Boolean
            Dim ret As Boolean = False
            Dim ps As Process() = Process.GetProcessesByName(processName)
            Dim processId As Integer = -1
            If ps.Length > 0 Then
                processId = ps(0).Id
            End If
            If processId > 1 Then
                Dim token As IntPtr = GetPrimaryToken(processId)
                If Not (token.Equals(IntPtr.Zero)) Then
                    Dim envBlock As IntPtr = GetEnvironmentBlock(token)
                    ret = LaunchProcessAsUser(appCmdLine, token, envBlock)
                    If Not (envBlock.Equals(IntPtr.Zero)) Then
                        DestroyEnvironmentBlock(envBlock)
                    End If
                End If
            End If
            Return ret
        End Function
    End Class
End Module





使用启动方法。希望这会有所帮助。



- Pete



Use the "Launch" method. Hope this helps.

- Pete


这里你去了 - 一分钟前测试过它。使用如下:



ProcessAsUser.Launch(c:\YourApp.exe, - 你的命令)



Here ya go - tested it just a minute ago. Use like this:

ProcessAsUser.Launch("c:\YourApp.exe", "-Your -commands")

Imports System.Runtime.InteropServices

Module modProcessAsUser

    <structlayout(layoutkind.sequential)> _
    Private Structure STARTUPINFO
        Public cb As Int32
        Public lpReserved As String
        Public lpDesktop As String
        Public lpTitle As String
        Public dwX As Int32
        Public dwY As Int32
        Public dwXSize As Int32
        Public dwYSize As Int32
        Public dwXCountChars As Int32
        Public dwYCountChars As Int32
        Public dwFillAttribute As Int32
        Public dwFlags As Int32
        Public wShowWindow As Short
        Public cbReserved2 As Short
        Public lpReserved2 As IntPtr
        Public hStdInput As IntPtr
        Public hStdOutput As IntPtr
        Public hStdError As IntPtr
    End Structure

    <structlayout(layoutkind.sequential)> _
    Friend Structure PROCESS_INFORMATION
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As Int32
        Public dwThreadId As Int32
    End Structure

    <structlayout(layoutkind.sequential)> _
    Friend Structure SECURITY_ATTRIBUTES
        Public nLength As Int32
        Public lpSecurityDescriptor As IntPtr
        Public bInheritHandle As Boolean
    End Structure

    Public Enum SECURITY_IMPERSONATION_LEVEL
        SecurityAnonymous
        SecurityIdentification
        SecurityImpersonation
        SecurityDelegation
    End Enum

    Public Enum TOKEN_TYPE
        TokenPrimary = 1
        TokenImpersonation
    End Enum

    Private Declare Auto Function CreateProcessAsUser Lib "advapi32" ( _
            ByVal hToken As IntPtr, _
            ByVal strApplicationName As String, _
            ByVal strCommandLine As String, _
            ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
            ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
            ByVal bInheritHandles As Boolean, _
            ByVal dwCreationFlags As Integer, _
            ByVal lpEnvironment As IntPtr, _
            ByVal lpCurrentDriectory As String, _
            ByRef lpStartupInfo As STARTUPINFO, _
            ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean

    Declare Function DuplicateTokenEx Lib "advapi32.dll" (ByVal hExistingToken As IntPtr, _
        ByVal dwDesiredAccess As System.UInt32, ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
        ByVal ImpersonationLevel As Int32, ByVal dwTokenType As Int32, ByRef phNewToken As IntPtr) As Boolean

    Declare Function CreateEnvironmentBlock Lib "userenv.dll" (ByRef lpEnvironment As IntPtr, _
                                                ByVal hToken As IntPtr, ByVal bInherit As Boolean) As Boolean

    Public Class ProcessAsUser

        Private Const SE_FILE_OBJECT = 1&
        Private Const OWNER_SECURITY_INFORMATION = &H1
        Private Const NAME_SIZE = 64
        Private Const SID_SIZE = 32
        Private Const STARTF_USESHOWWINDOW As Integer = &H1&
        Private Const STARTF_FORCEONFEEDBACK = &H40
        Private Const SW_SHOW = 5
        Private Const CREATE_UNICODE_ENVIRONMENT As Long = &H400&
        Private Const TOKEN_DUPLICATE = &H2
        Private Const TOKEN_ASSIGN_PRIMARY = &H1
        Private Const TOKEN_QUERY = &H8


        Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
        ByVal ProcessHandle As IntPtr, _
        ByVal DesiredAccess As Integer, _
        ByRef TokenHandle As IntPtr) As Boolean

        Declare Function DestroyEnvironmentBlock Lib "userenv.dll" (ByVal lpEnvironment As IntPtr) As Boolean

        Private Shared Function LaunchProcessAsUser(ByVal cmdLine As String, ByVal token As IntPtr, ByVal envBlock As IntPtr, Optional cmds As String = "") As Boolean
            Dim result As Boolean = False
            Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
            Dim saProcess As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
            Dim saThread As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES

            saProcess.nLength = Runtime.InteropServices.Marshal.SizeOf(saProcess)
            saThread.nLength = Runtime.InteropServices.Marshal.SizeOf(saThread)
            Dim si As STARTUPINFO = New STARTUPINFO
            si.cb = Runtime.InteropServices.Marshal.SizeOf(si)
            si.lpDesktop = Nothing
            si.wShowWindow = 1
            si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_FORCEONFEEDBACK
            si.wShowWindow = SW_SHOW
            result = CreateProcessAsUser(token, cmdLine, " " & cmds, saProcess, saThread, False, CREATE_UNICODE_ENVIRONMENT, envBlock, Nothing, si, pi)
            If result = False Then
                Dim iError As Integer = Runtime.InteropServices.Marshal.GetLastWin32Error
                Dim message As String = String.Format("CreateProcessAsUser Error: {0}", iError)
                Debug.WriteLine(message)
            End If
            Return result
        End Function

        Private Shared Function GetPrimaryToken(ByVal processId As Integer) As IntPtr
            Dim token As IntPtr = IntPtr.Zero
            Dim primaryToken As IntPtr = IntPtr.Zero
            Dim retVal As Boolean = False
            Dim p As Process = Nothing
            Try
                p = Process.GetProcessById(processId)
            Catch generatedExceptionVariable0 As ArgumentException
                Dim details As String = String.Format("ProcessID {0} Not Available", processId)
                Debug.WriteLine(details)
                Return primaryToken
            End Try
            retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, token)
            If retVal = True Then
                Dim sa As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
                sa.nLength = Runtime.InteropServices.Marshal.SizeOf(sa)
                retVal = DuplicateTokenEx(token, TOKEN_ASSIGN_PRIMARY Or TOKEN_DUPLICATE Or TOKEN_QUERY, sa, CType(SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, Integer), CType(TOKEN_TYPE.TokenPrimary, Integer), primaryToken)
                If retVal = False Then
                    Dim message As String = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error)
                    Debug.WriteLine(message)
                End If
            Else
                Dim message As String = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error)
                Debug.WriteLine(message)
            End If
            Return primaryToken
        End Function

        Private Shared Function GetEnvironmentBlock(ByVal token As IntPtr) As IntPtr
            Dim envBlock As IntPtr = IntPtr.Zero
            Dim retVal As Boolean = CreateEnvironmentBlock(envBlock, token, False)
            If retVal = False Then
                Dim message As String = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error)
                Debug.WriteLine(message)
            End If
            Return envBlock
        End Function

        Public Shared Function Launch(ByVal appCmdLine As String, Optional cmds As String = "", Optional ByVal processName As String = "explorer") As Boolean
            Dim ret As Boolean = False
            Dim ps As Process() = Process.GetProcessesByName(processName)
            Dim processId As Integer = -1
            If ps.Length > 0 Then
                processId = ps(0).Id
            End If
            If processId > 1 Then
                Dim token As IntPtr = GetPrimaryToken(processId)
                If Not (token.Equals(IntPtr.Zero)) Then
                    Dim envBlock As IntPtr = GetEnvironmentBlock(token)
                    ret = LaunchProcessAsUser(appCmdLine, token, envBlock, cmds)
                    If Not (envBlock.Equals(IntPtr.Zero)) Then
                        DestroyEnvironmentBlock(envBlock)
                    End If
                End If
            End If
            Return ret
        End Function
    End Class
End Module





Hope this helps.



- Pete



Hope this helps.

- Pete


Well, despite the excellent advise received, I have failed completely to get the Win7 Scheduler to do the job its made for.

A simple vb.net app that calls upon ffmpeg as a process. I can ffmpeg to fire up but its internal processes are now failing due to the Win7 Schedulers security crap.



In desperation and a lack of time to explore a code solution, I have found a replacement Scheduler which just works and is easy to use. It does not suffer any of the Win7 security crap and therefore saves me having to write a scheduler myself.



SOLWAY’S TASK SCHEDULER

http://www.theabsolute.net/sware/#tasksched



Hope this helps someone.
Well, despite the excellent advise received, I have failed completely to get the Win7 Scheduler to do the job its made for.
A simple vb.net app that calls upon ffmpeg as a process. I can ffmpeg to fire up but its internal processes are now failing due to the Win7 Schedulers security crap.

In desperation and a lack of time to explore a code solution, I have found a replacement Scheduler which just works and is easy to use. It does not suffer any of the Win7 security crap and therefore saves me having to write a scheduler myself.

SOLWAY'S TASK SCHEDULER
http://www.theabsolute.net/sware/#tasksched

Hope this helps someone.


这篇关于Windows 7计划程序与System.Diagnostics.Process - dot net有关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆