我有一个类正在尝试使用提供的凭据在服务中创建进程。
启动流程时,我看到错误Cannot create a file when that file already exists
。造成这种情况的原因是什么?
我已经尝试过调用所有类型的可执行文件,所以我知道这不是创建过程的过程。
public class ProcessAsUser
{
static ProcessAsUser()
{
UserToken = IntPtr.Zero;
}
private static IntPtr UserToken { get; set; }
public int StartProcess(ProcessStartInfo processStartInfo)
{
UserToken = IntPtr.Zero;
LogInOtherUser(processStartInfo);
var startUpInfo = new Native.STARTUPINFO();
uint creationFlags = 0;
if (processStartInfo.CreateNoWindow) creationFlags |= Native.CREATE_NO_WINDOW;
var processInfo = new Native.PROCESS_INFORMATION();
bool processStarted = Native.CreateProcessAsUser(
UserToken, // user token
processStartInfo.FileName, // application name
processStartInfo.Arguments, // commandline
IntPtr.Zero, // process attributes
IntPtr.Zero, // thread attributes
true, // inherrit handle
creationFlags, // creation flags
IntPtr.Zero, // environment
processStartInfo.WorkingDirectory+"\\", // current directory
ref startUpInfo,
out processInfo
);
if (!processStarted)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
return 0;
}
int processId = (int)processInfo.dwProcessId;
Native.CloseHandle(processInfo.hProcess);
Native.CloseHandle(processInfo.hThread);
ProcessId = processId;
return ProcessId;
}
public int ProcessId;
private static void LogInOtherUser(ProcessStartInfo processStartInfo)
{
if (UserToken == IntPtr.Zero)
{
var tempUserToken = IntPtr.Zero;
var password = SecureStringToString(processStartInfo.Password);
bool loginResult = Native.LogonUser(processStartInfo.UserName, processStartInfo.Domain, password,
Native.LOGON32_LOGON_BATCH, Native.LOGON32_PROVIDER_DEFAULT,
ref tempUserToken);
if (loginResult)
{
UserToken = tempUserToken;
}
else
{
Native.CloseHandle(tempUserToken);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
private static String SecureStringToString(SecureString value)
{
var stringPointer = Marshal.SecureStringToBSTR(value);
try
{
return Marshal.PtrToStringBSTR(stringPointer);
}
finally
{
Marshal.FreeBSTR(stringPointer);
}
}
public static void ReleaseUserToken()
{
Native.CloseHandle(UserToken);
}
}
internal class Native
{
internal const int LOGON32_LOGON_INTERACTIVE = 2;
internal const int LOGON32_LOGON_BATCH = 4;
internal const int LOGON32_PROVIDER_DEFAULT = 0;
public const int DUPLICATE_SAME_ACCESS = 2;
public const int CREATE_NO_WINDOW = 0x08000000;
public const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
[StructLayout(LayoutKind.Sequential)]
internal class PROCESS_INFORMATION
{
public IntPtr hProcess = IntPtr.Zero;
public IntPtr hThread = IntPtr.Zero;
public uint dwProcessId = 0;
public uint dwThreadId = 0;
}
[StructLayout(LayoutKind.Sequential)]
internal class STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop = string.Empty;
public string lpTitle;
public int dwX = 0;
public int dwY = 0;
public int dwXSize = 0;
public int dwYSize = 0;
public int dwXCountChars = 0;
public int dwYCountChars = 0;
public int dwFillAttribute = 0;
public int dwFlags = 0;
public short wShowWindow = 0;
public short cbReserved2 = 0;
public IntPtr lpReserved2 = IntPtr.Zero;
public IntPtr hStdInput = IntPtr.Zero;
public IntPtr hStdOutput = IntPtr.Zero;
public IntPtr hStdError = IntPtr.Zero;
public STARTUPINFO()
{
cb = Marshal.SizeOf(this);
}
}
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES
{
public SECURITY_ATTRIBUTES()
{
nLength = Marshal.SizeOf(this);
}
public int nLength;
public IntPtr lpSecurityDescriptor = IntPtr.Zero;
public bool bInheritHandle;
}
[DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserA", SetLastError = true, CharSet = CharSet.Ansi)]
internal static extern bool CreateProcessAsUser(
IntPtr hToken,
[MarshalAs(UnmanagedType.LPStr)] string lpApplicationName,
[MarshalAs(UnmanagedType.LPStr)] string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandle,
uint dwCreationFlags,
IntPtr lpEnvironment,
[MarshalAs(UnmanagedType.LPStr)] string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
internal static extern bool CloseHandle(IntPtr handle);
}