--- title: "Disable and Enable the Clipboard on Windows Devices" slug: "disable-and-enable-the-clipboard-on-windows-devices" updated: 2025-10-08T04:53:35Z published: 2025-10-08T04:53:35Z canonical: "help.scalefusion.com/disable-and-enable-the-clipboard-on-windows-devices" --- > ## Documentation Index > Fetch the complete documentation index at: https://help.scalefusion.com/llms.txt > Use this file to discover all available pages before exploring further. # Disable and Enable the Clipboard on Windows Devices This document provides steps to disable and re-enable the clipboard on Windows 10 & 11 using PowerShell scripts. This is particularly useful in managed environments where clipboard usage needs to be restricted. ## A. Disable Clipboard To disable the clipboard, follow these steps: 1. Create a file on your desktop, e.g., ClipboardHandlerServiceEx.ps1. 2. Copy the script content into the text editor, such as Notepad++, or click [**here**](https://cdn.document360.io/175c0eac-012f-4410-bdc5-ac60794f82d8/Images/Documentation/Disable%20Clipboard.ps1) to download the file. ```powershell $code = @" using System; using System.ServiceProcess; using System.Diagnostics; using System.Timers; using System.Runtime.InteropServices; namespace ClipboardHandler {    class ClipboardHandlerService : ServiceBase    { static Timer timer = new Timer();        static int interval = 100; //100 msec        static string AppDataFolder = String.Empty;        static string LogFile = String.Empty;        static string exeName = String.Empty;        static string arguments = String.Empty;        static void Main()        {            ServiceBase.Run(new ServiceBase[] { new ClipboardHandlerService() });        }        protected override void OnStart(string[] args)        {            AppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);            LogFile = System.IO.Path.Combine(AppDataFolder, "ClipboardHandler.log");            //if(Environment.Is64BitOperatingSystem)            //    exeName = Environment.ExpandEnvironmentVariables(@"%windir%\SysWOW64\cmd.exe");            //else            //    exeName = Environment.ExpandEnvironmentVariables(@"%windir%\system32\cmd.exe");            exeName = "cmd.exe";            arguments = "/c \"echo off | clip\"";            timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);            timer.Interval = interval;            timer.Enabled = true;            timer.Start();        }        private static void OnElapsedTime(object source, ElapsedEventArgs e)        {            try            {                //System.IO.File.AppendAllText(LogFile, "execute command");                                StartProcessAsCurrentUser(exeName, arguments, null, false);            }            catch (Exception ex)            {                if(!ex.Message.Contains("GetSessionUserToken failed")) //ignore when user is not logged-in                    System.IO.File.AppendAllText(LogFile, ex.Message);            }        }        protected override void OnStop()        {            timer.Elapsed -= new ElapsedEventHandler(OnElapsedTime); timer.Stop();        } #region Win32 Constants        private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;        private const int CREATE_NO_WINDOW = 0x08000000;        private const int CREATE_NEW_CONSOLE = 0x00000010;        private const uint INVALID_SESSION_ID = 0xFFFFFFFF;        private static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;        #endregion        #region DllImports        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]        private static extern bool CreateProcessAsUser(            IntPtr hToken,            String lpApplicationName,            String lpCommandLine,            IntPtr lpProcessAttributes,            IntPtr lpThreadAttributes,            bool bInheritHandle,            uint dwCreationFlags,            IntPtr lpEnvironment,            String lpCurrentDirectory,            ref STARTUPINFO lpStartupInfo,            out PROCESS_INFORMATION lpProcessInformation);        [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]        private static extern bool DuplicateTokenEx(            IntPtr ExistingTokenHandle,            uint dwDesiredAccess,            IntPtr lpThreadAttributes,            int TokenType,            int ImpersonationLevel,            ref IntPtr DuplicateTokenHandle);        [DllImport("userenv.dll", SetLastError = true)]        private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, bool bInherit);        [DllImport("userenv.dll", SetLastError = true)]        [return: MarshalAs(UnmanagedType.Bool)]        private static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);        [DllImport("kernel32.dll", SetLastError = true)]        private static extern bool CloseHandle(IntPtr hSnapshot);        [DllImport("kernel32.dll")]        private static extern uint WTSGetActiveConsoleSessionId();        [DllImport("Wtsapi32.dll")]        private static extern uint WTSQueryUserToken(uint SessionId, ref IntPtr phToken);        [DllImport("wtsapi32.dll", SetLastError = true)]        private static extern int WTSEnumerateSessions(            IntPtr hServer,            int Reserved,            int Version,            ref IntPtr ppSessionInfo,            ref int pCount);        #endregion        #region Win32 Structs        private enum SW        {            SW_HIDE = 0,            SW_SHOWNORMAL = 1,            SW_NORMAL = 1,            SW_SHOWMINIMIZED = 2,            SW_SHOWMAXIMIZED = 3,            SW_MAXIMIZE = 3,            SW_SHOWNOACTIVATE = 4,            SW_SHOW = 5,            SW_MINIMIZE = 6,            SW_SHOWMINNOACTIVE = 7,            SW_SHOWNA = 8,            SW_RESTORE = 9,            SW_SHOWDEFAULT = 10,            SW_MAX = 10        }        private enum WTS_CONNECTSTATE_CLASS        {            WTSActive,            WTSConnected,            WTSConnectQuery,            WTSShadow,            WTSDisconnected,            WTSIdle,            WTSListen,            WTSReset,            WTSDown,            WTSInit        }        [StructLayout(LayoutKind.Sequential)]        private struct PROCESS_INFORMATION        {            public IntPtr hProcess;            public IntPtr hThread;            public uint dwProcessId;            public uint dwThreadId;        }        private enum SECURITY_IMPERSONATION_LEVEL        {            SecurityAnonymous = 0,            SecurityIdentification = 1,            SecurityImpersonation = 2,            SecurityDelegation = 3,        }        [StructLayout(LayoutKind.Sequential)]        private struct STARTUPINFO        {            public int cb;            public String lpReserved;            public String lpDesktop;            public String lpTitle;            public uint dwX;            public uint dwY;            public uint dwXSize;            public uint dwYSize;            public uint dwXCountChars;            public uint dwYCountChars;            public uint dwFillAttribute;            public uint dwFlags;            public short wShowWindow;            public short cbReserved2;            public IntPtr lpReserved2;            public IntPtr hStdInput;            public IntPtr hStdOutput;            public IntPtr hStdError;        }        private enum TOKEN_TYPE        {            TokenPrimary = 1,            TokenImpersonation = 2        }        [StructLayout(LayoutKind.Sequential)]        private struct WTS_SESSION_INFO        {            public readonly UInt32 SessionID;            [MarshalAs(UnmanagedType.LPStr)]            public readonly String pWinStationName;            public readonly WTS_CONNECTSTATE_CLASS State;        }        #endregion        // Gets the user token from the currently active session        private static bool GetSessionUserToken(ref IntPtr phUserToken)        {            var bResult = false;            var hImpersonationToken = IntPtr.Zero;            var activeSessionId = INVALID_SESSION_ID;            var pSessionInfo = IntPtr.Zero;            var sessionCount = 0;            // Get a handle to the user access token for the current active session.            if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref sessionCount) != 0)            {                var arrayElementSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));                var current = pSessionInfo;                for (var i = 0; i < sessionCount; i++)                {                    var si = (WTS_SESSION_INFO)Marshal.PtrToStructure((IntPtr)current, typeof(WTS_SESSION_INFO));                    current += arrayElementSize;                    if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive)                    {                        activeSessionId = si.SessionID;                    }                }            }            // If enumerating did not work, fall back to the old method            if (activeSessionId == INVALID_SESSION_ID)            {                activeSessionId = WTSGetActiveConsoleSessionId();            }            if (WTSQueryUserToken(activeSessionId, ref hImpersonationToken) != 0)            {                // Convert the impersonation token to a primary token                bResult = DuplicateTokenEx(hImpersonationToken, 0, IntPtr.Zero,                    (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary,                    ref phUserToken);                CloseHandle(hImpersonationToken);            }            return bResult;        }        public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)        {            var hUserToken = IntPtr.Zero;            var startInfo = new STARTUPINFO();            var procInfo = new PROCESS_INFORMATION();            var pEnv = IntPtr.Zero;            int iResultOfCreateProcessAsUser;            startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));            try            {                if (!GetSessionUserToken(ref hUserToken))                {                    throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");                }                uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);                startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);                startInfo.lpDesktop = "winsta0\\default";                if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))                {                    throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");                }                if (!CreateProcessAsUser(hUserToken,                    appPath, // Application Name                    cmdLine, // Command Line                    IntPtr.Zero,                    IntPtr.Zero,                    false,                    dwCreationFlags,                    pEnv,                    workDir, // Working directory                    ref startInfo,                    out procInfo))                {                    iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();                    throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -" + iResultOfCreateProcessAsUser);                }                iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();            }            finally            {                CloseHandle(hUserToken);                if (pEnv != IntPtr.Zero)                {                    DestroyEnvironmentBlock(pEnv);                }                CloseHandle(procInfo.hThread);                CloseHandle(procInfo.hProcess);            }            return true;        }    } } "@ $serviceName  = "ClipboardHandler" $servicePath  = Join-Path $env:ProgramData ("{0}.exe" -f $serviceName) $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue $serviceexists = $false if($service) { $serviceexists = $true if(($service.Status -eq "Running") -or ($service.Status -eq "StartPending")) { Stop-Service -Name $serviceName } } Add-Type $code -ReferencedAssemblies 'System', 'System.Runtime.InteropServices', 'System.ServiceProcess' -OutputAssembly $servicePath -OutputType WindowsApplication | Out-Null if($serviceexists -eq $false) { New-Service -Name $serviceName -BinaryPathName $servicePath -DisplayName $serviceName -Description $serviceName -StartupType Automatic | out-null $newservice = Get-Service $serviceName $newservice | Start-Service } else { Start-Service -Name $serviceName } ``` 3. Follow [**our guide**](/docs/deploy-powershell-scripts-using-scalefusion) to upload & publish the PowerShell script using the Scalefusion Dashboard. 4. Once the script is successfully executed, you will be able to view the status in the **View Status** report on the Scalefusion dashboard. > [!NOTE] > Note: > > Disabling the clipboard via this script modifies registry and service settings. ## B. Enable Clipboard 1. Once the clipboard is disabled, it can only be re-enabled using a separate script, as disabling it makes changes to the registry and system services. 2. Create a file on your desktop, e.g., Enable_Clipboard.ps1. 3. Copy the script content into the text editor, such as Notepad++, or click [**here**](https://cdn.document360.io/175c0eac-012f-4410-bdc5-ac60794f82d8/Images/Documentation/Enable%20Clipboard.ps1) to download the file. ```powershell $serviceName  = "ClipboardHandler" $servicePath  = Join-Path $env:ProgramData ("{0}.exe" -f $serviceName) # Check if the service exists $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue if($service) {    # Stop service if running    if(($service.Status -eq "Running") -or ($service.Status -eq "StartPending"))    {        Stop-Service -Name $serviceName -Force    }    # Remove the service    sc.exe delete $serviceName | Out-Null    Write-Output "Service $serviceName removed." } else {    Write-Output "Service $serviceName not found." } # Delete the executable if it exists if(Test-Path $servicePath) {    Remove-Item $servicePath -Force    Write-Output "Executable $servicePath deleted." } else {    Write-Output "Executable $servicePath not found." } ``` 4. Follow [**our guide**](/docs/deploy-powershell-scripts-using-scalefusion) to upload & publish the PowerShell script using the Scalefusion Dashboard. 5. Once the script is successfully executed, you will be able to view the status in the **View Status** report on the Scalefusion dashboard. > [!CAUTION] > Note: > > Please note that to use the PowerShell scripts, the Scalefusion MDM Agent Application must be installed on the device(s). Please follow [**our guide**](/docs/scalefusion-mdm-agent-application) to publish and install the Scalefusion MDM Agent Application. > [!CAUTION] > Note: > > 1. The scripts and their contents are sourced from various albeit authenticated Microsoft sources and forums. > 2. Please validate the scripts on a test machine before deploying them on all your managed devices. > 3. Scalefusion has tested these scripts, however, Scalefusion will not be responsible for any loss of data or system malfunction that may arise due to the incorrect usage of these scripts.