├── Notif_Config.xml ├── Notif_User.ps1 ├── Public └── Invoke-AsCurrentUser.ps1 ├── README.md ├── RunAsUser └── 1.5.1 │ ├── LICENSE │ ├── PSGetModuleInfo.xml │ ├── Public │ └── Invoke-AsCurrentUser.ps1 │ ├── README.md │ ├── RunAsUser.psd1 │ └── runasuser.psm1 ├── display_notif.ps1 ├── logo_header.png └── preview_header.gif /Notif_Config.xml: -------------------------------------------------------------------------------- 1 | 2 | C:\ProgramData\intune_notif 3 | Quick notification 4 | I am a notification executed in System context 5 | Syst and Deploy 6 | logo_header.png 7 | short 8 | 9 | -------------------------------------------------------------------------------- /Notif_User.ps1: -------------------------------------------------------------------------------- 1 | $Global:Current_Folder = split-path $MyInvocation.MyCommand.Path 2 | 3 | $Notif_Config_XML = "$Current_Folder\Notif_Config.xml" 4 | $Get_Notif_Content = ([xml](get-content $Notif_Config_XML)).Toast_Notif 5 | $Title = $Get_Notif_Content.Notif_Title 6 | $Message = $Get_Notif_Content.Notif_Text 7 | $Attribution = $Get_Notif_Content.Notif_Attribution 8 | $HeaderLogo = $Get_Notif_Content.Notif_Picture 9 | $NotifFolder = $Get_Notif_Content.Notif_Folder 10 | $NotifScenario = $Get_Notif_Content.Notif_Scenario 11 | 12 | $Scenario = "$NotifScenario" 13 | $LogoType = "crop" 14 | $HeroImage = "$NotifFolder\$HeaderLogo" 15 | [xml]$Toast = @" 16 | 17 | 18 | 19 | 20 | $Attribution 21 | $Title 22 | $Message 23 | 24 | 25 | 26 | "@ 27 | $Load = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] 28 | $Load = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] 29 | $AppID = "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe" 30 | $ToastXml = New-Object -TypeName Windows.Data.Xml.Dom.XmlDocument 31 | $ToastXml.LoadXml($Toast.OuterXml) 32 | [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppID).Show($ToastXml) -------------------------------------------------------------------------------- /Public/Invoke-AsCurrentUser.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-AsCurrentUser { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory = $true)] 5 | [scriptblock] 6 | $ScriptBlock, 7 | [Parameter(Mandatory = $false)] 8 | [switch]$NoWait 9 | ) 10 | if (!("RunAsUser.ProcessExtensions" -as [type])) { 11 | Add-Type -TypeDefinition $script:source -Language CSharp 12 | } 13 | $encodedcommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($ScriptBlock)) 14 | $privs = whoami /priv /fo csv | ConvertFrom-Csv | Where-Object { $_.'Privilege Name' -eq 'SeDelegateSessionUserImpersonatePrivilege' } 15 | if ($privs.State -eq "Disabled") { 16 | Write-Error -Message "Not running with correct privilege. You must run this script as system or have the SeDelegateSessionUserImpersonatePrivilege token." 17 | return 18 | } 19 | else { 20 | try { 21 | # Use the same PowerShell executable as the one that invoked the function 22 | $pwshPath = (Get-Process -Id $pid).Path 23 | if ($NoWait) { $ProcWaitTime = 1 } else { $ProcWaitTime = -1 } 24 | [RunAsUser.ProcessExtensions]::StartProcessAsCurrentUser( 25 | $pwshPath, "`"$pwshPath`" -ExecutionPolicy Bypass -Window Normal -EncodedCommand $($encodedcommand)", 26 | (Split-Path $pwshPath -Parent), $false,$ProcWaitTime) 27 | } catch { 28 | Write-Error -Message "Could not execute as currently logged on user: $($_.Exception.Message)" -Exception $_.Exception 29 | return 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell Toast Notification with Header 2 | 3 | Display simple toast notification with Header picture for user in System context with Intune or SCCM 4 | 5 | > *View the full blog post here* 6 | http://www.systanddeploy.com/2020/06/ps1-to-service-tool-to-convert-your-ps1.html 7 | 8 | ![alt text](https://github.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/blob/master/preview_header.gif) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /RunAsUser/1.5.1/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kelvin Tegelaar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RunAsUser/1.5.1/PSGetModuleInfo.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/5c26f226a3eac2633bda0d59f8949644b9697cc4/RunAsUser/1.5.1/PSGetModuleInfo.xml -------------------------------------------------------------------------------- /RunAsUser/1.5.1/Public/Invoke-AsCurrentUser.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-AsCurrentUser { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Mandatory = $true)] 5 | [scriptblock] 6 | $ScriptBlock, 7 | [Parameter(Mandatory = $false)] 8 | [switch]$NoWait 9 | ) 10 | if (!("RunAsUser.ProcessExtensions" -as [type])) { 11 | Add-Type -TypeDefinition $script:source -Language CSharp 12 | } 13 | $encodedcommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($ScriptBlock)) 14 | $privs = whoami /priv /fo csv | ConvertFrom-Csv | Where-Object { $_.'Privilege Name' -eq 'SeDelegateSessionUserImpersonatePrivilege' } 15 | if ($privs.State -eq "Disabled") { 16 | Write-Error -Message "Not running with correct privilege. You must run this script as system or have the SeDelegateSessionUserImpersonatePrivilege token." 17 | return 18 | } 19 | else { 20 | try { 21 | # Use the same PowerShell executable as the one that invoked the function 22 | $pwshPath = (Get-Process -Id $pid).Path 23 | if ($NoWait) { $ProcWaitTime = 1 } else { $ProcWaitTime = -1 } 24 | [RunAsUser.ProcessExtensions]::StartProcessAsCurrentUser( 25 | $pwshPath, "`"$pwshPath`" -ExecutionPolicy Bypass -Window Normal -EncodedCommand $($encodedcommand)", 26 | (Split-Path $pwshPath -Parent), $false,$ProcWaitTime) 27 | } catch { 28 | Write-Error -Message "Could not execute as currently logged on user: $($_.Exception.Message)" -Exception $_.Exception 29 | return 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /RunAsUser/1.5.1/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/5c26f226a3eac2633bda0d59f8949644b9697cc4/RunAsUser/1.5.1/README.md -------------------------------------------------------------------------------- /RunAsUser/1.5.1/RunAsUser.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/5c26f226a3eac2633bda0d59f8949644b9697cc4/RunAsUser/1.5.1/RunAsUser.psd1 -------------------------------------------------------------------------------- /RunAsUser/1.5.1/runasuser.psm1: -------------------------------------------------------------------------------- 1 | $script:source = @" 2 | using Microsoft.Win32.SafeHandles; 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace RunAsUser 8 | { 9 | internal class NativeHelpers 10 | { 11 | [StructLayout(LayoutKind.Sequential)] 12 | public struct PROCESS_INFORMATION 13 | { 14 | public IntPtr hProcess; 15 | public IntPtr hThread; 16 | public int dwProcessId; 17 | public int dwThreadId; 18 | } 19 | 20 | [StructLayout(LayoutKind.Sequential)] 21 | public struct STARTUPINFO 22 | { 23 | public int cb; 24 | public String lpReserved; 25 | public String lpDesktop; 26 | public String lpTitle; 27 | public uint dwX; 28 | public uint dwY; 29 | public uint dwXSize; 30 | public uint dwYSize; 31 | public uint dwXCountChars; 32 | public uint dwYCountChars; 33 | public uint dwFillAttribute; 34 | public uint dwFlags; 35 | public short wShowWindow; 36 | public short cbReserved2; 37 | public IntPtr lpReserved2; 38 | public IntPtr hStdInput; 39 | public IntPtr hStdOutput; 40 | public IntPtr hStdError; 41 | } 42 | 43 | [StructLayout(LayoutKind.Sequential)] 44 | public struct WTS_SESSION_INFO 45 | { 46 | public readonly UInt32 SessionID; 47 | 48 | [MarshalAs(UnmanagedType.LPStr)] 49 | public readonly String pWinStationName; 50 | 51 | public readonly WTS_CONNECTSTATE_CLASS State; 52 | } 53 | } 54 | 55 | internal class NativeMethods 56 | { 57 | [DllImport("kernel32", SetLastError=true)] 58 | public static extern int WaitForSingleObject( 59 | IntPtr hHandle, 60 | int dwMilliseconds); 61 | 62 | [DllImport("kernel32.dll", SetLastError = true)] 63 | public static extern bool CloseHandle( 64 | IntPtr hSnapshot); 65 | 66 | [DllImport("userenv.dll", SetLastError = true)] 67 | public static extern bool CreateEnvironmentBlock( 68 | ref IntPtr lpEnvironment, 69 | SafeHandle hToken, 70 | bool bInherit); 71 | 72 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 73 | public static extern bool CreateProcessAsUserW( 74 | SafeHandle hToken, 75 | String lpApplicationName, 76 | StringBuilder lpCommandLine, 77 | IntPtr lpProcessAttributes, 78 | IntPtr lpThreadAttributes, 79 | bool bInheritHandle, 80 | uint dwCreationFlags, 81 | IntPtr lpEnvironment, 82 | String lpCurrentDirectory, 83 | ref NativeHelpers.STARTUPINFO lpStartupInfo, 84 | out NativeHelpers.PROCESS_INFORMATION lpProcessInformation); 85 | 86 | [DllImport("userenv.dll", SetLastError = true)] 87 | [return: MarshalAs(UnmanagedType.Bool)] 88 | public static extern bool DestroyEnvironmentBlock( 89 | IntPtr lpEnvironment); 90 | 91 | [DllImport("advapi32.dll", SetLastError = true)] 92 | public static extern bool DuplicateTokenEx( 93 | SafeHandle ExistingTokenHandle, 94 | uint dwDesiredAccess, 95 | IntPtr lpThreadAttributes, 96 | SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 97 | TOKEN_TYPE TokenType, 98 | out SafeNativeHandle DuplicateTokenHandle); 99 | 100 | [DllImport("advapi32.dll", SetLastError = true)] 101 | public static extern bool GetTokenInformation( 102 | SafeHandle TokenHandle, 103 | uint TokenInformationClass, 104 | SafeMemoryBuffer TokenInformation, 105 | int TokenInformationLength, 106 | out int ReturnLength); 107 | 108 | [DllImport("wtsapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 109 | public static extern bool WTSEnumerateSessions( 110 | IntPtr hServer, 111 | int Reserved, 112 | int Version, 113 | ref IntPtr ppSessionInfo, 114 | ref int pCount); 115 | 116 | [DllImport("wtsapi32.dll")] 117 | public static extern void WTSFreeMemory( 118 | IntPtr pMemory); 119 | 120 | [DllImport("kernel32.dll")] 121 | public static extern uint WTSGetActiveConsoleSessionId(); 122 | 123 | [DllImport("Wtsapi32.dll", SetLastError = true)] 124 | public static extern bool WTSQueryUserToken( 125 | uint SessionId, 126 | out SafeNativeHandle phToken); 127 | } 128 | 129 | internal class SafeMemoryBuffer : SafeHandleZeroOrMinusOneIsInvalid 130 | { 131 | public SafeMemoryBuffer(int cb) : base(true) 132 | { 133 | base.SetHandle(Marshal.AllocHGlobal(cb)); 134 | } 135 | public SafeMemoryBuffer(IntPtr handle) : base(true) 136 | { 137 | base.SetHandle(handle); 138 | } 139 | 140 | protected override bool ReleaseHandle() 141 | { 142 | Marshal.FreeHGlobal(handle); 143 | return true; 144 | } 145 | } 146 | 147 | internal class SafeNativeHandle : SafeHandleZeroOrMinusOneIsInvalid 148 | { 149 | public SafeNativeHandle() : base(true) { } 150 | public SafeNativeHandle(IntPtr handle) : base(true) { this.handle = handle; } 151 | 152 | protected override bool ReleaseHandle() 153 | { 154 | return NativeMethods.CloseHandle(handle); 155 | } 156 | } 157 | 158 | internal enum SECURITY_IMPERSONATION_LEVEL 159 | { 160 | SecurityAnonymous = 0, 161 | SecurityIdentification = 1, 162 | SecurityImpersonation = 2, 163 | SecurityDelegation = 3, 164 | } 165 | 166 | internal enum SW 167 | { 168 | SW_HIDE = 0, 169 | SW_SHOWNORMAL = 1, 170 | SW_NORMAL = 1, 171 | SW_SHOWMINIMIZED = 2, 172 | SW_SHOWMAXIMIZED = 3, 173 | SW_MAXIMIZE = 3, 174 | SW_SHOWNOACTIVATE = 4, 175 | SW_SHOW = 5, 176 | SW_MINIMIZE = 6, 177 | SW_SHOWMINNOACTIVE = 7, 178 | SW_SHOWNA = 8, 179 | SW_RESTORE = 9, 180 | SW_SHOWDEFAULT = 10, 181 | SW_MAX = 10 182 | } 183 | 184 | internal enum TokenElevationType 185 | { 186 | TokenElevationTypeDefault = 1, 187 | TokenElevationTypeFull, 188 | TokenElevationTypeLimited, 189 | } 190 | 191 | internal enum TOKEN_TYPE 192 | { 193 | TokenPrimary = 1, 194 | TokenImpersonation = 2 195 | } 196 | 197 | internal enum WTS_CONNECTSTATE_CLASS 198 | { 199 | WTSActive, 200 | WTSConnected, 201 | WTSConnectQuery, 202 | WTSShadow, 203 | WTSDisconnected, 204 | WTSIdle, 205 | WTSListen, 206 | WTSReset, 207 | WTSDown, 208 | WTSInit 209 | } 210 | 211 | public class Win32Exception : System.ComponentModel.Win32Exception 212 | { 213 | private string _msg; 214 | 215 | public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { } 216 | public Win32Exception(int errorCode, string message) : base(errorCode) 217 | { 218 | _msg = String.Format("{0} ({1}, Win32ErrorCode {2} - 0x{2:X8})", message, base.Message, errorCode); 219 | } 220 | 221 | public override string Message { get { return _msg; } } 222 | public static explicit operator Win32Exception(string message) { return new Win32Exception(message); } 223 | } 224 | 225 | public static class ProcessExtensions 226 | { 227 | #region Win32 Constants 228 | 229 | private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400; 230 | private const int CREATE_NO_WINDOW = 0x08000000; 231 | 232 | private const int CREATE_NEW_CONSOLE = 0x00000010; 233 | 234 | private const uint INVALID_SESSION_ID = 0xFFFFFFFF; 235 | private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; 236 | 237 | #endregion 238 | 239 | // Gets the user token from the currently active session 240 | private static SafeNativeHandle GetSessionUserToken() 241 | { 242 | var activeSessionId = INVALID_SESSION_ID; 243 | var pSessionInfo = IntPtr.Zero; 244 | var sessionCount = 0; 245 | 246 | // Get a handle to the user access token for the current active session. 247 | if (NativeMethods.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref sessionCount)) 248 | { 249 | try 250 | { 251 | var arrayElementSize = Marshal.SizeOf(typeof(NativeHelpers.WTS_SESSION_INFO)); 252 | var current = pSessionInfo; 253 | 254 | for (var i = 0; i < sessionCount; i++) 255 | { 256 | var si = (NativeHelpers.WTS_SESSION_INFO)Marshal.PtrToStructure( 257 | current, typeof(NativeHelpers.WTS_SESSION_INFO)); 258 | current = IntPtr.Add(current, arrayElementSize); 259 | 260 | if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive) 261 | { 262 | activeSessionId = si.SessionID; 263 | break; 264 | } 265 | } 266 | } 267 | finally 268 | { 269 | NativeMethods.WTSFreeMemory(pSessionInfo); 270 | } 271 | } 272 | 273 | // If enumerating did not work, fall back to the old method 274 | if (activeSessionId == INVALID_SESSION_ID) 275 | { 276 | activeSessionId = NativeMethods.WTSGetActiveConsoleSessionId(); 277 | } 278 | 279 | SafeNativeHandle hImpersonationToken; 280 | if (!NativeMethods.WTSQueryUserToken(activeSessionId, out hImpersonationToken)) 281 | { 282 | throw new Win32Exception("WTSQueryUserToken failed to get access token."); 283 | } 284 | 285 | using (hImpersonationToken) 286 | { 287 | // First see if the token is the full token or not. If it is a limited token we need to get the 288 | // linked (full/elevated token) and use that for the CreateProcess task. If it is already the full or 289 | // default token then we already have the best token possible. 290 | TokenElevationType elevationType = GetTokenElevationType(hImpersonationToken); 291 | 292 | if (elevationType == TokenElevationType.TokenElevationTypeLimited) 293 | { 294 | using (var linkedToken = GetTokenLinkedToken(hImpersonationToken)) 295 | return DuplicateTokenAsPrimary(linkedToken); 296 | } 297 | else 298 | { 299 | return DuplicateTokenAsPrimary(hImpersonationToken); 300 | } 301 | } 302 | } 303 | 304 | public static int StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true,int wait = -1) 305 | { 306 | using (var hUserToken = GetSessionUserToken()) 307 | { 308 | var startInfo = new NativeHelpers.STARTUPINFO(); 309 | startInfo.cb = Marshal.SizeOf(startInfo); 310 | 311 | uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW); 312 | startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE); 313 | //startInfo.lpDesktop = "winsta0\\default"; 314 | 315 | IntPtr pEnv = IntPtr.Zero; 316 | if (!NativeMethods.CreateEnvironmentBlock(ref pEnv, hUserToken, false)) 317 | { 318 | throw new Win32Exception("CreateEnvironmentBlock failed."); 319 | } 320 | try 321 | { 322 | StringBuilder commandLine = new StringBuilder(cmdLine); 323 | var procInfo = new NativeHelpers.PROCESS_INFORMATION(); 324 | 325 | if (!NativeMethods.CreateProcessAsUserW(hUserToken, 326 | appPath, // Application Name 327 | commandLine, // Command Line 328 | IntPtr.Zero, 329 | IntPtr.Zero, 330 | false, 331 | dwCreationFlags, 332 | pEnv, 333 | workDir, // Working directory 334 | ref startInfo, 335 | out procInfo)) 336 | { 337 | throw new Win32Exception("CreateProcessAsUser failed."); 338 | } 339 | 340 | try 341 | { 342 | NativeMethods.WaitForSingleObject( procInfo.hProcess, wait); 343 | return procInfo.dwProcessId; 344 | } 345 | finally 346 | { 347 | NativeMethods.CloseHandle(procInfo.hThread); 348 | NativeMethods.CloseHandle(procInfo.hProcess); 349 | } 350 | } 351 | finally 352 | { 353 | NativeMethods.DestroyEnvironmentBlock(pEnv); 354 | } 355 | } 356 | } 357 | 358 | private static SafeNativeHandle DuplicateTokenAsPrimary(SafeHandle hToken) 359 | { 360 | SafeNativeHandle pDupToken; 361 | if (!NativeMethods.DuplicateTokenEx(hToken, 0, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 362 | TOKEN_TYPE.TokenPrimary, out pDupToken)) 363 | { 364 | throw new Win32Exception("DuplicateTokenEx failed."); 365 | } 366 | 367 | return pDupToken; 368 | } 369 | 370 | private static TokenElevationType GetTokenElevationType(SafeHandle hToken) 371 | { 372 | using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, 18)) 373 | { 374 | return (TokenElevationType)Marshal.ReadInt32(tokenInfo.DangerousGetHandle()); 375 | } 376 | } 377 | 378 | private static SafeNativeHandle GetTokenLinkedToken(SafeHandle hToken) 379 | { 380 | using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, 19)) 381 | { 382 | return new SafeNativeHandle(Marshal.ReadIntPtr(tokenInfo.DangerousGetHandle())); 383 | } 384 | } 385 | 386 | private static SafeMemoryBuffer GetTokenInformation(SafeHandle hToken, uint infoClass) 387 | { 388 | int returnLength; 389 | bool res = NativeMethods.GetTokenInformation(hToken, infoClass, new SafeMemoryBuffer(IntPtr.Zero), 0, 390 | out returnLength); 391 | int errCode = Marshal.GetLastWin32Error(); 392 | if (!res && errCode != 24 && errCode != 122) // ERROR_INSUFFICIENT_BUFFER, ERROR_BAD_LENGTH 393 | { 394 | throw new Win32Exception(errCode, String.Format("GetTokenInformation({0}) failed to get buffer length", infoClass)); 395 | } 396 | 397 | SafeMemoryBuffer tokenInfo = new SafeMemoryBuffer(returnLength); 398 | if (!NativeMethods.GetTokenInformation(hToken, infoClass, tokenInfo, returnLength, out returnLength)) 399 | throw new Win32Exception(String.Format("GetTokenInformation({0}) failed", infoClass)); 400 | 401 | return tokenInfo; 402 | } 403 | } 404 | } 405 | "@ 406 | $Public = @(Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue) 407 | foreach ($import in @($Public)) 408 | { 409 | try 410 | { 411 | . $import.FullName 412 | } 413 | catch 414 | { 415 | Write-Error -Message "Failed to import function $($import.FullName): $_" 416 | } 417 | } -------------------------------------------------------------------------------- /display_notif.ps1: -------------------------------------------------------------------------------- 1 | $Global:Current_Folder = split-path $MyInvocation.MyCommand.Path 2 | $Log_File = "c:\windows\debug\display_notif.log" 3 | 4 | $Notif_Config_XML = "$Current_Folder\Notif_Config.xml" 5 | $Get_Notif_Content = ([xml](get-content $Notif_Config_XML)).Toast_Notif 6 | $Notification_folder = $Get_Notif_Content.Notif_Folder 7 | 8 | Function Write_Log 9 | { 10 | param( 11 | $Message_Type, 12 | $Message 13 | ) 14 | 15 | $MyDate = "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date) 16 | Add-Content $Log_File "$MyDate - $Message_Type : $Message" 17 | write-host "$MyDate - $Message_Type : $Message" 18 | } 19 | 20 | If(!(test-path $Log_File)){new-item $Log_File -type file -force} 21 | If(!(test-path $Notification_folder)){new-item $Notification_folder -type Directory -force} 22 | 23 | Try 24 | { 25 | copy-item "$Current_Folder\*" $Notification_folder -recurse -force 26 | Write_Log -Message_Type "SUCCESS" -Message "Folder content $Current_Folder has been successfully copied" 27 | } 28 | Catch 29 | { 30 | Write_Log -Message_Type "ERROR" -Message "Folder content $Current_Folder has not been copied" 31 | } 32 | 33 | Try 34 | { 35 | import-module "$Notification_folder\RunasUser" 36 | Write_Log -Message_Type "SUCCESS" -Message "Importation du module RunasUser avec succès" 37 | $RunasUser_Module_imported = $True 38 | } 39 | Catch 40 | { 41 | Write_Log -Message_Type "ERROR" -Message "Erreur ^pendant l'importation du module RunasUser" 42 | $RunasUser_Module_imported = $False 43 | } 44 | 45 | 46 | If($RunasUser_Module_imported -eq $True) 47 | { 48 | $scriptblock = { 49 | powershell -ExecutionPolicy Bypass -NoProfile "C:\ProgramData\intune_notif\Notif_User.ps1" 50 | } 51 | 52 | Try 53 | { 54 | Invoke-AsCurrentUser -ScriptBlock $scriptblock | out-null 55 | Write_Log -Message_Type "SUCCESS" -Message "The script has been successfully executed in user context" 56 | } 57 | Catch 58 | { 59 | Write_Log -Message_Type "ERROR" -Message "An issue occured while executing the script in user context" 60 | } 61 | } -------------------------------------------------------------------------------- /logo_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/5c26f226a3eac2633bda0d59f8949644b9697cc4/logo_header.png -------------------------------------------------------------------------------- /preview_header.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damienvanrobaeys/PowerShell_Toast_Notif_Header_System/5c26f226a3eac2633bda0d59f8949644b9697cc4/preview_header.gif --------------------------------------------------------------------------------