Использование Процесса. Начните () запускать процесс как другого пользователя из службы Windows

Я приведу вам простой пример: подумайте об этом коде:

myVar = 0 
print (myVar )      # 01 line: returns 0

def func():
    myVar  = "def"
    print (myVar )

func()              # 02 line: returns def
print (myVar )      # 03 line: returns 0

, поскольку вы можете видеть, что последняя строка кода вернет 0, потому что внутри функции переменная myVar не переназначена , он только что был изменен и будет изменяться только тогда, когда вызываемая функция не влияет на основную переменную myVar, потому что она определена внутри нашей функции (означает, что это локальная переменная), но с использованием глобального ключевого слова как такового:

 myVar  = 0 
print (myVar )       # 01 Line : returns 0

def func():
    global myVar 
    myVar  = "def"
    print (myVar )

func()               # 02 Line : returns def
print (myVar )       # 03 Line : returns def

мы фактически заказываем python, что эта переменная внутри def не является локальной, используйте глобальную переменную с именем myVar, чтобы изменить ее.

35
задан GEOCHET 25 June 2009 в 22:29
поделиться

7 ответов

У меня, кажется, есть рабочая реализация (Работы Над Моим Machine(TM)) для следующих сценариев:

Пакетный файл, Консольный блок.NET.NET приложение Windows Forms.

Вот то, как:

у меня есть сервис окон, работающий как пользователь Администратора. Я добавляю следующие политики к пользователю Администратора:

  • Вход в систему как услуга
  • закон как часть операционной системы
  • Корректирует квоты памяти для процесса
  • Замена маркер уровня процесса

, Эти политики могут быть добавлены путем открытия Control Panel / Средства администрирования / политика Локальной защиты / Пользовательское Присвоение Прав. После того как они установлены, политики не вступают в силу до следующего входа в систему. Можно использовать другого пользователя вместо Администратора, который мог бы сделать вещи немного более безопасными :)

Теперь, мой сервис окон имеет необходимые полномочия запустить задания как другие пользователи. Когда задание должно быть запущено, сервис выполняет отдельный блок ("Начинающий" консольный блок.NET), который инициирует процесс для меня.

следующий код, расположенный в сервисе окон, выполняет мой блок консоли "Starter":

Process proc = null;
System.Diagnostics.ProcessStartInfo info;
string domain = string.IsNullOrEmpty(row.Domain) ? "." : row.Domain;
info = new ProcessStartInfo("Starter.exe");
info.Arguments = cmd + " " + domain + " " + username + " " + password + " " + args;
info.WorkingDirectory = Path.GetDirectoryName(cmd);
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
proc = System.Diagnostics.Process.Start(info);

консольный блок затем запускает целевой процесс через вызовы interop:

class Program
{
    #region Interop

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public UInt32 LowPart;
        public Int32 HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID_AND_ATTRIBUTES
    {
        public LUID Luid;
        public UInt32 Attributes;
    }

    public struct TOKEN_PRIVILEGES
    {
        public UInt32 PrivilegeCount;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public LUID_AND_ATTRIBUTES[] Privileges;
    }

    enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        MaxTokenInfoClass
    }

    [Flags]
    enum CreationFlags : uint
    {
        CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
        CREATE_DEFAULT_ERROR_MODE = 0x04000000,
        CREATE_NEW_CONSOLE = 0x00000010,
        CREATE_NEW_PROCESS_GROUP = 0x00000200,
        CREATE_NO_WINDOW = 0x08000000,
        CREATE_PROTECTED_PROCESS = 0x00040000,
        CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
        CREATE_SEPARATE_WOW_VDM = 0x00001000,
        CREATE_SUSPENDED = 0x00000004,
        CREATE_UNICODE_ENVIRONMENT = 0x00000400,
        DEBUG_ONLY_THIS_PROCESS = 0x00000002,
        DEBUG_PROCESS = 0x00000001,
        DETACHED_PROCESS = 0x00000008,
        EXTENDED_STARTUPINFO_PRESENT = 0x00080000
    }

    public enum TOKEN_TYPE
    {
        TokenPrimary = 1,
        TokenImpersonation
    }

    public enum SECURITY_IMPERSONATION_LEVEL
    {
        SecurityAnonymous,
        SecurityIdentification,
        SecurityImpersonation,
        SecurityDelegation
    }

    [Flags]
    enum LogonFlags
    {
        LOGON_NETCREDENTIALS_ONLY = 2,
        LOGON_WITH_PROFILE = 1
    }

    enum LOGON_TYPE
    {
        LOGON32_LOGON_INTERACTIVE = 2,
        LOGON32_LOGON_NETWORK,
        LOGON32_LOGON_BATCH,
        LOGON32_LOGON_SERVICE,
        LOGON32_LOGON_UNLOCK = 7,
        LOGON32_LOGON_NETWORK_CLEARTEXT,
        LOGON32_LOGON_NEW_CREDENTIALS
    }

    enum LOGON_PROVIDER
    {
        LOGON32_PROVIDER_DEFAULT,
        LOGON32_PROVIDER_WINNT35,
        LOGON32_PROVIDER_WINNT40,
        LOGON32_PROVIDER_WINNT50
    }

    #region _SECURITY_ATTRIBUTES
    //typedef struct _SECURITY_ATTRIBUTES {  
    //    DWORD nLength;  
    //    LPVOID lpSecurityDescriptor;  
    //    BOOL bInheritHandle;
    //} SECURITY_ATTRIBUTES,  *PSECURITY_ATTRIBUTES,  *LPSECURITY_ATTRIBUTES;
    #endregion
    struct SECURITY_ATTRIBUTES
    {
        public uint Length;
        public IntPtr SecurityDescriptor;
        public bool InheritHandle;
    }

    [Flags] enum SECURITY_INFORMATION : uint
    {
        OWNER_SECURITY_INFORMATION        = 0x00000001,
        GROUP_SECURITY_INFORMATION        = 0x00000002,
        DACL_SECURITY_INFORMATION         = 0x00000004,
        SACL_SECURITY_INFORMATION         = 0x00000008,
        UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
        UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
        PROTECTED_SACL_SECURITY_INFORMATION   = 0x40000000,
        PROTECTED_DACL_SECURITY_INFORMATION   = 0x80000000
    }

    #region _SECURITY_DESCRIPTOR
    //typedef struct _SECURITY_DESCRIPTOR {
    //  UCHAR  Revision;
    //  UCHAR  Sbz1;
    //  SECURITY_DESCRIPTOR_CONTROL  Control;
    //  PSID  Owner;
    //  PSID  Group;
    //  PACL  Sacl;
    //  PACL  Dacl;
    //} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
    #endregion
    [StructLayoutAttribute(LayoutKind.Sequential)]
    struct SECURITY_DESCRIPTOR
    {
        public byte revision;
        public byte size;
        public short control; // public SECURITY_DESCRIPTOR_CONTROL control;
        public IntPtr owner;
        public IntPtr group;
        public IntPtr sacl;
        public IntPtr dacl;
    }

    #region _STARTUPINFO
    //typedef struct _STARTUPINFO {  
    //    DWORD cb;  
    //    LPTSTR lpReserved;  
    //    LPTSTR lpDesktop;  
    //    LPTSTR lpTitle;  
    //    DWORD dwX;  
    //    DWORD dwY;  
    //    DWORD dwXSize;  
    //    DWORD dwYSize;  
    //    DWORD dwXCountChars;  
    //    DWORD dwYCountChars;  
    //    DWORD dwFillAttribute;  
    //    DWORD dwFlags;  
    //    WORD wShowWindow;  
    //    WORD cbReserved2;  
    //    LPBYTE lpReserved2;  
    //    HANDLE hStdInput;  
    //    HANDLE hStdOutput;  
    //    HANDLE hStdError; 
    //} STARTUPINFO,  *LPSTARTUPINFO;
    #endregion
    struct STARTUPINFO
    {
        public uint cb;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Reserved;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Desktop;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string Title;
        public uint X;
        public uint Y;
        public uint XSize;
        public uint YSize;
        public uint XCountChars;
        public uint YCountChars;
        public uint FillAttribute;
        public uint Flags;
        public ushort ShowWindow;
        public ushort Reserverd2;
        public byte bReserverd2;
        public IntPtr StdInput;
        public IntPtr StdOutput;
        public IntPtr StdError;
    }

    #region _PROCESS_INFORMATION
    //typedef struct _PROCESS_INFORMATION {  
    //  HANDLE hProcess;  
    //  HANDLE hThread;  
    //  DWORD dwProcessId;  
    //  DWORD dwThreadId; } 
    //  PROCESS_INFORMATION,  *LPPROCESS_INFORMATION;
    #endregion
    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr Process;
        public IntPtr Thread;
        public uint ProcessId;
        public uint ThreadId;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision);
    const uint SECURITY_DESCRIPTOR_REVISION = 1;

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR sd, bool daclPresent, IntPtr dacl, bool daclDefaulted);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    extern static bool DuplicateTokenEx(
        IntPtr hExistingToken,
        uint dwDesiredAccess,
        ref SECURITY_ATTRIBUTES lpTokenAttributes,
        SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
        TOKEN_TYPE TokenType,
        out IntPtr phNewToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );

    #region GetTokenInformation
    //BOOL WINAPI GetTokenInformation(
    //  __in       HANDLE TokenHandle,
    //  __in       TOKEN_INFORMATION_CLASS TokenInformationClass,
    //  __out_opt  LPVOID TokenInformation,
    //  __in       DWORD TokenInformationLength,
    //  __out      PDWORD ReturnLength
    //);
    #endregion
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool GetTokenInformation(
        IntPtr TokenHandle,
        TOKEN_INFORMATION_CLASS TokenInformationClass,
        IntPtr TokenInformation,
        int TokenInformationLength,
        out int ReturnLength
        );


    #region CreateProcessAsUser
    //        BOOL WINAPI CreateProcessAsUser(
    //  __in_opt     HANDLE hToken,
    //  __in_opt     LPCTSTR lpApplicationName,
    //  __inout_opt  LPTSTR lpCommandLine,
    //  __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
    //  __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
    //  __in         BOOL bInheritHandles,
    //  __in         DWORD dwCreationFlags,
    //  __in_opt     LPVOID lpEnvironment,
    //  __in_opt     LPCTSTR lpCurrentDirectory,
    //  __in         LPSTARTUPINFO lpStartupInfo,
    //  __out        LPPROCESS_INFORMATION lpProcessInformation);
    #endregion
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern bool CreateProcessAsUser(
        IntPtr Token, 
        [MarshalAs(UnmanagedType.LPTStr)] string ApplicationName,
        [MarshalAs(UnmanagedType.LPTStr)] string CommandLine,
        ref SECURITY_ATTRIBUTES ProcessAttributes, 
        ref SECURITY_ATTRIBUTES ThreadAttributes, 
        bool InheritHandles,
        uint CreationFlags, 
        IntPtr Environment, 
        [MarshalAs(UnmanagedType.LPTStr)] string CurrentDirectory, 
        ref STARTUPINFO StartupInfo, 
        out PROCESS_INFORMATION ProcessInformation);

    #region CloseHandle
    //BOOL WINAPI CloseHandle(
    //      __in          HANDLE hObject
    //        );
    #endregion
    [DllImport("Kernel32.dll")]
    extern static int CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    //static internal const int TOKEN_QUERY = 0x00000008;
    internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
    //static internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

    internal const int TOKEN_QUERY = 0x00000008;
    internal const int TOKEN_DUPLICATE = 0x0002;
    internal const int TOKEN_ASSIGN_PRIMARY = 0x0001;

    #endregion

    [STAThread]
    static void Main(string[] args)
    {
        string username, domain, password, applicationName;
        username = args[2];
        domain = args[1];
        password = args[3];
        applicationName = @args[0];

        IntPtr token = IntPtr.Zero;
        IntPtr primaryToken = IntPtr.Zero;
        try
        {
            bool result = false;

            result = LogonUser(username, domain, password, (int)LOGON_TYPE.LOGON32_LOGON_NETWORK, (int)LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out token);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }

            string commandLine = null;

            #region security attributes
            SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES();

            SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
            IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
            Marshal.StructureToPtr(sd, ptr, false);
            InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION);
            sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR));

            result = SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }

            primaryToken = new IntPtr();
            result = DuplicateTokenEx(token, 0, ref processAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
            }
            processAttributes.SecurityDescriptor = ptr;
            processAttributes.Length = (uint)Marshal.SizeOf(sd);
            processAttributes.InheritHandle = true;
            #endregion

            SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
            threadAttributes.SecurityDescriptor = IntPtr.Zero;
            threadAttributes.Length = 0;
            threadAttributes.InheritHandle = false;

            bool inheritHandles = true;
            //CreationFlags creationFlags = CreationFlags.CREATE_DEFAULT_ERROR_MODE;
            IntPtr environment = IntPtr.Zero;
            string currentDirectory = currdir;

            STARTUPINFO startupInfo = new STARTUPINFO();
            startupInfo.Desktop = "";

            PROCESS_INFORMATION processInformation;

            result = CreateProcessAsUser(primaryToken, applicationName, commandLine, ref processAttributes, ref threadAttributes, inheritHandles, 16, environment, currentDirectory, ref startupInfo, out processInformation);
            if (!result)
            {
                int winError = Marshal.GetLastWin32Error();
                File.AppendAllText(logfile, DateTime.Now.ToLongTimeString() + " " + winError + Environment.NewLine);
            }
        }
        catch
        {
            int winError = Marshal.GetLastWin32Error();
            File.AppendAllText(logfile, DateTime.Now.ToLongTimeString() + " " + winError + Environment.NewLine);
        }
        finally
        {
            if (token != IntPtr.Zero)
            {
                int x = CloseHandle(token);
                if (x == 0)
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                x = CloseHandle(primaryToken);
                if (x == 0)
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
    }

основная процедура:

  1. Журнал пользователь на
  2. преобразовывает данный маркер в первичный маркер
  3. Используя этот маркер, выполняет процесс
  4. Близко дескриптор по окончании.

Это - код разработки только что из моей машины и никакого пути, почти готового к употреблению в продуктивных средах. Ошибки код здесь является все еще содержащим - Для начинающих: я не уверен, закрываются ли дескрипторы в правой точке, и существует несколько interop функций, определяемых, выше которых не требуются. Отдельный процесс начинающего также действительно раздражает меня. Идеально я хотел бы весь этот материал Job, обернутый в блоке для использования от нашего API, а также этого обслуживания. Если бы у кого-то есть какие-либо предложения здесь, они ценились бы.

23
ответ дан Matt Jacobsen 27 November 2019 в 15:46
поделиться

Я не предложу ни psexec, ни планировщика задачи. Но, Вы посмотрели Sudowin?

Это делает почти точно, чего Вы желаете за исключением, которое это просит пароль прежде, чем выполнить процесс.

кроме того, будучи открытым исходным кодом и всеми, Вы видите, как он выполняет процессы со связанного времени обслуживания и снова.

1
ответ дан Vinko Vrsalovic 27 November 2019 в 15:46
поделиться

Просто предположение - Вы используете LoadUserProfile=true с информацией о запуске? CreateProcessWithLogonW не загружает пользовательскую структуру данных реестра по умолчанию, если Вы не говорите его.

1
ответ дан liggett78 27 November 2019 в 15:46
поделиться

Причина, что сбои вызова после первого раза очень, вероятно, потому что он использует дескриптор безопасности "по умолчанию" (независимо от того, что это).

от msdn:

lpProcessAttributes [в, дополнительный]

указатель А на структуру SECURITY_ATTRIBUTES, которая определяет дескриптор безопасности для нового процесса, возражает, и определяет, могут ли дочерние процессы наследовать возвращенный дескриптор к процессу. Если lpProcessAttributes является ПУСТЫМ, или lpSecurityDescriptor является ПУСТЫМ, процесс получает дескриптор безопасности по умолчанию, и дескриптор не может быть наследован. Дескриптор безопасности по умолчанию является дескриптором безопасности пользователя, на которого ссылаются в hToken параметре. Этот дескриптор безопасности не может предоставить доступ для вызывающей стороны, , в этом случае, процесс не может быть открыт снова после того, как это выполняется. дескриптор процесса допустим и продолжит иметь права полного доступа.

я предполагаю, что CreateProcessWithLogonW создает этот дескриптор безопасности по умолчанию (в любом случае, я не определяю один).

Время для запуска Interopping...

1
ответ дан Matt Jacobsen 27 November 2019 в 15:46
поделиться

Вам не нужен дескриптор окна для использования CreateProcessWithLogonW, я не уверен, куда информация прибыла из.

приложение, отказавшее для инициализации ошибки, имеет много причин, но это почти всегда связывается с безопасностью или исчерпанными пользовательскими ресурсами. Чрезвычайно трудно диагностировать это без намного большей информации о том, что Вы выполняете и контекст, в котором Вы работаете. Но вещи изучить: делает предоставленного пользователя, имеют корректные полномочия получить доступ к каталогу исполняемого файла, делает пользователя, имеют разрешение получить доступ к станции окна и рабочему столу, в котором это запускается, делает это имеет корректные полномочия на любых dll файлах, которые это должно загрузить при инициализации, и т.д.

0
ответ дан Stephen Martin 27 November 2019 в 15:46
поделиться

Я только что перечитал этот комментарий в MSDN ( http://msdn.microsoft.com/en-us/library/ms682431 (По сравнению с 85) .aspx):

не называют пользовательские приложения с этой функцией! ChristianWimmer |
Редактирование | Выставочная История Ожидайте, Если Вы собирающийся называть приложения непривилегированного режима, которые предлагают редактирование документа и подобный материал (как Word), все несохраненные данные, будете потеряны. Это вызвано тем, что обычная последовательность завершения работы не относится к процессам, запущенным с CreateProcessWithLogonW. Таким образом запущенные приложения не получают WM_QUERYENDSESSION, WM_ENDSESSION и самое важное сообщение WM_QUIT. Таким образом, они не просят сохранение данных или очищают свой материал. Они просто выйдут без предупреждения. Эта функция не удобна для пользователя и должна использоваться с осторожностью.

Это - просто "плохой пользовательский опыт". Никто не ожидает его.

Это могло объяснить, что я наблюдал: Работы в первый раз. Перестал работать в каждый последующий раз. Это укрепляет мою веру, что что-то не очищается правильно внутренне

0
ответ дан Matt Jacobsen 27 November 2019 в 15:46
поделиться

Вы говорите, что "Служба Windows запускается с помощью учетных данных "администратора"",

Вы имеете в виду фактическую учетную запись 'Администратора' или пользователя в группе 'Администраторов'? При запуске сервиса, поскольку Администратор решил это для меня.

0
ответ дан Fiona 27 November 2019 в 15:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: