public:it:windows

Windows

  • ping 侦测保活同时记录:powershell 执行
    ping -t 192.168.1.1 | Foreach{"{0} - {1}" -f (Get-Date),$_} > D://work/ping-log.txt
  • 查看 dns 缓存: ipconfig /displaydns, 清空 dns 缓存:ipconfig /flushdns
  • 查看端口占用 netstat -ano, 在 powershell 里可以用 netstat -ano | select-string LISTENING 来筛选只查看端口监听绑定
  • 防火墙设置命令行: cmd netsh advfirewall firewall, powershell New-NetfirewallRule 等
  • windows 防火墙规则的优先级是采用最小化策略,即一般 deny 比 allow 优先
  • CreateProcessWithToken等创建不同凭据进程函数如果出现 1058 错误,可能是系统服务 Secondary Logon 被禁用导致。
  • 如果「高级系统设置/系统属性」-「高级」-「性能设置」-「视觉效果」-「平滑屏幕字体边缘」被取消,会让使用 GdiPlus 描绘的文本不显示
  • 查看文件的哈希值
    certutil -hashfile <file-path-name> MD5
    certutil -hashfile <file-path-name> SHA1
    certutil -hashfile <file-path-name> SHA256
  • 证书管理:当前用户 certmgr.msc, 本地计算机 certlm.msc
  • 命令行测试目标 NTP 服务可用性:w32tm /stripchart /computer:<target_ip>
  • 直接打开网络适配器:win+r运行 ncpa.cpl
    • 在桌面设置快捷方式:右键桌面新建快捷方式,填入ncpa.cpl, 设置名称保存。
  • 直接打开设备管理器:win+r运行 devmgmt.msc
  • 多桌面设置,任务栏「任务视图」点开可以设置类似 mac 的多桌面,或者可以使用快捷键 CTRL + WIN + D 创建桌面,CTRL + win + ←/→切换桌面
  • 删除时提示「另一个程序正在使用此文件,进程无法访问。」时,可以打开「资源监视器」(可从任务管理器的性能页面左下角打开),在CPU页卡下「关联的句柄」那搜索,找到对应的进程来决定是否结束。
  • 显示器为DP/HDMI接口连接时,休眠唤醒或重启显示器后所有窗口跑到了左上角, 可修改注册表解决此问题\
  • 取消任务栏某些图标重启后固定显示:编辑 C:\Users\<your-user-name\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml, 找到 CustomTaskbarLayoutCollection, 删除 <taskbar:TaskbarPinList> 里的相关项目,再在任务栏右键对应图标取消固定,下次重启就不会再回来。
  • 这个指南不错:https://ss64.com/nt/syntax.html
  • 查看指令的路径的命令:where <cmd>
    • 在powershell里where是另外的object指令,要写全exe: where.exe <cmd>
  • Win10 Build 17063 之后,可以使用 tarcurl 指令了 LOL m(
  • 各种命令说明:Command-Line Reference
  • 确保管理员权限的写法
    BatchGotAdmin.bat
    @echo off
    :: BatchGotAdmin  
    :-------------------------------------  
    REM  --> Check for permissions  
    >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"  
     
    REM --> If error flag set, we do not have admin.  
    if '%errorlevel%' NEQ '0' (  
        echo Requesting administrative privileges...  
        goto UACPrompt  
    ) else ( goto gotAdmin )  
     
    :UACPrompt  
        echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"  
        echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"  
     
        "%temp%\getadmin.vbs"  
        exit /B  
     
    :gotAdmin  
        if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )  
        pushd "%CD%"  
        CD /D "%~dp0"  
    :--------------------------------------
     
    echo 1 start openvpn
    echo 2 stop openvpn
    set /p T= please select:
    if %T%==1 goto 1
    if %T%==2 goto 2
    :1 
        sc start OpenVPNservice
    :2
        sc stop OpenVPNservice
  • 批量条件拷贝,使用 robocopy 命令, 用法. 例如, 拷贝 c:\FolderA 中新于2016年1月11日的文件到 c:\Backup :
     robocopy c:\FolderA  c:\Backup /s /maxage:20160111 

    或者使用 xcopy

  • 批量删除空文件夹:(以下代码放入 del.bat)
    del.bat
    DIR "%CD%" /AD /B /S | SORT /R /O list.txt
    IF EXIST deleted.txt ATTRIB -S -H -A -R deleted.txt & DEL /F /Q deleted.txt
    FOR /F "delims=|" %%i IN ( list.txt ) DO RD "%%i\" & IF NOT EXIST "%%i\" ECHO %%i\>>deleted.txt
    IF EXIST deleted.txt NOTEPAD.EXE deleted.txt
    DEL /S /Q list.txt
  • 批量枚举文件进行操作的指令forfiles,例如批量删除修改时间早于某日期的文件:
    forfiles /s /m *.* /d -2017/01/01 /c "cmd /c del /s /f /q @path"
  • 命令行操作防火墙, win10 可以用 powershell Set-NetFirewallProfile, New-NetFirewallRule等; win10 之前可用 netsh advfirewall,例如关掉所有(域、专用、公用)防火墙
    netsh advfirewall set allprofiles state off

    设置策略:

    netsh advfirewall set allprofiles firewallpolicy blockinbound,allowoutbound

    更多可在powershell 打命令查看

    netsh advfirewall -?
  • 进入脚本文件本身所在目录:
    : enter the folder of this file
    cd %~dp0
  • cmd 设置别名使用 doskey /?, 例如 doskey ls=dir $*
  • cmd 设置初始自动运行脚本:AutoRun
    reg add "HKCU\Software\Microsoft\Command Processor" /v AutoRun ^
      /t REG_EXPAND_SZ /d "%"USERPROFILE"%\init.cmd" /f
  • 如果 bat 脚本里有中文并且编码为UTF8,需设置代码页确保在cmd里可执行:
    @echo off
    chcp 65001 
  • 程序崩溃生成 crash dump 文件相关函数: SetUnhandledExceptionFilterMiniDumpWriteDump
    LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
    {
        HANDLE lhDumpFile = CreateFile(_T("DumpFile.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL);
     
        MINIDUMP_EXCEPTION_INFORMATION loExceptionInfo;
        loExceptionInfo.ExceptionPointers = ExceptionInfo;
        loExceptionInfo.ThreadId = ::GetCurrentThreadId();
        loExceptionInfo.ClientPointers = TRUE;
     
        ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), lhDumpFile, MiniDumpNormal, &loExceptionInfo, NULL, NULL);
     
        ::CloseHandle(lhDumpFile);
     
        return EXCEPTION_EXECUTE_HANDLER;
    }
    int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
    {
        ::SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
        ...
    }

    得添加头文件<Dbghelp.h>,链接 Dbghelp.lib

  • 设置进程工作集大小: SetProcessWorkingSetSize , 参数同时设置为-1,可清理多余PAGE, 给用户个好看的任务管理器内存显示,相当于 EmptyWorkingSet
  • MoveFileEx 可以设置为重启电脑后才移动/删除,关键字MOVEFILE_DELAY_UNTIL_REBOOT
  • 获取系统各文件夹路径: SHGetFolderPath
  • RegisterWaitForSingleObject,vista之后则是 CreateThreadpoolxxx 系列函数,现成的线程池来等待事件,不需要自己开线程了。
  • 获取进程结束时的返回值: GetExitCodeProcess
  • CreateProcessAsUser如果访问不了注册表HKCU,要考虑调用LoadUserProfile,详见MSDN
  • 关于stations和desktops,详见MSDN:About Window Stations and Desktops
  • CoInitalzieSecurity给进程设置安全权限,一个进程只能设置一次,多次设置会返回RPC_E_TOO_LATE错误,值为0x80010119
  • ATL::CSecurityDesc ATL提供了这类函数来方便权限设定
  • ShellExecuteEx如果用户为管理员,可以把参数 lpVerb 设置为 “runas” 来绕过 UAC,具体步骤是用 runas 启动一个自身新实例,再把自身进程退出。
  • 想让服务和桌面交互?看这里MSDN:Interactive Services.
    • winlogon.exe进程是后台服务进程,但属于登录用户会话,所以可以获取其访问令牌,然后通过 CreateProcessAsUser 将进程启动到活动登录用户当前活动会话,就可进行界面交互。
  • SetProcessShutdownParameters想让程序退出慢时不让弹出重试窗口?关键词 SHUTDOWN_NORETRY 详见MSDN
  • WTSGetActiveConsoleSessionId 只能获取本地用户活动ID,不能获取远程登录ID,要配合用 WTSEnumerateSessions 来判断state值来获取当前活动用户 session id。
    • 后台服务获取当前用户会话ID可以通过 SERVICE_CONTROL_SESSIONCHANGE 来获取。
  • theme and visual styles手动绘制原生主题风格控件相关
  • 映射网络驱动器: WNetAddConnection2
  • 共享文件夹: NetShareAdd
  • 创建帐户: NetUserAdd,NetLocalGroupAddMembers
  • Internationalization GetSystemDefaultLangID 获取系统语言; xp设置程序界面语言:SetThreadLocale;vista以上设置程序界面语言:SetThreadUILanguage
  • IE控件加载模块资源的协议格式: res protocol. 如果IE控件加载的html文件想加载同模块的图片资源, 可以直接在HTML文件里这样写 <img src=“%23203” /> , 其中%23是 # 符号. 203是图片资源ID. 注意图片资源必须在RC文件的HTML分类下!
  • IE控件去掉滚动条,网上说在 body 元素里添加 style=“overflow: hidden” 是不符合 w3c 标准的,在加载声明 Doctype w3c 标准的页面时, 顶级 html 元素就是<html>. 所以, 直接在 html 标签里修改 overflow 就可以正确屏蔽滚动条.
  • 嵌套子进程窗口直接用 ::SetParent 就可。
  • 修改文件夹权限:参考博文
    • GetNamedSecurityInfo 获取DACL
    • SetEntriesInAcl, SetNamedSecurityInfo
    • 获取当前登录用户名: 从 explorer.exe 获取 token OpenProcessToken, GetTokenInformation, LookupAccountSid
  • listview 控件行高居然不能直接设置,只能用图片高度或文字字体高度设置
  • 虽然msdn显示托盘图标的气泡提示在XP就能用,但是如果你编译时的 _WIN32_WINNT 高于等于 0x0600, 且用的 win7 编译,那么你程序在XP运行时一切正常包括各种返回值都正确,但就是不出托盘气泡——奇葩——所以还是老老实实把那些个宏定到你想支持的最低系统版本吧,不然真不知道会出什么不能追踪的问题——虽然好像程序运行起来没问题。
  • windows 服务要接收设备或关机等通知的话,需要用到 HandlerEx,但是 VS2010 默认的 ATL 服务项目的代码用的是 Handler, 需要自己手动 copy atlbase.h 的相关代码并修改
  • FILETIME 需转为 LARGE_INTEGER 进行处理再转为 FILETIME, 需要注意的是 FILETIME的单位是100*nanosecond, 即10,000,000分之一秒
  • 通知栏只是任务栏窗口的一部分, Shell_Notifyicon 添加的图标会因为启动时任务栏窗口还未创建, explorer.exe 过于繁忙, 或者直接在任务管理器结束explorer.exe 而丢失. 为了避免这种情况, 需要 RegisterWindowMessage(_T(“TaskbarCreated”), 详见 MSDN:Shell_Notifyicon 底下评论部分, 以及Taskbar created notification.
  • win32工程的资源界面, 在对话框资源右键菜单中, 选项Insert Activex Control是灰的, 要让其可用, 可以删掉 resource.h 里的宏 _APS_NO_MFC!!
  • 对话框嵌入 IE 控件, 初始化 com 环境应该用 STA 模式, 不能用 MTA 模式.
  • 对话框的 IE 控件如果要有效加载本程序模块资源, 比如图片, 需要手动编辑 rc 文件把图片加到 HTML 下, 例如IDB_IMG HTML “res\\myimg.bmp”
  • WNetCleanConnection2 并不能清理干净连接, 只要系统内残留有该共享文件路径的 File 句柄, 下一次 WNetAddConnection2 如果使用另一个账户登录, 就会失败! 可用 procexp.exe 来清理残留句柄, 或者使用命令行工具 Handle.exe —-仍然有问题, 强行结束句柄(或程序)会造成其它异常问题. 目前还没找到直接的办法.
  • ATL server 服务, 用 VS2013 的工具链 v120_xp 编译的服务, 在 XP 系统下注销服务时( /unregserver ),会抛出无权限错误异常, 直接原因是 com 服务 release 之前 com 环境就已经结束. 把用到的 com 指针由智能指针改为普通指针, 自己手动在 PostThreadMessage 函数里 release , 可解决.
  • 关于 MAX_PATH限制:maximum-file-path-limitation
  • ::IsWindows10OrGreater 在 win10 仍然返回false, 因为相关接口已经被win10弃用; 如果要准确判断win10,可以用非常规方法 RtlGetVersion, 参考get-correct-system-version-on-windows-10
  • Zeal : 技术文档本地离线浏览,类似 Mac 下的 Dash
  • DebugView: 接收非VS调试环境下程序中的OutputDebugString, 以及内核的DbgPrint, 方便调试,使用
  • Chocolatey : windows 的软件管理器
  • winget: 微软自己弄的软件管理器
  • scoop: 命令行包管理工具,相比 Chocolatey, 它的安装文件都处于 ~\scoop 下。
  • hashmyfiles: 计算文件hash的小工具,支持右键菜单设置。
  • Detours Hook 库
    • 工作集:进程当前使用的物理内存量,包括专用与共享;
    • 专用工作集: 进程当前使用而其它进程无法使用的物理内存量;
    • 提交大小(commit size):操作系统为该进程保留的虚拟内存大小;用这个值来判断是否内存泄漏。
  • xshell默认会把制表符显示成宽字符, 需要在会话属性-终端里, 取消“韩中日语言中的不确定字符处理为宽字符”.

◊◊ 关于内存泄漏

◊◊ C/C++ Runtime Library

  • MD, MT的选择
    • 为什么选择/MD,不选/MT?
      1. 程序就不需要静态链接运行时库,可以减小软件的大小;
      2. 所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题;
      3. 用户机器可能缺少我们编译时使用的动态运行时库。(补充:如果我们软件有多个DLL,采用/MT体积增加太多,则可以考虑/MD + 自带系统运行时库)
    • 为什么选择/MT,不选择/MD?
      1. 有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。
      2. 减少模块对外界的依赖。
    • 多个模块,必须选择相同的运行时库。
    • 选择/MT需要解决的堆空间释放问题, 不同的模块各自有一份C运行时库代码、或者根本没有C运行时库,导致了各个模块会有各自的堆。如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。
    • 选择/MD需要注意多个模块使用不同版本运行时库的问题

◊◊ Command prompt

  • From VS2013 Menu Select “Tools”, then Select “External Tools”. Enter as below:
    1. Title: “VS2013 Native Tools-Command Prompt” would be good
    2. Command: C:\Windows\System32\cmd.exe
    3. Arguments: /k “C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat”
    4. Initial Directory: Select as suits your needs.
    5. Click OK. Now you have command prompt access under the Tools Menu.

◊◊ VS2019的代码文件编码字符集

  • 调出「高级保存设置」菜单项:「工具」菜单-「自定义」对话框-「命令」选项卡-「文件」菜单栏-「添加命令」-「类别」-「文件」-「命令」-选取「高级保存设置」,添加。
  • 注意:VS2019在中文系统上,有BOM的代码文件就算是utf-8编码,也会在编译时把非宽字符的中文字符串默认以GBK编码进行编译;只有在无bom的utf-8代码文件上才保留原utf-8编码(也许是认不出来所以保持原样)
  • 造成上面那条的原因是:MSVC是区分源文件字符集与编译时字符集的,并且可设置。参考 官方文档Tokens and character sets, 可用编译参数 /source-charset /execution-charset/utf-8 来指定。

◊◊ Tips

  • 让VC编译出来的程序不显示CMD黑色窗口:参考此文章
    //在代码里加入
    #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
    //或直接在工程属性里设置.
     
  • 有时候在某些机子上的 JIT DEBUGGER 没反应(崩溃后弹出窗口选择调试,没有调起后续窗口), 可以这样解决:MSDN: Troubleshoot Just-In-Time debugging
  • VC DEBUG工程默认定义的宏是 _DEBUG MSDN
  • 查看导出符号:在VS的 Tools 菜单打开Visual Studio command prompt, 执行命令 dumpbin /exports <target.dll|target.lib>
  • 关于关机: 组策略 gpedit.msc,本地组策略编辑器-计算机配置-管理模板-系统-关机选项
  • 锁屏不出现任务管理器选项: 在 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System添加字符串值,名为DisableTaskMgr, 值为 1;
  • 禁用Ctrl-Alt-del:
    • 组策略 gpedit.msc-用户配置-管理模板-系统-“Ctrl-Alt-Del”, 选择生效所有禁用选项;
    • 组策略 gpedit.msc-计算机配置-管理模板-系统-登录, 选择生效禁用快速用户切换;
  • public/it/windows.txt
  • 最后更改: 2024/04/17 10:20
  • oakfire