Windows 7计划程序与System.Diagnostics.Process - dot net有关 [英] Windows 7 Scheduler issues with 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屋!