为什么CreateProcessAsUser失败,“当该文件已存在时无法创建文件”

时间:2015-04-01 05:09:07

标签: c# pinvoke createprocess

我有一个类正在尝试使用提供的凭据在服务中创建进程。

启动流程时,我看到错误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);

}

0 个答案:

没有答案