VNC源码研究(十)XP、Win7实现模拟发送ATL+CTRL+DEL

2023-10-27

 

转载请标明是引用于 http://blog.csdn.net/chenyujing1234 

欢迎大家拍砖

 

1、vnc-4.0-winsrc  版本中实现模拟发送ATL+CTRL+DEL

在工程wrfb_win32m中找到模拟发送ATL+CTR_DEL 的代码

 

在Service.h中有

  // -=- Routines used by the SInput Keyboard class to emulate Ctrl-Alt-Del
    //     Returns false under Win9x
    bool emulateCtrlAltDel();


它的实现是:

bool
rfb::win32::emulateCtrlAltDel() {
  if (!osVersion.isPlatformNT)
    return false;

  CADThread* cad_thread = new CADThread();
  vlog.debug("emulate Ctrl-Alt-Del");
  if (cad_thread) {
    cad_thread->start();
    cad_thread->join();
    bool result = cad_thread->result;
    delete cad_thread;
    return result;
  }
  return false;
}

(1)首先判断是不是NT家族的操作系统

OSVersionInfo继续于系统的结构体OSVERSIONINFO(这样的设计是为了考虑到后面要调用系统API:GetVersionEx)

namespace rfb {

  namespace win32 {

    extern struct OSVersionInfo : OSVERSIONINFO {
      OSVersionInfo();

      // Is the OS one of the NT family (NT 3.51, NT4.0, 2K, XP, etc.)?
      bool isPlatformNT;
      // Is one of the Windows family?
      bool isPlatformWindows;

      // Is this OS one of those that blue-screens when grabbing another desktop (NT4 pre SP3)?
      bool cannotSwitchDesktop;

    } osVersion;

  };

};

它的系统信息在OSVersionInfo构造函数时获得:

OSVersionInfo::OSVersionInfo() {
  // Get OS Version Info
  ZeroMemory(static_cast<OSVERSIONINFO*>(this), sizeof(this));
  dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if (!GetVersionEx(this))
    throw rdr::SystemException("unable to get system version info", GetLastError());

  // Set the special extra flags
  isPlatformNT = dwPlatformId == VER_PLATFORM_WIN32_NT;
  isPlatformWindows = dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;

  cannotSwitchDesktop = isPlatformNT && (dwMajorVersion==4) &&
    ((_tcscmp(szCSDVersion, _T("")) == 0) ||
     (_tcscmp(szCSDVersion, _T("Service Pack 1")) == 0) ||
     (_tcscmp(szCSDVersion, _T("Service Pack 2")) == 0));

}

(2)创建CADThread对象

CADThread* cad_thread = new CADThread();

CADThread类继续自Thread
Thread的设计是值得我们学习的。

class Thread {
  public:
    Thread(const char* name_=0);
    virtual ~Thread();

    virtual void run();

    virtual void start();
    virtual Thread* join();

    const char* getName() const;
    ThreadState getState() const;

    // Determines whether the thread should delete itself when run() returns
    // If you set this, you must NEVER call join()!
    void setDeleteAfterRun() {deleteAfterRun = true;};

    unsigned long getThreadId() const;

    static Thread* self();

    friend class Condition;

  protected:
    Thread(HANDLE thread_, DWORD thread_id_);
    static DWORD WINAPI threadProc(LPVOID lpParameter);

    HANDLE thread;
    DWORD thread_id;
    char* name;
    ThreadState state;
    Condition* sig;
    Mutex mutex;

    HANDLE cond_event;
	  Thread* cond_next;

    bool deleteAfterRun;
  };


CADThread重载了Thread类的run函数,CADThread的run函数先保存原有的桌面,然后切换到Winlogon桌面,然后发送ATL_CTRL_DEL,

最后把桌面还原。

class CADThread : public Thread {
public:
  CADThread() : Thread("CtrlAltDel Emulator"), result(false) {}
  virtual void run() {
	  HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());

    if (switchToDesktop(OpenDesktop(_T("Winlogon"), 0, FALSE, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
		  DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
		  DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
      DESKTOP_SWITCHDESKTOP | GENERIC_WRITE))) {
	    PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
      switchToDesktop(old_desktop);
      result = true;
    }
  }
  bool result;
};


 

(3)使用(2)得到的对象调用功能

cad_thread->start();
    cad_thread->join();


分别调用了start函数与join函数。有人可能会问,(2)定义的run接口怎么没调用到,其实是有的。

因为在Thread类的构造时就启动了此线程:

Thread::Thread(const char* name_) : sig(0), deleteAfterRun(false) {
  sig = new Condition(mutex);
  cond_event = CreateEvent(NULL, TRUE, FALSE, NULL);
  if (!name_)
    name_ = "Unnamed";
  name = strDup(name_);
  thread = CreateThread(NULL, 0, threadProc, this, CREATE_SUSPENDED, &thread_id);
  state = ThreadCreated;
  logAction(this, "created");
}


 

Thread::threadProc中就会调用到它:


 

2、tightvnc  客户端版本中实现模拟发送ATL+CTRL+DEL

在我的文章《XP、Wn7模拟发送ctrl+alt+delete组合键》中讲到在win7中实现模拟ATL+CTRL+DEL的方法,虽然我已经改在了会话1中发送窗口消息,可是还是没达到效果。

网友建议我去查看VNC代码,由于tightvnc代码是支持Win7 的,于是希望在这里找到解决方法。

在win-system工程中有Environment.h文件定义有类:

#ifndef _ENVIRONMENT_H_
#define _ENVIRONMENT_H_

#include "util/StringStorage.h"

#include <winnt.h>

class Environment
{
public:
  static const int APPLICATION_DATA_SPECIAL_FOLDER = 0x0; 
  static const int COMMON_APPLICATION_DATA_SPECIAL_FOLDER = 0x1;
public:
  Environment();
  ~Environment();

  static void getErrStr(StringStorage *out);

  static void getErrStr(const TCHAR *specification, StringStorage *out);

  static bool getSpecialFolderPath(int specialFolderId, StringStorage *out);

  static bool getCurrentModulePath(StringStorage *out);

  static bool getCurrentModuleFolderPath(StringStorage *out);

  static bool getCurrentUserName(StringStorage *out);

  static bool getComputerName(StringStorage *out);

  static void restoreWallpaper();
  static void disableWallpaper();

  static bool isWinNTFamily();
  static bool isWinXP();
  static bool isWin2003Server();
  static bool isVistaOrLater();

  static void simulateCtrlAltDel();

private:
  static void init();
  static OSVERSIONINFO m_osVerInfo;
};

#endif


其中有 static void simulateCtrlAltDel();接口

void Environment::simulateCtrlAltDel()
{
  if (isWinNTFamily()) {
    CtrlAltDelSimulator cadSim;
    cadSim.wait();
  }
}


vnc-4.0-winsrc  版本的CADThread类继承于Thread类类似,这里的CtrlAltDelSimulator类也继续Thread。

同样在thread类的构造时就启动了此线程:

Thread::Thread()
: m_terminated(false), m_active(false), m_hDesk(0)
{
  m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc,
                           (LPVOID) this, CREATE_SUSPENDED, (LPDWORD) &m_threadID);
  m_hDesk = DesktopSelector::getInputDesktop();
}


线程里会去调用execute方法:

DWORD WINAPI Thread::threadProc(LPVOID pThread)
{
  Thread *_this = ((Thread *)pThread);
  try {
    DesktopSelector::setDesktopToCurrentThread(_this->m_hDesk);
    DesktopSelector::closeDesktop(_this->m_hDesk);
    _this->m_hDesk = 0;
    _this->execute();
  } catch (Exception &e) {
    Log::error(_T("Abnormal thread termination.")
               _T(" ThreadId = %x, message = \"%s\" \n"),
               _this->m_threadID, e.getMessage());
  }
  _this->m_active = false;
  return 0;
}

CtrlAltDelSimulator类重载了execute方法:

void CtrlAltDelSimulator::execute()
{
  if (DesktopSelector::selectDesktop(&StringStorage(_T("Winlogon")))) {
    HWND hwndCtrlAltDel = FindWindow(_T("SAS window class"), _T("SAS window"));
    if (hwndCtrlAltDel == NULL) {
      hwndCtrlAltDel = HWND_BROADCAST;
    }
    PostMessage(hwndCtrlAltDel, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
  }
}

 

往窗口发送消息是与VNC4.0版本是类似的,这里只讲selectDesktop的不同。

 

bool DesktopSelector::selectDesktop(const StringStorage *name)
{
  HDESK desktop;
  if (name) {
    desktop = getDesktop(name);
  } else {
    desktop = getInputDesktop();
  }

  bool result = setDesktopToCurrentThread(desktop) != 0;
  closeDesktop(desktop);

  return result;
}


 

HDESK DesktopSelector::getDesktop(const StringStorage *name)
{
  return OpenDesktop(name->getString(), 0, TRUE,
                     DESKTOP_CREATEMENU |
                     DESKTOP_CREATEWINDOW |
                     DESKTOP_ENUMERATE |
                     DESKTOP_HOOKCONTROL |
                     DESKTOP_WRITEOBJECTS |
                     DESKTOP_READOBJECTS |
                     DESKTOP_SWITCHDESKTOP |
                     GENERIC_WRITE);
}


 

bool DesktopSelector::setDesktopToCurrentThread(HDESK newDesktop)
{
  return SetThreadDesktop(newDesktop) != 0;
}


3、VNC服务端发送模拟CTRL+ATL+DEL的方法

3、1 在Vista版本前

 参考我的文章《XP、Wn7模拟发送ctrl+alt+delete组合键

 

3、2 在Vista版本后

同样是在Environment.h里的class Environment类中有:

  static bool isWinNTFamily();
  static bool isWinXP();
  static bool isWin2003Server();
  static bool isVistaOrLater();

  static void simulateCtrlAltDel();

  static void simulateCtrlAltDelUnderVista();

win7下的函数就是:simulateCtrlAltDelUnderVista

void Environment::simulateCtrlAltDelUnderVista()
{
  Log::info(_T("Requested Ctrl+Alt+Del simulation under Vista or later"));

  try {
    DynamicLibrary sasLib(_T("sas.dll"));
    SendSas sendSas = (SendSas)sasLib.getProcAddress("SendSAS");
    if (sendSas == 0) {
      throw Exception(_T("The SendSAS function has not been found"));
    }
    sendSas(FALSE); 
  } catch (Exception &e) {
    Log::error(_T("The simulateCtrlAltDelUnderVista() function failed: %s"),
               e.getMessage());
  }
}


实现思路:

(1)从system32文件夹下的sas.dll里得到SendSAS接口,

(2)然后调用此接口sendSas(FALSE);

使用注意事项:

(1)

SendSAS function

Simulates a secure attention sequence (SAS).

VOID WINAPI SendSAS(
  _In_  BOOL AsUser
);


 

Parameters

AsUser [in]

TRUE if the caller is running as the current user; otherwise,FALSE.

Remarks

为了调用SendSAS成功,应用必然以服务方式运行或有uiAccess属性(用requestedExceptionLevel函数设置为true)。

如果不是以服务方式运行,那么得把User Account Control打开。

Important  Applications with the uiAccess attribute set to "true" must be signed by usingAuthenticode. In addition, the application must reside in a protected location in the file system. Currently, there are two allowable protected locations:

\Program Files\
\windows\system32\

本地的安全策略必须配置为允许服务和应用程序模拟SAS。

为了配置策略,修改组策略编辑器(GPE)中的设置。

控制 委托的GPE是在下面的位置:

Computer Configuration | Administrative Templates | Windows Components | Windows Logon Options | Disable or enable software Secure Attention Sequence

A service can impersonate the token of another process that calls that service. In this case, a call to theSendSAS function by that service simulates a SAS on the session associated with the impersonated token.

以上策略对应的注册表是:

reg add

 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v

SoftwareSASGeneration /t REG_DWORD /d 1 /f

即增加以下注册表:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"SoftwareSASGeneration"=dword:00000003


 

 

(2)我把它放在Win7类型于GINA的凭证COM里(且是以起一线程的方式调用),发现没有效果。

这是因为SendSAS只能在服务中才起作用,而在凭据中是不能起作用的。

(3) 

 

 那么simulateCtrlAltDelUnderVista在哪里被调用呢?

void SasUserInput::setKeyboardEvent(UINT32 keySym, bool down)
{
  bool delPressed = false;

  if (m_underVista) {
    switch (keySym) {
    case XK_Alt_L:
    case XK_Alt_R:
      m_altPressed = down;
      break;
    case XK_Control_L:
    case XK_Control_R:
      m_ctrlPressed = down;
      break;
    case XK_Delete:
      delPressed = down;
    }
  }

  if (m_ctrlPressed && m_altPressed && delPressed && m_underVista) {
    Environment::simulateCtrlAltDelUnderVista();
  } else {
    m_client->setKeyboardEvent(keySym, down);
  }
}


我们再来看setKeyboardEvent在哪里被调用了:

(1)

void UserInputServer::applyKeyEvent(BlockingGate *backGate)
{
  UINT32 keySym;
  bool down;
  readKeyEvent(&keySym, &down, backGate);
  m_userInput->setKeyboardEvent(keySym, down);
}

applyKeyEvent调用readKeyEvent读出键值和按下或弹上的标志,然后再调用setKeyboardEvent。

applyKeyEvent的实现过程:

void DesktopServerProto::readKeyEvent(UINT32 *keySym, bool *down,
                                      BlockingGate *gate)
{
  *keySym = gate->readUInt32();
  *down = gate->readUInt8() != 0;
}



 

(2)

void RfbClient::onKeyboardEvent(UINT32 keySym, bool down)
{
  m_desktop->setKeyboardEvent(keySym, down);
}


 

(3)

void WinDesktop::setKeyboardEvent(UINT32 keySym, bool down)
{
  Log::info(_T("set keyboard event (keySym = %u, down = %d)"), keySym, (int)down);
  try {
    if (isRemoteInputAllowed()) {
      m_userInput->setKeyboardEvent(keySym, down);
    }
  } catch (Exception &e) {
    Log::error(_T("setKeyboardEvent() crashed: %s"), e.getMessage());
    m_extDeskTermListener->onAbnormalDesktopTerminate();
  }
}


 

(4)

 

 

 



 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VNC源码研究(十)XP、Win7实现模拟发送ATL+CTRL+DEL 的相关文章

  • VNC源码研究(十)XP、Win7实现模拟发送ATL+CTRL+DEL

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家拍砖 1 vnc 4 0 winsrc 版本中实现模拟发送ATL CTRL DEL 在工程wrfb win32m中找到模拟发送ATL CTR D
  • Windows 7 下 vs2010内存泄漏检测工具VLD的使用

    1 环境和软件 Windows7 32位系统 Visual Studio 2012 旗舰版 vld 2 2 3 setup exe 大小1 04M 2 步骤 1 下载安装 下载好 vld 2 2 3 setup exe 大小1 04M 并安
  • MySQL5.6.11安装步骤(Windows7 64位)

    原文地址 http www cnblogs com happyty p 4131686 html 1 下载MySQL Community Server 5 6 21 注意选择系统类型 32位 64位 2 解压MySQL压缩包 将以下载的My
  • windows7下安装pytorch 0.4.0 GPU版本

    1 PyTorch的官方Windows支持 2018年4月25日 PyTorch 官方发布 0 4 0 版本 该版本的PyTorch 有多项重大更新 其中最重要的改进是支持 Windows系统 Windows用户能直接通过conda pip
  • Google Chrome在Windows7安装离线版

    前言 今天因为旧版chrome老是要报更新 所以安装了个新版 因为被墙原因 许多网友会遇到一些安装chrome的问题 所以今天分享一下安装教程 安装chrome 1 前往chrome官网 可以看到链接地址是http www google c
  • Win7复制文件时出现:“您需要权限来执行操作!”(终极解决方法!)

    最近 装了win7需要倒数据 但总是出现 您需要权限来执行操作 提示 而使复制终断 很挠头 后来 发现 原来是 杀毒软件 惹的祸 做程序的朋友请注意 程序复制程序时关闭杀毒软件的2个理由 1 真不知道现在的 杀毒软件 怎么做的 一点水平也没
  • citrix协议ICA技术原理

    转载自 http www zrss com cn article 110 1 html Citrix交付中心解决方案的核心是虚拟化技术 虚拟化计算的核心是ICA协议 ICA协议连接了运行在平台上的应用客户端运行环境和远端终端设备 通过ICA
  • 记一次pptp实践经历

    由于公司业务需求 需要搭建vpn服务器以供外部用户传送数据 所以需要采用客户端到网关的方式的VPN VPN服务器的类型很多 如IPSec L2TP PPTP SSLVPN OPENVPN等 考虑到安全稳定性的因素 专业的vpn设备肯定是首要
  • 电脑可以聊微信但是无法上网页的解决方法

    电脑可以聊微信但是无法上网页 ping不通百度的IP地址 一般是电脑的DNS出现错误 解决方案如下 打开360安全卫士 点击功能大全中的断网急救箱 进行扫描 之后进行修复 问题即可解决
  • 利用kali hydra 暴力破解Windows7(hydra的基本用法)会继续更新

    Hydra的简单介绍 Hydra对应的英文意思是九头蛇 它是一款爆破神器 可以对多种服务的账号和密码进行爆破 包括Web登录 数据库 SSH FTP等服务 支持Linux Windows Mac平台安装 其中Kali Linux中自带Hyd
  • Windows1.0到Windows10三十年进化史,你还记得自己最初使用的系统吗?

    从1985年Windows 1 0正式诞生到2015年Windows 10诞生 微软花了三十年的时间 从像素化桌面到现在扁平化的界面 让我们来看一下Windows 1 0到Windows10三十年来的变化 1 1985年11月20日 微软发
  • 十分钟利用windows7漏洞破解开机密码

    所有win7系统都使用 首先连按五下Shift键弹出粘滞键提醒 然后我们点击否后关机 启动系统时将其强制关机 虚拟机利用电源关闭虚拟机 自用主机就在开机时长按关机键强制关闭系统 随后启动系统 我们选择启动启动修复 推荐 选择取消即不还原 等
  • electron在window7上安装白屏问题

    问题描述 electron5 0 13以上的版本打包win7上需要 NET Framework 4 6 版本及以上版本才可以运行 但是有些win7由于是SP1的系统属于精简版window所以无法安装 NET Framework 4 6及其以
  • window 7 平台上 MXNET 源码编译

    目的 本文主要描述怎么在windows上编译mxnet源码 得到可用的libmxnet dll和libmxnet lib文件 版本 mxnet x64 release CPU版 运行环境 windows 7 64bit visual stu
  • rdp协议解读

    转自 http blog csdn net jiangtao killer article details 6940346 一 前言 RDP 远程显示协议 Remote Display Protocol 简称RDP 提供了客户和服务器之间的
  • Windows桌面文件夹删除被提示“找不到该项目”——顽固目录、文件的删除

    注意 若转载 请贴上链接 https blog csdn net qq 41042595 article details 112576438 如若发现抄袭或未标明来源现象 都可举报反馈 文章目录 问题来源场景 原因分析 解决方案 步骤一 1
  • 在服务中启动带有界面的程序

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家拍砖 参考文章 http blog csdn net goingup article details 2932752 reply 在服务中启动带
  • 揭开智能卡的面纱

    一 概述 ICC是Integrated Circuit Card的缩写 意思是集成电路卡 我们通常把它称为智能卡 Smart Card 智能卡应用广泛 它可以用来保存私人密码 银行账号 个人资料等 那么如何编写应用程序 从智能卡上读出或向其
  • 如何查看和修改Windows远程桌面端口

    Windows远程桌面的默认端口为3389 基于安全性考虑 部分用户有修改默认端口的需要 以减少通过远程桌面恶意攻击和扫描主机的次数 因此今天带大家一起学习下 如何查看和修改Windows远程桌面的默认端口 一 查看Windows远程桌面端
  • VS 2008配置Winpcap环境

    写在前面的话 这篇博客主要是写给小白看的 因为自己也是一个小白 之前从没有接触过网络嗅探器这些东西 如果说基础的话就是学习过计算机网络 对于计算机网络有一点点了解 再就是对于编程语言基础语法还算熟悉吧 这学期选修了网络攻击与防范这门课程 老

随机推荐

  • visio图标_弱电间机柜原型图整理,可编辑!(Excel,visio,CAD)

    有朋友问到机柜原型图 这个我们在弱电vip技术群里面也有朋友提到过 今天我们就整理了弱电系统中常用的机柜原型图 有Excel visio CAD版本 可以修改编辑 1 Excel机柜原型图 可编辑 机柜布局 1 机柜布局 2 机柜布局 3
  • C++全局对象初始化依赖关系处理

    class A private int m nSize public A m nSize 100 m pList new char 4 memset m pList 0 sizeof 4 sizeof char int GetSize re
  • 使用基础粒子群(PSO)算法求解一元及二元方程的Python代码

    最近在看清风的数学建模视频 其中有两道题 求一元函数的最值问题 题目 求函数 y 11 s i n x
  • 小谈Intel SGX

    目录 Intel SGX简介 背景 为什么要Intel SGX Intel SGX尚处于学术讨论 Intel SGX和可信启动什么关系 开发者眼中SGX长什么样子 SGX访问控制是什么 MEE与SGX EPC内存加密 CPU里面SGX长什么
  • 深度学习笔记(一):环境(yolov5)配置

    前言 本文为笔者在学习深度学习 进行环境配置时集各家所长总结的一些经验 旨在能够较快的配置好深度学习所需的环境 一 软件安装 1 1 Anaconda安装 直接在官网下载 Anaconda官网链接 安装包下载完毕后 进行安装 更改安装路径
  • CSS属性纪要

    1 line height 行高 跟font size属性的大小有关 一般可用来设置元素垂直居中 1 单行文字或单张图片的垂直居中 div 你好你好 div 以以上代码为例 设置box和height和line height高度一样就可以垂直
  • 原子锁

    Windows核心编程 Interlocked原子访问系列函数 http blog csdn net zhongguoren666 article details 7542975 InterlockedExchange http blog
  • 时间序列的数据分析(一):主要成分

    时间序列是一组按照时间发生先后顺序进行排列 并且包含一些信息的数据点序列 在时间序列数据中通常包含了数据的发展趋势 向上 向下 保持 和数据的变化规律 季节性 等特征 而这些特征往往具有一定的规律性和可预测性 具体来说时间序列数据具有如下几
  • BES2300 代码主架构笔记

    1 BES的内核用的是RTX的内核 并且用了ARM推广的CMSIS RTOS API接口 这样做的好处是可以方便内核的更换 方便移植上层代码 2 程序是从RTX CM LIB H里面的 main init 开始的 里面包括了内核的初始化 堆
  • 【更新指南】BarTender正式迎来2019 R2重大版本更新!

    BarTender 在 150 多个国家 地区拥有成千上百的用户 在标签 条形码 证卡和 RFID 标记的设计和打印领域是全球首屈一指的软件 BarTender 既可以单独运行 也可以与任何其他程序集成 几乎是所有按需打印或打标应用的完美解
  • 国泰安下载数据太大?stata传不进来?

    除了换电脑还有啥方法 其实就是一个小的tip 善用国泰安的条件筛选功能 只愿大家可以从下面的小例子中获取点扩展思维 例如最常用的财务报表数据 国泰安默认的是季度数据 但大多数时候我们需要的只是年度数据 那么我们就可以在条件筛选处加一个 不要
  • 【Android】点击应用进而打开base.apk的调用流程再分析

    点击一个应用的时候 会加载其对应的base apk 我们在AssetManager类的addAssetPath方法中添加堆栈打印 其调用堆栈为 android content res AssetManager addAssetPath As
  • 性能测试 —— Jmeter 常用重要函数汇总

    1 counter 计数器 加1的功能 疑问 假如加2 使用计数器 计数器超过最大值后重新开始计数 重点 最大值 如果运行结果超过最大值时 又会从起始值开始循环每个 用户独立计数器 多线程时 每个用户都是从起始值开始计数 跟线程号有关 th
  • Android 工程师需要了解的 Lint 知识入门篇

    前言 项目开发过程中 通过对代码规范的约束对于代码质量的提升是非常重要的 这其中除了人为的代码审查之外 我们还可以使用 lint 工具来定位并修改一些有问题的代码 帮助提高我们的代码规范程度 今天我们就一起来学学 lint 的使用 自动提示
  • filter过滤器

    1 Filter 什么是过滤器 1 Filter 过滤器它是 JavaWeb 的三大组件之一 三大组件分别是 Servlet 程序 Listener 监听器 Filter 过滤器 2 Filter 过滤器它是 JavaEE 的规范 也就是接
  • PCB布线中,重要的信号线进行包地处理

    原文地址 http zhenshanmcu blog 163 com blog static 16545766220137755225723 相关网帖 1 在PADS2007中 地包线怎么画 主要针对时钟信号 http zhidao bai
  • 自定义异常类

    public class MyException extends Exception public MyException String message super message
  • HTML5中制作彩色圆环的代码,HTML5 五彩圆环Loading加载动画实现教程

    HTML代码 CSS代码 webkit keyframes spin from webkit transform rotate 360deg transform rotate 360deg to webkit transform rotat
  • Unity做一个发射炮台,1秒发射1个,5秒后消失的例子

    思路 小球要移动 移动一段时间消失 需要translate destory 一个小球不够 需要多次COPY预制体小球 copy 一 COPY代码 把这个代码放在不是复制的球的其他物体上 然后把预制体球拖入a中 using UnityEngi
  • VNC源码研究(十)XP、Win7实现模拟发送ATL+CTRL+DEL

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家拍砖 1 vnc 4 0 winsrc 版本中实现模拟发送ATL CTRL DEL 在工程wrfb win32m中找到模拟发送ATL CTR D