├── EVD安装包_V0.1 ├── .nomedia └── EVDsetup.exe ├── README.md ├── main.cpp ├── 一键关闭虚拟屏 ├── .nomedia └── STOP EasyVirtualDisplay.bat └── 后台启动脚本 ├── .nomedia └── START MIN EasyVirtualDisplay.bat /EVD安装包_V0.1/.nomedia: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /EVD安装包_V0.1/EVDsetup.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sprlightning/Easy-Virtual-Display-AutoRunBackground/b49fa35fe4ebc48cd55d7c926c0273cac55b4542/EVD安装包_V0.1/EVDsetup.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!NOTE] 2 | > This project is only a temporary solution and currently only provides minimal maintenance. Parsec-vdd will directly provide a more complete solution, please continue to pay attention. 3 | > 4 | > where find it? 👉👉👉https://github.com/nomi-san/parsec-vdd 5 | > 6 | >———————————————————本项目fork源于KtzeAbyss—————————————————— 7 | > 8 | > KtzeAbyss的项目我没权限上传,所以在此fork后打包发布。 9 | > 10 | > 在KtzeAbyss版本的基础上添加了适用于开机自启的后台静默运行脚本(受jiuyan660启发,找到了开启虚拟屏的源头程序)。 11 | > 12 | > 要求将脚本放在EVD安装目录(不可以安装在C盘),并且关闭UAC,开启白名单,创建计划选无论是否登录都要运行,不保存密码,勾选最高权限,触发器用任何用户登录时。 13 | > 14 | > 一键关闭脚本可一键关闭虚拟屏。 15 | > 16 | > 所有内容见release。 17 | > 18 | > ![屏幕截图 2024-04-15 030455](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/c3548ddb-9a17-498d-b0d8-680ca2139688) 19 | > 20 | > 21 | > PS.KtzeAbyss的项目地址👉👉👉https://github.com/KtzeAbyss/Easy-Virtual-Display 22 | > 23 | >———————————————————以下为历史内容—————————————————— 24 | > 25 | > 本项目仅作为一个临时解决方案,目前只提供最低限度的维护,Parsec-vdd将直接提供更完善的解决方案,请各位持续关注。 26 | > 27 | > 项目地址 👉👉👉https://github.com/nomi-san/parsec-vdd 28 | 29 | [English](#english) | [中文](#中文) 30 | 31 | 32 | 33 | # Easy Virtual Display 34 | 35 | Create virtual displays in Windows with ease, supporting a range of resolutions and refresh rates (such as 4K 240Hz). Ideal for remote control or graphics card spoofing. 36 | 37 | # Project Background 38 | 39 | This project builds upon the ParsecVDD foundation and utilizes the repository found at [https://github.com/nomi-san/parsec-vdd](https://github.com/nomi-san/parsec-vdd). 40 | 41 | # Download 42 | 43 | Please select the latest release version. 44 | 45 | ![屏幕截图 2024-04-15 025424](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/e51ed4e4-2ee2-46c0-a6ba-370cb910f747) 46 | 47 | 48 | 49 | # How to Use 50 | 51 | 1. Download and install the application. It is recommended to create a shortcut. 52 | 53 | 54 | 55 | ![屏幕截图 2024-04-15 025424](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/e51ed4e4-2ee2-46c0-a6ba-370cb910f747) 56 | 57 | 58 | ![image](https://github.com/KtzeAbyss/Easy-Virtual-Display/assets/46898226/4aff971b-b1ef-4aa4-a04d-43b09df850ea) 59 | 60 | 61 | 2. Double-click to launch (virtualDisplayLit.exe, please make sure to run in administrator mode). 62 | 3. The program will by default hide in the system tray at the bottom right corner, Right-click the icon to access the feature menu.On the initial run, install the driver (only required the first time). 63 | 4. Then, click 'Start Virtual Display' to access the display settings via right-click on the desktop, just like configuring a physical monitor. 64 | 65 | ![image](https://github.com/KtzeAbyss/Easy-Virtual-Display/assets/46898226/3471d425-ae62-48b4-be8a-7c0106fb06b1) 66 | 67 | ## Menu Items 68 | From top to bottom, the menu options are as follows: Start Virtual Display, Stop Virtual Display, Force Quit, Install Driver, Uninstall Driver, and Exit. 69 | 1. Start Virtual Display 70 | 2. Stop Virtual Display 71 | 3. Force Quit 72 | 4. Install Driver 73 | 5. Uninstall Driver 74 | 6. Exit 75 | 76 | # Demo 77 | 78 | ## Privacy Screen (Remote Control/Streaming) 79 | 80 | Privacy Screen (Remote Control/Streaming): After starting the virtual display, configure it to display only on Display 2 (Virtual Display) in the display settings. This will cause the host machine's screen to go black while the client machine displays the host's screen, allowing you to work discreetly without being detected by others. 81 | 82 | ## Overcoming Physical Display Limitations 83 | Unrestricted creation of virtual displays with various resolutions and refresh rates, allowing the client to output user-preferred resolutions and refresh rates (such as 4K 240Hz) on low-performance displays or systems without a physical display. 84 | 85 | 86 | 87 | # Easy Virtual Display(简易虚拟显示器) 88 | 89 | 轻松在Windows中创建虚拟显示器,支持各种分辨率和刷新率(如4k 244hz)。非常适用于远程控制或图形卡欺骗。 90 | 91 | # 项目背景 92 | 93 | 本项目基于ParsecVDD的基础构建,并利用了位于[https://github.com/nomi-san/parsec-vdd](https://github.com/nomi-san/parsec-vdd)的存储库。 94 | 95 | # 下载 96 | 97 | 请选择最新发布版本。 98 | 99 | 100 | ![屏幕截图 2024-04-15 025424](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/e51ed4e4-2ee2-46c0-a6ba-370cb910f747) 101 | 102 | 103 | # 使用方法(首次启动务必先安装驱动!!!首次启动务必先安装驱动!!!首次启动务必先安装驱动!!!) 104 | 105 | 1. 下载并安装应用程序。建议创建快捷方式。 106 | 107 | 108 | ![屏幕截图 2024-04-15 025424](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/e51ed4e4-2ee2-46c0-a6ba-370cb910f747) 109 | 110 | ![图片](https://github.com/KtzeAbyss/Easy-Virtual-Display/assets/46898226/4aff971b-b1ef-4aa4-a04d-43b09df850ea) 111 | 112 | 2. 双击启动(virtualDisplayLit.exe),请确保以管理员模式运行。 113 | 3. 该程序默认隐藏在右下角系统托盘中,右键单击图标即可访问功能菜单。首次运行时,请安装驱动程序(仅首次运行)。 114 | 4. 然后,单击“启动虚拟显示器”以通过在桌面上右键单击来访问显示设置,就像配置物理显示器一样。 115 | 116 | ![图片](https://github.com/KtzeAbyss/Easy-Virtual-Display/assets/46898226/3471d425-ae62-48b4-be8a-7c0106fb06b1) 117 | 118 | ## 菜单项 119 | 120 | 从上到下,菜单选项如下:启动虚拟显示器、停止虚拟显示器、强制退出、安装驱动、卸载驱动和退出。 121 | 1. 启动虚拟显示器:正常启动(首次运行前务必安装驱动) 122 | 2. 停止虚拟显示器:正常停止 123 | 3. 强制退出:某些情况下驱动可能会出现占用导致虚拟显示器启动不正常,此时可以先启用强制退出功能,确保驱动异常占用不是本程序导致的,然后卸载重装驱动或修复驱动 124 | 4. 安装驱动:首次启动务必先安装驱动!!!首次启动务必先安装驱动!!!首次启动务必先安装驱动!!! 125 | 5. 卸载驱动:卸载驱动 126 | 6. 退出:退出程序 127 | 128 | # 玩法演示 129 | 130 | ## 开机后台自启动 131 | 要求将脚本放在EVD安装目录(不可以安装在C盘),并且关闭UAC,开启白名单,创建计划选无论是否登录都要运行,不保存密码,勾选最高权限,触发器用任何用户登录时。 132 | 133 | 134 | ![屏幕截图 2024-04-15 025358](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/ff87c1b8-6579-414c-862e-624fb8b81c1e) 135 | 136 | 137 | ![屏幕截图 2024-04-15 030046](https://github.com/sprlightning/Easy-Virtual-Display/assets/96748320/5744cbbc-132b-4c4f-b33b-72331f20afcb) 138 | 139 | 140 | ## 隐私屏(远程控制/串流) 141 | 142 | 启动虚拟显示器后,在显示设置中设置仅在显示器2(虚拟显示器)上显示,此时被控端(host)将黑屏,控制端(client)将正常显示被控端(host)的画面,允许你成为卷王而不被其他人发现。 143 | 144 | ## 摆脱物理显示器限制 145 | 146 | 无限制的创建各种分辨率和各种刷新率的虚拟显示器,允许被控端在低性能显示器或无显示器搭载的情况下,控制端输出用户喜好的分辨率和刷新率(如4K 240Hz)。 147 | 148 | # Star History 149 | 150 | [![Star History Chart](https://api.star-history.com/svg?repos=KtzeAbyss/Easy-Virtual-Display&type=Date)](https://star-history.com/#KtzeAbyss/Easy-Virtual-Display&Date) 151 | 152 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #pragma comment(lib, "Setupapi.lib") 11 | 12 | BOOLEAN GetDevicePath2( 13 | _In_ LPCGUID InterfaceGuid, 14 | _Out_writes_(BufLen) PTCHAR DevicePath, 15 | _In_ size_t BufLen 16 | ) 17 | { 18 | HANDLE hDevice = INVALID_HANDLE_VALUE; 19 | PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL; 20 | ULONG predictedLength = 0; 21 | ULONG requiredLength = 0; 22 | HDEVINFO hardwareDeviceInfo; 23 | SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 }; 24 | BOOLEAN status = FALSE; 25 | HRESULT hr; 26 | 27 | hardwareDeviceInfo = SetupDiGetClassDevs( 28 | InterfaceGuid, 29 | NULL, // Define no enumerator (global) 30 | NULL, // Define no 31 | (DIGCF_PRESENT | // Only Devices present 32 | DIGCF_DEVICEINTERFACE)); // Function class devices. 33 | if (INVALID_HANDLE_VALUE == hardwareDeviceInfo) 34 | { 35 | printf("Idd device: SetupDiGetClassDevs failed, last error 0x%x\n", GetLastError()); 36 | return FALSE; 37 | } 38 | 39 | deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 40 | 41 | 42 | if (!SetupDiEnumDeviceInterfaces(hardwareDeviceInfo, 43 | 0, // No care about specific PDOs 44 | InterfaceGuid, 45 | 0, // 46 | &deviceInterfaceData)) 47 | { 48 | printf("Idd device: SetupDiEnumDeviceInterfaces failed, last error 0x%x\n", GetLastError()); 49 | goto Clean0; 50 | } 51 | 52 | // 53 | // Allocate a function class device data structure to receive the 54 | // information about this particular device. 55 | // 56 | SetupDiGetDeviceInterfaceDetail( 57 | hardwareDeviceInfo, 58 | &deviceInterfaceData, 59 | NULL, // probing so no output buffer yet 60 | 0, // probing so output buffer length of zero 61 | &requiredLength, 62 | NULL);//not interested in the specific dev-node 63 | 64 | if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) 65 | { 66 | printf("Idd device: SetupDiGetDeviceInterfaceDetail failed, last error 0x%x\n", GetLastError()); 67 | goto Clean0; 68 | } 69 | 70 | predictedLength = requiredLength; 71 | deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc( 72 | GetProcessHeap(), 73 | HEAP_ZERO_MEMORY, 74 | predictedLength 75 | ); 76 | 77 | if (deviceInterfaceDetailData) 78 | { 79 | deviceInterfaceDetailData->cbSize = 80 | sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 81 | } 82 | else 83 | { 84 | printf("Idd device: HeapAlloc failed, last error 0x%x\n", GetLastError()); 85 | goto Clean0; 86 | } 87 | 88 | if (!SetupDiGetDeviceInterfaceDetail( 89 | hardwareDeviceInfo, 90 | &deviceInterfaceData, 91 | deviceInterfaceDetailData, 92 | predictedLength, 93 | &requiredLength, 94 | NULL)) 95 | { 96 | printf("Idd device: SetupDiGetDeviceInterfaceDetail failed, last error 0x%x\n", GetLastError()); 97 | goto Clean1; 98 | } 99 | 100 | hr = StringCchCopy(DevicePath, BufLen, deviceInterfaceDetailData->DevicePath); 101 | if (FAILED(hr)) 102 | { 103 | printf("Error: StringCchCopy failed with HRESULT 0x%x", hr); 104 | status = FALSE; 105 | goto Clean1; 106 | } 107 | else 108 | { 109 | status = TRUE; 110 | } 111 | 112 | Clean1: 113 | (VOID)HeapFree(GetProcessHeap(), 0, deviceInterfaceDetailData); 114 | Clean0: 115 | (VOID)SetupDiDestroyDeviceInfoList(hardwareDeviceInfo); 116 | return status; 117 | } 118 | 119 | HANDLE DeviceOpenHandle(const GUID& devGuid) 120 | { 121 | // const int maxDevPathLen = 256; 122 | TCHAR devicePath[256] = { 0 }; 123 | HANDLE hDevice = INVALID_HANDLE_VALUE; 124 | do 125 | { 126 | if (FALSE == GetDevicePath2( 127 | &devGuid, 128 | devicePath, 129 | sizeof(devicePath) / sizeof(devicePath[0]))) 130 | { 131 | break; 132 | } 133 | if (_tcslen(devicePath) == 0) 134 | { 135 | printf("GetDevicePath got empty device path\n"); 136 | break; 137 | } 138 | 139 | _tprintf(_T("Idd device: try open %s\n"), devicePath); 140 | hDevice = CreateFile( 141 | devicePath, 142 | GENERIC_READ | GENERIC_WRITE, 143 | // FILE_SHARE_READ | FILE_SHARE_WRITE, 144 | 0, 145 | NULL, // no SECURITY_ATTRIBUTES structure 146 | OPEN_EXISTING, // No special create flags 147 | 0, // No special attributes 148 | NULL 149 | ); 150 | if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL) 151 | { 152 | DWORD error = GetLastError(); 153 | printf("CreateFile failed 0x%lx\n", error); 154 | } 155 | } while (0); 156 | 157 | return hDevice; 158 | } 159 | 160 | enum VddCtlCode 161 | { 162 | IOCTL_VDD_CONNECT = 0x22A008, 163 | IOCTL_VDD_ADD = 0x22E004, 164 | IOCTL_VDD_UPDATE = 0x22A00C, 165 | }; 166 | 167 | void VddIoCtl(HANDLE vdd, VddCtlCode code) 168 | { 169 | BYTE InBuffer[32]{}; 170 | int OutBuffer = 0; 171 | OVERLAPPED Overlapped{}; 172 | DWORD NumberOfBytesTransferred; 173 | 174 | Overlapped.hEvent = CreateEventW(NULL, NULL, NULL, NULL); 175 | DeviceIoControl(vdd, code, InBuffer, _countof(InBuffer), &OutBuffer, sizeof(OutBuffer), NULL, &Overlapped); 176 | GetOverlappedResult(vdd, &Overlapped, &NumberOfBytesTransferred, TRUE); 177 | 178 | if (Overlapped.hEvent && Overlapped.hEvent != INVALID_HANDLE_VALUE) 179 | CloseHandle(Overlapped.hEvent); 180 | } 181 | 182 | bool quit = false; 183 | 184 | void pipe_thread() 185 | { 186 | HANDLE hPipe; 187 | char buffer[1024] = { 0 }; 188 | DWORD dwRead; 189 | 190 | hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\MyPipe"), 191 | PIPE_ACCESS_DUPLEX, 192 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 193 | 1, 194 | 1024 * 16, 195 | 1024 * 16, 196 | NMPWAIT_USE_DEFAULT_WAIT, 197 | NULL); 198 | 199 | if (hPipe != INVALID_HANDLE_VALUE) 200 | { 201 | if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe 202 | { 203 | while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE) 204 | { 205 | buffer[dwRead] = '\0'; 206 | 207 | if (std::string(buffer) == "quit") 208 | { 209 | quit = true; 210 | break; 211 | } 212 | } 213 | } 214 | 215 | DisconnectNamedPipe(hPipe); 216 | } 217 | 218 | CloseHandle(hPipe); 219 | } 220 | 221 | int main() 222 | { 223 | const GUID PARSEC_VDD_DEVINTERFACE = \ 224 | { 0x00b41627, 0x04c4, 0x429e, { 0xa2, 0x6e, 0x02, 0x65, 0xcf, 0x50, 0xc8, 0xfa } }; 225 | 226 | // try to get device handle with GUID 227 | HANDLE vdd = DeviceOpenHandle(PARSEC_VDD_DEVINTERFACE); 228 | if (!vdd || vdd == INVALID_HANDLE_VALUE) 229 | { 230 | printf("failed to get ParsecVDD device handle.\n"); 231 | return 1; 232 | } 233 | 234 | // connect & plug in 235 | VddIoCtl(vdd, IOCTL_VDD_CONNECT); 236 | VddIoCtl(vdd, IOCTL_VDD_UPDATE); 237 | VddIoCtl(vdd, IOCTL_VDD_ADD); 238 | VddIoCtl(vdd, IOCTL_VDD_UPDATE); 239 | 240 | std::thread pipe_thread_instance(pipe_thread); 241 | 242 | while (true) 243 | { 244 | // update each 100ms 245 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 246 | VddIoCtl(vdd, IOCTL_VDD_UPDATE); 247 | 248 | if (quit) { 249 | break; 250 | } 251 | } 252 | 253 | pipe_thread_instance.join(); 254 | 255 | // disconnect 256 | VddIoCtl(vdd, IOCTL_VDD_CONNECT); 257 | CloseHandle(vdd); 258 | 259 | return 0; 260 | } -------------------------------------------------------------------------------- /一键关闭虚拟屏/.nomedia: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /一键关闭虚拟屏/STOP EasyVirtualDisplay.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem 关闭echo命令显示 3 | 4 | chcp 65001 5 | rem 强制开启UTF-8,以支持中文显示 6 | 7 | rem 为本脚本获取管理员权限 8 | ver | findstr "10\.[0-9]\.[0-9]*" >nul && goto powershellAdmin 9 | 10 | :mshtaAdmin 11 | rem 原理是利用mshta运行vbscript脚本给bat文件提权 12 | rem 这里使用了前后带引号的%~dpnx0来表示当前脚本,比原版的短文件名%~s0更可靠 13 | rem 这里使用了两次Net session,第二次是检测是否提权成功,如果提权失败则跳转到failed标签 14 | rem 这有效避免了提权失败之后bat文件继续执行的问题 15 | Net session >nul 2>&1 || mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c ""%~dpnx0""","","runas",1)(window.close)&&exit 16 | Net session >nul 2>&1 || goto failed 17 | goto Admin 18 | 19 | :powershellAdmin 20 | rem 原理是利用powershell给bat文件提权 21 | rem 这里使用了两次Net session,第二次是检测是否提权成功,如果提权失败则跳转到failed标签 22 | rem 这有效避免了提权失败之后bat文件继续执行的问题 23 | Net session >nul 2>&1 || powershell start-process \"%0\" -verb runas && exit 24 | Net session >nul 2>&1 || goto failed 25 | goto Admin 26 | 27 | :failed 28 | echo 提权失败,可能是杀毒软件拦截了提权操作,或者您没有同意UAC提权申请。 29 | echo 建议您右键点击此脚本,选择“以管理员身份运行”。 30 | echo 按任意键退出。 31 | pause >nul 32 | exit 33 | 34 | :Admin 35 | echo 本脚本处理所在路径:%0 36 | echo 已获取管理员权限! 37 | ping 127.0.0.1 -n 1 > nul 38 | echo 如果此窗口标题处显示“管理员”字样,那就说明提权成功了。 39 | 40 | echo 尝试将工作目录转移到软件目录... 41 | cd /d %~dp0 42 | rem 切换软件工作目录到软件所在文件夹 43 | ping 127.0.0.1 -n 1 > nul 44 | echo 目录转移成功! 45 | 46 | echo Designed by HPL at 2024年4月15日02点36分 47 | echo: 48 | 49 | set TITLE=STOP_EasyVirtualDisplay 50 | set executable=VirtualDisplayProject.exe 51 | 52 | title %TITLE% 53 | 54 | tasklist|findstr /i "%executable%" 55 | if errorlevel 1 ( 56 | echo [%DATE%%TIME:~0,8%]未发现正在运行的%executable%! 57 | ping 127.0.0.1 -n 1 > nul 58 | msg %username% /time:6 "虚拟屏%executable%未开启" 59 | goto end 60 | ) 61 | if errorlevel 0 ( 62 | echo [%DATE%%TIME:~0,8%]已找到%executable%,将在1s后关闭%executable%! 63 | echo -------------------------------------------------------------------------------- 64 | ping 127.0.0.1 -n 1 > nul 65 | goto stop 66 | ) 67 | 68 | :stop 69 | taskkill /f /im %executable% 70 | 71 | msg %username% /time:6 "虚拟屏%executable%已关闭" 72 | 73 | :end 74 | exit -------------------------------------------------------------------------------- /后台启动脚本/.nomedia: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /后台启动脚本/START MIN EasyVirtualDisplay.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem 关闭echo命令显示 3 | 4 | chcp 65001 5 | rem 强制开启UTF-8,以支持中文显示 6 | 7 | rem 为本脚本获取管理员权限 8 | ver | findstr "10\.[0-9]\.[0-9]*" >nul && goto powershellAdmin 9 | 10 | :mshtaAdmin 11 | rem 原理是利用mshta运行vbscript脚本给bat文件提权 12 | rem 这里使用了前后带引号的%~dpnx0来表示当前脚本,比原版的短文件名%~s0更可靠 13 | rem 这里使用了两次Net session,第二次是检测是否提权成功,如果提权失败则跳转到failed标签 14 | rem 这有效避免了提权失败之后bat文件继续执行的问题 15 | Net session >nul 2>&1 || mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c ""%~dpnx0""","","runas",1)(window.close)&&exit 16 | Net session >nul 2>&1 || goto failed 17 | goto Admin 18 | 19 | :powershellAdmin 20 | rem 原理是利用powershell给bat文件提权 21 | rem 这里使用了两次Net session,第二次是检测是否提权成功,如果提权失败则跳转到failed标签 22 | rem 这有效避免了提权失败之后bat文件继续执行的问题 23 | Net session >nul 2>&1 || powershell start-process \"%0\" -verb runas && exit 24 | Net session >nul 2>&1 || goto failed 25 | goto Admin 26 | 27 | :failed 28 | echo 提权失败,可能是杀毒软件拦截了提权操作,或者您没有同意UAC提权申请。 29 | echo 建议您右键点击此脚本,选择“以管理员身份运行”。 30 | echo 按任意键退出。 31 | pause >nul 32 | exit 33 | 34 | :Admin 35 | echo 本脚本处理所在路径:%0 36 | echo 已获取管理员权限! 37 | ping 127.0.0.1 -n 1 > nul 38 | echo 如果此窗口标题处显示“管理员”字样,那就说明提权成功了。 39 | 40 | echo 尝试将工作目录转移到软件目录... 41 | cd /d %~dp0 42 | rem 切换软件工作目录到软件所在文件夹 43 | ping 127.0.0.1 -n 1 > nul 44 | echo 目录转移成功! 45 | 46 | echo Designed by HPL at 2024年4月15日02点36分 47 | echo: 48 | 49 | set TITLE=START_MIN_EasyVirtualDisplay 50 | set executable=VirtualDisplayProject.exe 51 | 52 | title %TITLE% 53 | 54 | powershell -command "& {Start-Process %executable% -WindowStyle Hidden}" 55 | 56 | ping 127.0.0.1 -n 1 > nul 57 | 58 | echo [%DATE%%TIME:~0,8%]%executable% is running! 59 | echo: 60 | echo [%DATE%%TIME:~0,8%]%executable% is running! >> %TITLE%.log 61 | echo: >> %TITLE%.log 62 | 63 | ping 127.0.0.1 -n 1 > nul 64 | 65 | msg %username% /time:6 "已开启虚拟屏%executable%!" 66 | 67 | exit --------------------------------------------------------------------------------