微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从不同的会话中获取 Windows 环境变量的当前值

如何解决如何从不同的会话中获取 Windows 环境变量的当前值

使用带有 .Net 4+ 或 Standard 2.0 或 Windows API 的 C#,我想为所有登录用户获取环境变量的值,让我们将变量称为“标识符”。这些会话的变量是在他们登录后以编程方式设置的(由我无法控制的代码)。他们每次登录时的“标识符”都可以不同。

如何从进程运行所在的会话以外的会话中获取“标识符”环境变量的当前值,或者不可能?

解决方法

用户环境变量可在 HKEY_USERS[SID]\Environment 下访问。您可以使用以下命令来搜索特定的环境变量:

(注意:机器级变量在 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment 中。不会寻找那些。那些应该在你的进程运行的同一个会话下可用,所以它与原始的无关关于会话特定变量的问题。)

将以下内容放入新类:

result <- dplyr::bind_rows(a,b)
result

#  24 period1 period2 ...period30
#1 NA       5       4           4

你可以像这样在winforms中点击按钮来调用它:

    static class WinApis
{        
    [DllImport("Secur32.dll",SetLastError = false)]
    private static extern NtStatus LsaEnumerateLogonSessions(out UInt64 LogonSessionCount,out IntPtr LogonSessionList);
    [DllImport("secur32.dll",SetLastError = false)]
    private static extern NtStatus LsaFreeReturnBuffer([In] IntPtr buffer);

    [DllImport("Secur32.dll",SetLastError = false)]
    private static extern uint LsaGetLogonSessionData(IntPtr luid,out IntPtr ppLogonSessionData);
    private enum NtStatus : uint
    {
        // Success
        Success = 0x00000000,Wait0 = 0x00000000,Wait1 = 0x00000001,Wait2 = 0x00000002,Wait3 = 0x00000003,Wait63 = 0x0000003f,Abandoned = 0x00000080,AbandonedWait0 = 0x00000080,AbandonedWait1 = 0x00000081,AbandonedWait2 = 0x00000082,AbandonedWait3 = 0x00000083,AbandonedWait63 = 0x000000bf,UserApc = 0x000000c0,KernelApc = 0x00000100,Alerted = 0x00000101,Timeout = 0x00000102,Pending = 0x00000103,Reparse = 0x00000104,MoreEntries = 0x00000105,NotAllAssigned = 0x00000106,SomeNotMapped = 0x00000107,OpLockBreakInProgress = 0x00000108,VolumeMounted = 0x00000109,RxActCommitted = 0x0000010a,NotifyCleanup = 0x0000010b,NotifyEnumDir = 0x0000010c,NoQuotasForAccount = 0x0000010d,PrimaryTransportConnectFailed = 0x0000010e,PageFaultTransition = 0x00000110,PageFaultDemandZero = 0x00000111,PageFaultCopyOnWrite = 0x00000112,PageFaultGuardPage = 0x00000113,PageFaultPagingFile = 0x00000114,CrashDump = 0x00000116,ReparseObject = 0x00000118,NothingToTerminate = 0x00000122,ProcessNotInJob = 0x00000123,ProcessInJob = 0x00000124,ProcessCloned = 0x00000129,FileLockedWithOnlyReaders = 0x0000012a,FileLockedWithWriters = 0x0000012b,// Informational
        Informational = 0x40000000,ObjectNameExists = 0x40000000,ThreadWasSuspended = 0x40000001,WorkingSetLimitRange = 0x40000002,ImageNotAtBase = 0x40000003,RegistryRecovered = 0x40000009,// Warning
        Warning = 0x80000000,GuardPageViolation = 0x80000001,DatatypeMisalignment = 0x80000002,Breakpoint = 0x80000003,SingleStep = 0x80000004,BufferOverflow = 0x80000005,NoMoreFiles = 0x80000006,HandlesClosed = 0x8000000a,PartialCopy = 0x8000000d,DeviceBusy = 0x80000011,InvalidEaName = 0x80000013,EaListInconsistent = 0x80000014,NoMoreEntries = 0x8000001a,LongJump = 0x80000026,DllMightBeInsecure = 0x8000002b,// Error
        Error = 0xc0000000,Unsuccessful = 0xc0000001,NotImplemented = 0xc0000002,InvalidInfoClass = 0xc0000003,InfoLengthMismatch = 0xc0000004,AccessViolation = 0xc0000005,InPageError = 0xc0000006,PagefileQuota = 0xc0000007,InvalidHandle = 0xc0000008,BadInitialStack = 0xc0000009,BadInitialPc = 0xc000000a,InvalidCid = 0xc000000b,TimerNotCanceled = 0xc000000c,InvalidParameter = 0xc000000d,NoSuchDevice = 0xc000000e,NoSuchFile = 0xc000000f,InvalidDeviceRequest = 0xc0000010,EndOfFile = 0xc0000011,WrongVolume = 0xc0000012,NoMediaInDevice = 0xc0000013,NoMemory = 0xc0000017,NotMappedView = 0xc0000019,UnableToFreeVm = 0xc000001a,UnableToDeleteSection = 0xc000001b,IllegalInstruction = 0xc000001d,AlreadyCommitted = 0xc0000021,AccessDenied = 0xc0000022,BufferTooSmall = 0xc0000023,ObjectTypeMismatch = 0xc0000024,NonContinuableException = 0xc0000025,BadStack = 0xc0000028,NotLocked = 0xc000002a,NotCommitted = 0xc000002d,InvalidParameterMix = 0xc0000030,ObjectNameInvalid = 0xc0000033,ObjectNameNotFound = 0xc0000034,ObjectNameCollision = 0xc0000035,ObjectPathInvalid = 0xc0000039,ObjectPathNotFound = 0xc000003a,ObjectPathSyntaxBad = 0xc000003b,DataOverrun = 0xc000003c,DataLate = 0xc000003d,DataError = 0xc000003e,CrcError = 0xc000003f,SectionTooBig = 0xc0000040,PortConnectionRefused = 0xc0000041,InvalidPortHandle = 0xc0000042,SharingViolation = 0xc0000043,QuotaExceeded = 0xc0000044,InvalidPageProtection = 0xc0000045,MutantNotOwned = 0xc0000046,SemaphoreLimitExceeded = 0xc0000047,PortAlreadySet = 0xc0000048,SectionNotImage = 0xc0000049,SuspendCountExceeded = 0xc000004a,ThreadIsTerminating = 0xc000004b,BadWorkingSetLimit = 0xc000004c,IncompatibleFileMap = 0xc000004d,SectionProtection = 0xc000004e,EasNotSupported = 0xc000004f,EaTooLarge = 0xc0000050,NonExistentEaEntry = 0xc0000051,NoEasOnFile = 0xc0000052,EaCorruptError = 0xc0000053,FileLockConflict = 0xc0000054,LockNotGranted = 0xc0000055,DeletePending = 0xc0000056,CtlFileNotSupported = 0xc0000057,UnknownRevision = 0xc0000058,RevisionMismatch = 0xc0000059,InvalidOwner = 0xc000005a,InvalidPrimaryGroup = 0xc000005b,NoImpersonationToken = 0xc000005c,CantDisableMandatory = 0xc000005d,NoLogonServers = 0xc000005e,NoSuchLogonSession = 0xc000005f,NoSuchPrivilege = 0xc0000060,PrivilegeNotHeld = 0xc0000061,InvalidAccountName = 0xc0000062,UserExists = 0xc0000063,NoSuchUser = 0xc0000064,GroupExists = 0xc0000065,NoSuchGroup = 0xc0000066,MemberInGroup = 0xc0000067,MemberNotInGroup = 0xc0000068,LastAdmin = 0xc0000069,WrongPassword = 0xc000006a,IllFormedPassword = 0xc000006b,PasswordRestriction = 0xc000006c,LogonFailure = 0xc000006d,AccountRestriction = 0xc000006e,InvalidLogonHours = 0xc000006f,InvalidWorkstation = 0xc0000070,PasswordExpired = 0xc0000071,AccountDisabled = 0xc0000072,NoneMapped = 0xc0000073,TooManyLuidsRequested = 0xc0000074,LuidsExhausted = 0xc0000075,InvalidSubAuthority = 0xc0000076,InvalidAcl = 0xc0000077,InvalidSid = 0xc0000078,InvalidSecurityDescr = 0xc0000079,ProcedureNotFound = 0xc000007a,InvalidImageFormat = 0xc000007b,NoToken = 0xc000007c,BadInheritanceAcl = 0xc000007d,RangeNotLocked = 0xc000007e,DiskFull = 0xc000007f,ServerDisabled = 0xc0000080,ServerNotDisabled = 0xc0000081,TooManyGuidsRequested = 0xc0000082,GuidsExhausted = 0xc0000083,InvalidIdAuthority = 0xc0000084,AgentsExhausted = 0xc0000085,InvalidVolumeLabel = 0xc0000086,SectionNotExtended = 0xc0000087,NotMappedData = 0xc0000088,ResourceDataNotFound = 0xc0000089,ResourceTypeNotFound = 0xc000008a,ResourceNameNotFound = 0xc000008b,ArrayBoundsExceeded = 0xc000008c,FloatDenormalOperand = 0xc000008d,FloatDivideByZero = 0xc000008e,FloatInexactResult = 0xc000008f,FloatInvalidOperation = 0xc0000090,FloatOverflow = 0xc0000091,FloatStackCheck = 0xc0000092,FloatUnderflow = 0xc0000093,IntegerDivideByZero = 0xc0000094,IntegerOverflow = 0xc0000095,PrivilegedInstruction = 0xc0000096,TooManyPagingFiles = 0xc0000097,FileInvalid = 0xc0000098,InstanceNotAvailable = 0xc00000ab,PipeNotAvailable = 0xc00000ac,InvalidPipeState = 0xc00000ad,PipeBusy = 0xc00000ae,IllegalFunction = 0xc00000af,PipeDisconnected = 0xc00000b0,PipeClosing = 0xc00000b1,PipeConnected = 0xc00000b2,PipeListening = 0xc00000b3,InvalidReadMode = 0xc00000b4,IoTimeout = 0xc00000b5,FileForcedClosed = 0xc00000b6,ProfilingNotStarted = 0xc00000b7,ProfilingNotStopped = 0xc00000b8,NotSameDevice = 0xc00000d4,FileRenamed = 0xc00000d5,CantWait = 0xc00000d8,PipeEmpty = 0xc00000d9,CantTerminateSelf = 0xc00000db,InternalError = 0xc00000e5,InvalidParameter1 = 0xc00000ef,InvalidParameter2 = 0xc00000f0,InvalidParameter3 = 0xc00000f1,InvalidParameter4 = 0xc00000f2,InvalidParameter5 = 0xc00000f3,InvalidParameter6 = 0xc00000f4,InvalidParameter7 = 0xc00000f5,InvalidParameter8 = 0xc00000f6,InvalidParameter9 = 0xc00000f7,InvalidParameter10 = 0xc00000f8,InvalidParameter11 = 0xc00000f9,InvalidParameter12 = 0xc00000fa,MappedFileSizeZero = 0xc000011e,TooManyOpenedFiles = 0xc000011f,Cancelled = 0xc0000120,CannotDelete = 0xc0000121,InvalidComputerName = 0xc0000122,FileDeleted = 0xc0000123,SpecialAccount = 0xc0000124,SpecialGroup = 0xc0000125,SpecialUser = 0xc0000126,MembersPrimaryGroup = 0xc0000127,FileClosed = 0xc0000128,TooManyThreads = 0xc0000129,ThreadNotInProcess = 0xc000012a,TokenAlreadyInUse = 0xc000012b,PagefileQuotaExceeded = 0xc000012c,CommitmentLimit = 0xc000012d,InvalidImageLeFormat = 0xc000012e,InvalidImageNotMz = 0xc000012f,InvalidImageProtect = 0xc0000130,InvalidImageWin16 = 0xc0000131,LogonServer = 0xc0000132,DifferenceAtDc = 0xc0000133,SynchronizationRequired = 0xc0000134,DllNotFound = 0xc0000135,IoPrivilegeFailed = 0xc0000137,OrdinalNotFound = 0xc0000138,EntryPointNotFound = 0xc0000139,ControlCExit = 0xc000013a,PortNotSet = 0xc0000353,DebuggerInactive = 0xc0000354,CallbackBypass = 0xc0000503,PortClosed = 0xc0000700,MessageLost = 0xc0000701,InvalidMessage = 0xc0000702,RequestCanceled = 0xc0000703,RecursiveDispatch = 0xc0000704,LpcReceiveBufferExpected = 0xc0000705,LpcInvalidConnectionUsage = 0xc0000706,LpcRequestsNotAllowed = 0xc0000707,ResourceInUse = 0xc0000708,ProcessIsProtected = 0xc0000712,VolumeDirty = 0xc0000806,FileCheckedOut = 0xc0000901,CheckOutRequired = 0xc0000902,BadFileType = 0xc0000903,FileTooLarge = 0xc0000904,FormsAuthRequired = 0xc0000905,VirusInfected = 0xc0000906,VirusDeleted = 0xc0000907,TransactionalConflict = 0xc0190001,InvalidTransaction = 0xc0190002,TransactionNotActive = 0xc0190003,TmInitializationFailed = 0xc0190004,RmNotActive = 0xc0190005,RmMetadataCorrupt = 0xc0190006,TransactionNotJoined = 0xc0190007,DirectoryNotRm = 0xc0190008,CouldNotResizeLog = 0xc0190009,TransactionsUnsupportedRemote = 0xc019000a,LogResizeInvalidSize = 0xc019000b,RemoteFileVersionMismatch = 0xc019000c,CrmProtocolAlreadyExists = 0xc019000f,TransactionPropagationFailed = 0xc0190010,CrmProtocolNotFound = 0xc0190011,TransactionSuperiorExists = 0xc0190012,TransactionRequestNotValid = 0xc0190013,TransactionNotRequested = 0xc0190014,TransactionAlreadyAborted = 0xc0190015,TransactionAlreadyCommitted = 0xc0190016,TransactionInvalidMarshallBuffer = 0xc0190017,CurrentTransactionNotValid = 0xc0190018,LogGrowthFailed = 0xc0190019,ObjectNoLongerExists = 0xc0190021,StreamMiniversionNotFound = 0xc0190022,StreamMiniversionNotValid = 0xc0190023,MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024,CantOpenMiniversionWithModifyIntent = 0xc0190025,CantCreateMoreStreamMiniversions = 0xc0190026,HandleNoLongerValid = 0xc0190028,NoTxfMetadata = 0xc0190029,LogCorruptionDetected = 0xc0190030,CantRecoverWithHandleOpen = 0xc0190031,RmDisconnected = 0xc0190032,EnlistmentNotSuperior = 0xc0190033,RecoveryNotNeeded = 0xc0190034,RmAlreadyStarted = 0xc0190035,FileIdentityNotPersistent = 0xc0190036,CantBreakTransactionalDependency = 0xc0190037,CantCrossRmBoundary = 0xc0190038,TxfDirNotEmpty = 0xc0190039,IndoubtTransactionsExist = 0xc019003a,TmVolatile = 0xc019003b,RollbackTimerExpired = 0xc019003c,TxfAttributeCorrupt = 0xc019003d,EfsNotAllowedInTransaction = 0xc019003e,TransactionalOpenNotAllowed = 0xc019003f,TransactedMappingUnsupportedRemote = 0xc0190040,TxfMetadataAlreadyPresent = 0xc0190041,TransactionScopeCallbacksNotSet = 0xc0190042,TransactionRequiredPromotion = 0xc0190043,CannotExecuteFileInTransaction = 0xc0190044,TransactionsNotFrozen = 0xc0190045,MaximumNtStatus = 0xffffffff
    }
    [StructLayout(LayoutKind.Sequential)]

    private struct LSA_UNICODE_STRING

    {

        public UInt16 Length;
        public UInt16 MaximumLength;
        public IntPtr buffer;

    }

    [StructLayout(LayoutKind.Sequential)]

    private struct LUID

    {

        public UInt32 LowPart;
        public UInt32 HighPart;

    }

    [StructLayout(LayoutKind.Sequential)]

    private struct SECURITY_LOGON_SESSION_DATA

    {

        public UInt32 Size;
        public LUID LoginID;
        public LSA_UNICODE_STRING Username;
        public LSA_UNICODE_STRING LoginDomain;
        public LSA_UNICODE_STRING AuthenticationPackage;
        public UInt32 LogonType;
        public UInt32 Session;
        public IntPtr PSiD;
        public UInt64 LoginTime;
        public LSA_UNICODE_STRING LogonServer;
        public LSA_UNICODE_STRING DnsDomainName;
        public LSA_UNICODE_STRING Upn;

    }

    private enum SECURITY_LOGON_TYPE : uint

    {

        Interactive = 2,//The security principal is logging on interactively.
        Network,//The security principal is logging using a network.
        Batch,//The logon is for a batch process.
        Service,//The logon is for a service account.
        Proxy,//Not supported.
        Unlock,//The logon is an attempt to unlock a workstation.
        NetworkCleartext,//The logon is a network logon with cleartext credentials.
        NewCredentials,// Allows the caller to clone its current token and specify new credentials for outbound connections.
        RemoteInteractive,// A terminal server session that is both remote and interactive.
        CachedInteractive,// Attempt to use the cached credentials without going out across the network.
        CachedRemoteInteractive,// Same as RemoteInteractive,except used internally for auditing purposes.
        CachedUnlock      // The logon is an attempt to unlock a workstation.

    }
    public static List<string> GetSessionEnvironmentValue(string variableName,string userFilter="")
    {
        // Based on: https://stackoverflow.com/questions/27826595/wtsenumeratesessions-hangs-and-never-returns
        // Which appears similar to PS script: https://www.pinvoke.net/default.aspx/secur32/LsaEnumerateLogonSessions.html
        
        var outList = new List<string>();
        System.Security.Principal.WindowsIdentity currentUser = System.Security.Principal.WindowsIdentity.GetCurrent();

        DateTime systime = new DateTime(1601,1,0); //win32 systemdate

        UInt64 count;
        IntPtr luidPtr = IntPtr.Zero;
        LsaEnumerateLogonSessions(out count,out luidPtr);  //gets an array of pointers to LUIDs

        IntPtr iter = luidPtr;      //set the pointer to the start of the array

        for (ulong i = 0; i < count; i++)   //for each pointer in the array
        {
            IntPtr sessionData;

            LsaGetLogonSessionData(iter,out sessionData);
            SECURITY_LOGON_SESSION_DATA data = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(sessionData,typeof(SECURITY_LOGON_SESSION_DATA));

            //if we have a valid logon
            if (data.PSiD != IntPtr.Zero)
            {
                //get the security identifier for further use
                System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(data.PSiD);

                //extract some useful information from the session data struct
                var ptrToStringUni = Marshal.PtrToStringUni(data.Username.buffer);
                if (ptrToStringUni != null)
                {
                    string username = ptrToStringUni.Trim();          //get the account username
                    var toStringUni = Marshal.PtrToStringUni(data.LoginDomain.buffer);
                    if (toStringUni != null)
                    {
                        string domain = toStringUni.Trim();        //domain for this account  
                        var stringUni = Marshal.PtrToStringUni(data.AuthenticationPackage.buffer);
                        if (stringUni != null)
                        {
                            string authpackage = stringUni.Trim();    //authentication package
                        }
                        string session = data.Session.ToString();
                        SECURITY_LOGON_TYPE secType = (SECURITY_LOGON_TYPE)data.LogonType;
                        DateTime time = systime.AddTicks((long)data.LoginTime); //get the datetime the session was logged in

                        // get variable
                        var envVarVal = GetUserEnvironmentValue(sid.Value,variableName);

                        // Only add result to list if it meets username filter
                        if (envVarVal!="" && (userFilter=="" || username.ToLower().Contains(userFilter.ToLower())))
                        {
                            outList.Add($"User: {username},EnvironVar({variableName}): {envVarVal},SID: {sid.Value}");
                        }

                    }
                }
            }
            iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LUID)));  //move the pointer forward
            LsaFreeReturnBuffer(sessionData);   //free the SECURITY_LOGON_SESSION_DATA memory in the struct
        }
        LsaFreeReturnBuffer(luidPtr);   //free the array of LUIDs

        return outList;
    }

    private static string GetUserEnvironmentValue(string sid,string variableName)
    {
        var envKey = Registry.Users.OpenSubKey($@"{sid}\Environment");
        if (envKey != null)
        {
            var envVarVal = envKey.GetValue(variableName);
            if (envVarVal!=null)
                return envVarVal.ToString();
        }
        return "";
    }

}

虽然这并没有给我我最终需要的东西,但它回答了我所说的问题。

我最终选择了不同的路线,因为我需要的环境变量是在脚本/批处理文件中设置的,或者直接传递给我的可执行文件,并且无法在不使用其他 API 的情况下进行检查...>

如果其他人有类似的情况,我最终会通过 nuget 包使用 Gapotchenko.FX.Diagnostics.Process 并使用与管理员类似的内容进行搜索:

    private void btnOthersEnvVars_Click(object sender,EventArgs e)
    {
        if (txtEnvVar.Text == "")
            throw new Exception("You didn't supply a variable name...");

        var sb = new StringBuilder();
        foreach (var sessionInfo in WinApis.GetSessionEnvironmentValue(txtEnvVar.Text)) // you can add a username param as well
        {
            sb.AppendLine(sessionInfo);
        }
        Console.WriteLine(sb.ToString());
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。