精华内容
下载资源
问答
  • 怎样写一个hook
    2021-01-22 04:33:26

    一、为什么要自定义Hook

          将组件逻辑提到可重用的函数中,然后这些函数供它的Hook使用,或者函数组件使用,最终目的是形成公用的Hook库。

          最终根据不同的场景开发自定义不同类型的Hook.

    二、函数名必须为"use"开头,在函数内部可以调用其它的hook(例如:useState,useEffect)

       例子:

    import { useState, useEffect } from 'react';
    
    function useFriendStatus(friendID) {  const [isOnline, setIsOnline] = useState(null);
    
      useEffect(() => {
        function handleStatusChange(status) {
          setIsOnline(status.isOnline);
        }
    
        ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
        return () => {
          ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
        };
      });
    
      return isOnline;
    }

     

    三、两个组件使用相同的Hook会共享state吗?不会

        每次调用 Hook,它都会获取独立的 state。

        我们可以在一个组件中多次调用 useState 和 useEffect,它们是完全独立的。

    四、多个hook之间如何传递信息

         hook本身是函数,通过传参即可完成。

     

     

     

     

     

     

    更多相关内容
  • 来来来,手摸手写一个hook hello,这里是潇晨,今天就带着大家一起来手写一个迷你版的hooks,方便大家理解hook在源码中的运行机制,配有图解,保姆级的教程,只求同学一个小小的????,????。 第一步:引入React和...

    来来来,手摸手写一个hook

    hello,这里是潇晨,今天就带着大家一起来手写一个迷你版的hooks,方便大家理解hook在源码中的运行机制,配有图解,保姆级的教程,只求同学一个小小的👍,🐶。

    第一步:引入React和ReactDOM

    因为我们要将jsx转变为virtual-dom,这一步分工作就交给babel吧,而jsxbabel进行词法解析之后会形成React.createElement()的调用,而React.createElement()执行之后的返回结果就是jsx对象或者叫virtual-dom

    又因为我们要将我们的demo渲染到dom上,所以我们引入ReactDOM

    import React from "react";
    import ReactDOM from "react-dom";
    

    第二步:我们来写一个小demo

    我们定义两个状态countage,在点击的时候触发更新,让它们的值加1。

    在源码中useState是保存在一个Dispatcher对象上面的,并且在mountupdate的时候取到的是不同的hooks,所以我们先暂时从Dispatcher上拿到useState,等下在来定义Dispatcher

    接下来定义一个schedule函数,每次调用的时候会重新渲染组件。

    function App() {
      let [count, setCount] = Dispatcher.useState(1);
      let [age, setAge] = Dispatcher.useState(10);
      return (
        <>
          <p>Clicked {count} times</p>
          <button onClick={() => setCount(() => count + 1)}> Add count</button>
          <p>Age is {age}</p>
          <button onClick={() => setAge(() => age + 1)}> Add age</button>
        </>
      );
    }
    
    function schedule() {	//每次调用会重新渲染组件
      ReactDOM.render(<App />, document.querySelector("#root"));
    }
    
    schedule();
    

    第三步:定义Dispatcher

    在看这部分前,先来捋清楚fiberhookupdate的关系,看图:

    image-20211129105128673

    Dispatcher是什么:Dispatcher在源码中就是一个对象,上面存放着各种各样的hooks,在mountupdate的时候会使用过不同的Dispatcher,来看看在源码中Dispatcher是什么样子:

    在调用useState之后,会调用一个resolveDispatcher的函数,这个函数调用之后会返回一个dispatcher对象,这个对象上就有useState等钩子。

    image-20211126164214374

    那我们来看看这个函数做了啥事情,这个函数比较简单,直接从ReactCurrentDispatcher对象上拿到current,然后返回出来的这个current就是dispatcher,那这个ReactCurrentDispatcher又是个啥?别急,继续在源码中来找一下。

    image-20211126164903336

    在源码中有这样一段代码,如果是在正式环境中,分为两种情况

    1. 如果满足 current === null || current.memoizedState === null,说明我们处于首次渲染的时候,也就是mount的时候,其中current就是我们fiber节点,memoizedState保存了fiberhook,也就是说在应用首次渲染的时候,current fiber是不存在的,我们还没有创造出任何fiber节点,或者存在某些fiber,但是上面没有构建相应的hook,这个时候就可以认为是处于首次渲染的时候,我们取到的是HooksDispatcherOnMount
    2. 如果不满足 current === null || current.memoizedState === null,就说明我们处于更新阶段,也就是update的时候,我们取到的是HooksDispatcherOnUpdate
    if (__DEV__) {
        if (current !== null && current.memoizedState !== null) {
          ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV;
        } else if (hookTypesDev !== null) {
          ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV;
        } else {
          ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV;
        }
      } else {
        ReactCurrentDispatcher.current =
          current === null || current.memoizedState === null
            ? HooksDispatcherOnMount
            : HooksDispatcherOnUpdate;
      }
    

    那我们就来看一下这个HooksDispatcherOnMountHooksDispatcherOnUpdate是个什么,好家伙,原来你包含了所有的hooks啊。

    const HooksDispatcherOnMount: Dispatcher = {
      readContext,
    
      useCallback: mountCallback,
      useContext: readContext,
      useEffect: mountEffect,
      useImperativeHandle: mountImperativeHandle,
      useLayoutEffect: mountLayoutEffect,
      useMemo: mountMemo,
      useReducer: mountReducer,
      useRef: mountRef,
      useState: mountState,
      useDebugValue: mountDebugValue,
      useDeferredValue: mountDeferredValue,
      useTransition: mountTransition,
      useMutableSource: mountMutableSource,
      useOpaqueIdentifier: mountOpaqueIdentifier,
    
      unstable_isNewReconciler: enableNewReconciler,
    };
    
    const HooksDispatcherOnUpdate: Dispatcher = {
      readContext,
    
      useCallback: updateCallback,
      useContext: readContext,
      useEffect: updateEffect,
      useImperativeHandle: updateImperativeHandle,
      useLayoutEffect: updateLayoutEffect,
      useMemo: updateMemo,
      useReducer: updateReducer,
      useRef: updateRef,
      useState: updateState,
      useDebugValue: updateDebugValue,
      useDeferredValue: updateDeferredValue,
      useTransition: updateTransition,
      useMutableSource: updateMutableSource,
      useOpaqueIdentifier: updateOpaqueIdentifier,
    
      unstable_isNewReconciler: enableNewReconciler,
    };
    

    所以dispatcher就是个对象,里面包含了所有的hooks,在首次渲染和更新的时候拿到的是不同的dispatcher,在调用hooks的时候就会调用到不同的函数,比如如果使用了useState,在mount的时候调用到的就是mountState,在update的时候调用到的就是updateState

    image-20211126170906166

    现在我们来手写一下dispatcherdispatcher是个对象,对象上存在useState,我们用一个自执行函数来表示,此外还需要用到两个变量和一个常量fiber

    • workInProgressHook表示遍历到的hook(因为hook会保存在链表上,需要遍历链表计算hook上保存的状态)
    • 为了简单起见,定义一个isMount=true表示mount的时候,在update的时候将它设置成false
    • 为简单起见,fiber就定义成一个对象,memoizedState表示这个fiber节点上存放的hook链表,stateNode就是第二步的demo。
    let workInProgressHook;//当前工作中的hook
    let isMount = true;//是否时mount时
    
    const fiber = {//fiber节点
      memoizedState: null,//hook链表
      stateNode: App
    };
    
    const Dispatcher = (() => {//Dispatcher对象
      function useState(){
        //。。。
      }
    
      return {
        useState
      };
    })();
    

    在定义useState之前,首先来看看hookupdate的数据结构

    hook:
    • queue:上面有pending属性,pending也是一条环状链表,上面存放了未被更新的update,也就是说这些update会以next指针连接成环状链表。
    • memoizedState表示当前的状态
    • next:指向下一个hook,形成一条链表
     const hook = {//构建hook
       queue: {
         pending: null//未执行的update链表
       },
       memoizedState: null,//当前state
       next: null//下一个hook
     };
    
    update:
    • action:是出发更新的函数
    • next:连接下一个update,形成一条环状链表
     const update = {//构建update
        action,
        next: null
      };
    

    那接下来定义useState吧,分三个部分:

    • 创建hook或取到hook
      1. mount的时候:调用mountWorkInProgressHook创建一个初始的hook,赋值useState传进来的初始值initialState
      2. update的时候:调用updateWorkInProgressHook,拿到当前正在工作的hook
    • 计算hook上未更新的状态:遍历hook上的pending链表,调用链表节点上的action函数,生成一个新的状态,然后更新hook上的状态。
    • 返回新的状态和dispatchAction传入queue参数
    function useState(initialState) {
      	//第1步:创建hook或取到hook
        let hook;
        if (isMount) {
          hook = mountWorkInProgressHook();
          hook.memoizedState = initialState;//初始状态
        } else {
          hook = updateWorkInProgressHook();
        }
    		//第2步:计算hook上未更新的状态
        let baseState = hook.memoizedState;//初始状态
        if (hook.queue.pending) {
          let firstUpdate = hook.queue.pending.next;//第一个update
    
          do {
            const action = firstUpdate.action;
            baseState = action(baseState);//调用action计算新的状态
            firstUpdate = firstUpdate.next;//通过update的action计算state
          } while (firstUpdate !== hook.queue.pending);//当链表还没遍历完时 进行循环
    
          hook.queue.pending = null;//重置update链表
        }
        hook.memoizedState = baseState;//赋值新的state
      
    		//第3步:返回新的状态和dispatchAction传入queue参数
        return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回
      }
    

    接下来定义mountWorkInProgressHookupdateWorkInProgressHook这两个函数

    • mountWorkInProgressHook:在mount的时候调用,新创建一个hook对象,
      1. 如果当前fiber不存在memoizedState,那当前hook就是这个fiber上的第一个hook,将hook赋值给fiber.memoizedState
      2. 如果当前fiber存在memoizedState,那将当前hook接在workInProgressHook.next后面。
      3. 将当前hook赋值给workInProgressHook
    • updateWorkInProgressHook:在update的时候调用,返回当前的hook,也就是workInProgressHook,并且将workInProgressHook指向hook链表的下一个。
    function mountWorkInProgressHook() {//mount时调用
        const hook = {//构建hook
          queue: {
            pending: null//未执行的update链表
          },
          memoizedState: null,//当前state
          next: null//下一个hook
        };
        if (!fiber.memoizedState) {
          fiber.memoizedState = hook;//第一个hook的话直接赋值给fiber.memoizedState
        } else {
          workInProgressHook.next = hook;//不是第一个的话就加在上一个hook的后面,形成链表
        }
        workInProgressHook = hook;//记录当前工作的hook
        return workInProgressHook;
      }
    
    function updateWorkInProgressHook() {//update时调用
      let curHook = workInProgressHook;
      workInProgressHook = workInProgressHook.next;//下一个hook
      return curHook;
    }
    

    第四步:定义dispatchAction

    • 创建update,挂载载queue.pending

      1. 如果之前queue.pending不存在,那创建的这个update就是第一个,则update.next = update
      2. 如果之前queue.pending存在,则将创建的这个update加入queue.pending的环状链表中

      1

    • isMount=false,并且赋值workInProgressHook,调用schedule进行更新渲染

    function dispatchAction(queue, action) {//触发更新
      const update = {//构建update
        action,
        next: null
      };
      if (queue.pending === null) {
        update.next = update;//update的环状链表
      } else {
        update.next = queue.pending.next;//新的update的next指向前一个update
        queue.pending.next = update;//前一个update的next指向新的update
      }
      queue.pending = update;//更新queue.pending
    
      isMount = false;//标志mount结束
      workInProgressHook = fiber.memoizedState;//更新workInProgressHook
      schedule();//调度更新
    }
    

    最终代码

    import React from "react";
    import ReactDOM from "react-dom";
    
    let workInProgressHook;//当前工作中的hook
    let isMount = true;//是否时mount时
    
    const fiber = {//fiber节点
      memoizedState: null,//hook链表
      stateNode: App//dom
    };
    
    const Dispatcher = (() => {//Dispatcher对象
      function mountWorkInProgressHook() {//mount时调用
        const hook = {//构建hook
          queue: {
            pending: null//未执行的update链表
          },
          memoizedState: null,//当前state
          next: null//下一个hook
        };
        if (!fiber.memoizedState) {
          fiber.memoizedState = hook;//第一个hook的话直接赋值给fiber.memoizedState
        } else {
          workInProgressHook.next = hook;//不是第一个的话就加在上一个hook的后面,形成链表
        }
        workInProgressHook = hook;//记录当前工作的hook
        return workInProgressHook;
      }
      function updateWorkInProgressHook() {//update时调用
        let curHook = workInProgressHook;
        workInProgressHook = workInProgressHook.next;//下一个hook
        return curHook;
      }
      function useState(initialState) {
        let hook;
        if (isMount) {
          hook = mountWorkInProgressHook();
          hook.memoizedState = initialState;//初始状态
        } else {
          hook = updateWorkInProgressHook();
        }
    
        let baseState = hook.memoizedState;//初始状态
        if (hook.queue.pending) {
          let firstUpdate = hook.queue.pending.next;//第一个update
    
          do {
            const action = firstUpdate.action;
            baseState = action(baseState);
            firstUpdate = firstUpdate.next;//循环update链表
          } while (firstUpdate !== hook.queue.pending);//通过update的action计算state
    
          hook.queue.pending = null;//重置update链表
        }
        hook.memoizedState = baseState;//赋值新的state
    
        return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回
      }
    
      return {
        useState
      };
    })();
    
    function dispatchAction(queue, action) {//触发更新
      const update = {//构建update
        action,
        next: null
      };
      if (queue.pending === null) {
        update.next = update;//update的环状链表
      } else {
        update.next = queue.pending.next;//新的update的next指向前一个update
        queue.pending.next = update;//前一个update的next指向新的update
      }
      queue.pending = update;//更新queue.pending
    
      isMount = false;//标志mount结束
      workInProgressHook = fiber.memoizedState;//更新workInProgressHook
      schedule();//调度更新
    }
    
    function App() {
      let [count, setCount] = Dispatcher.useState(1);
      let [age, setAge] = Dispatcher.useState(10);
      return (
        <>
          <p>Clicked {count} times</p>
          <button onClick={() => setCount(() => count + 1)}> Add count</button>
          <p>Age is {age}</p>
          <button onClick={() => setAge(() => age + 1)}> Add age</button>
        </>
      );
    }
    
    function schedule() {
      ReactDOM.render(<App />, document.querySelector("#root"));
    }
    
    schedule();
    

    预览效果:https://codesandbox.io/s/custom-hook-tyf19?file=/src/index.js

    视频讲解(高效学习):点击学习

    往期react源码解析文章:

    1.开篇介绍和面试题

    2.react的设计理念

    3.react源码架构

    4.源码目录结构和调试

    5.jsx&核心api

    6.legacy和concurrent模式入口函数

    7.Fiber架构

    8.render阶段

    9.diff算法

    10.commit阶段

    11.生命周期

    12.状态更新流程

    13.hooks源码

    14.手写hooks

    15.scheduler&Lane

    16.concurrent模式

    17.context

    18事件系统

    19.手写迷你版react

    20.总结&第一章的面试题解答

    展开全文
  • 易语言远程HOOK监视内存读写源码,远程HOOK监视内存读写,内存_远程HOOK读写_回调,HOOK_远程函数_取参数值,HOOK_远程函数_安装,HOOK_远程函数_窗口,HOOK_远程函数_卸载,下面为辅助功能,Call,内存_读整数型,指针_取变量...
  • 易语言使用APIhook进行拦截文件读写,拦截文件读写,使用apihook
  • APIHook文件监控 监控指定目录下文件的读写和修改.zip
  • 易语言远程HOOK监视内存读写源码
  • 一个基于Magisk&Riru的Module,可以助你用超低成本开发各种Hook插件,无须Xposed 此Module仅供大家学习研究,请勿用于商业用途。利用此Module进行非法行为造成的一切后果自负! 博客详情: 背景: 前段时间在...
  • 大家好,我是努力学习 React 的前端西瓜哥。 我们在 React 函数组件时,如果想要...当第一次执行函数组件时,React 会分配一个对象,然后一个个调用 Hook 时,将得到的结果依次放入到有序的表中,然后保存在该对象

    大家好,我是努力学习 React 的前端西瓜哥。

    我们在写 React 函数组件时,如果想要复用组件的部分逻辑,可以考虑写自定义 Hook。本文会教大家如何写自定义 React Hook。

    Hook 的规则

    在此之前,我们先了解一下 Hook 的使用规则。

    首先 Hook 只能在函数组件的顶层使用,不能在循环、条件、嵌套函数中执行。

    这和 React Hook 的实现原理有关。当第一次执行函数组件时,React 会分配一个对象,然后一个个调用 Hook 时,将得到的结果依次放入到有序的表中,然后保存在该对象中。

    之后的执行,必须要保证这些 Hook 的执行顺序相同,才能做依赖项的对比,以及和前一次渲染的状态的对比。

    如果能 hook 可以出现循环、条件、嵌套函数中,就不能保证 Hook 执行顺序不变。

    此外Hook 只能在函数组件内工作,不要在非组件函数中使用 Hook

    如果你在普通函数内使用了 Hook,React 会报错。

    当然如果是自定义 Hook(一个使用了 React 内置 Hook 的普通函数),然后放到函数组件内,那也是合法的。

    为防止开发者不小心写岔,React 官方还写了一个名为 eslint-plugin-react-hooks 的 ESLint 插件,用于检测不合法的 Hook 调用位置,实在是太贴心了。强烈建议使用。

    写一个自定义 Hook

    自定义 Hook,就是使用了内置 Hook 的普通函数。它是对函数组件可复用的部分逻辑的做了一层封装,然后再被函数组件使用。

    自定义的 Hook 必须使用 use 开头。因为 React 的官方 ESLint 插件认为 use 开头是自定义 Hook。

    如果你不用 use 开头,ESLint 插件就会认为这是一个普通函数,调用时不符合 Hook 规则时不会报错,你就可能写出有问题的代码。

    另外,自定义 Hook 下使用的 Hook,也必须位于顶层,这也是为了保证 hook 的顺序多次执行能保持一致。

    下面我们来写几个常用的自定义 Hook

    useMount / useUnmount

    我们希望实现类似类函数 componentDidMount 的效果。

    const useMount = fn => {
      useEffect(() => {
        fn();
      }, []);
    }
    

    使用方式:

    function App = () => {  
      // 自定义 Hook
      useEffect(() => {
        console.log('挂载');
      });
      
      // 原来的写法
      useEffect(() => {
        console.log('挂载');
      }, []);
    }
    

    相比原来的 useEffect 的实现,做了封装后的 useMount 更语义化一些。

    此外,也不需要写多余的依赖项,并将组件销毁的逻辑隔离出去。

    类似类函数 componentWillUnmount 的 useUnmount Hook 实现如下:

    const useUnmount = fn => {
      useEffect(() => fn, []);
    }
    
    // 用法
    useUnmount(() => {
      console.log('销毁');
    })
    

    useUpdateEffect

    下面我们再实现一个 useEffect 的剔除掉挂载那一次的版本,对标类函数的 componentDidUpdate。

    const useUpdateEffect = (fn, deps) => {
      const isMount = useRef(true);
      useEffect(() => {
        if (isMount.current) {
          isMount.current = false;
          return;
        }
        return fn();
      }, deps);
    }
    
    // 用法
    useUpdateEffect(() => {
      console.log('更新');
    })
    

    思路其实很简单,就是多使用一个默认值为 true 的布尔值变量。我们用它来记录当前是否为第一次执行,如果是,就不执行传入的函数,然后将布尔值设置为 false。

    false 代表之后都是第二次第三次的执行,每次都执行传入的函数。

    这里我们没有用 useState,因为通过 setState 方法会重新渲染组件。所以我们使用了 useRef,修改它的值不会触发组件的更新。

    结尾

    自定义 Hook,是一种比组件更小粒度的可复用逻辑组织方式,这也是 React 函数组件带给我们最大的惊喜。为此,我们有必要学习好自定义 Hook。

    我是前端西瓜哥,欢迎关注我。

    展开全文
  • 内容索引:VC/C++源码,系统相关,HOOK,钩子 VC++的APIHook实例源代码,大致翻了一下,只挂引入表的函数,注入有SetWindowHookEx和CreateRemoteThread两种方式,进程枚举也区分了不同系统下使用的psai和toolhelp,...
  • 易语言 拦截文件读写 APIhook 拦截打开文件 拦截文件读入 拦截取文件长度 拦截文件读写位置
  • 纯C#实现Hook功能详解

    2021-01-01 08:16:48
    发布一个自己的用于Hook .Net方法的类库,代码量不大,完全的C#代码实现,是一个比较有趣的功能,分享出来希望能和大家共同探讨 安装:Install-Package DotNetDetour 源码:...
  • 如何Hook一个函数

    2022-04-02 20:12:17
    【IT168 技术文档】函数是什么  在LUA中, 一个函数是一个简单的变量。从LUA的文档来看:  The statement function f () ... end translates to f = function () ...... 如何Hook一个函数

    【IT168 技术文档】函数是什么

      在LUA中, 一个函数是一个简单的变量。从LUA的文档来看:

     
    

      The statement   function f () ... end   translates to   f = function () ... end

      那意味着任意一个函数能被其它的任意一个函数通过一个简单的分配所替代。把这个记在心里,它将变得很容易去“Hook”,或者是添加你自己的函数到一个预先定义好的函数中。 # Hook 有钩住,钩子的意思。

      如何Hook一个函数

      警告:这个部分包含过时的信息。比如说我们想显示那些我们级别高很多的玩家和怪的级别来替代骷髅。隐藏级别的函数是TargetFrame_CheckLevel(),因此我们需要hook那个函数来让它不要隐藏级别。

      让我们假设我们的插件被命名为"MyAddOn",并且有一个OnLoad处理器被它的XML 事件所调用。在Lua的文档中我们应该有:

     
    

      local MyAddOn_Orig_TargetFrame_CheckLevel;   function MyAddOn_OnLoad()   MyAddOn_Orig_TargetFrame_CheckLevel = TargetFrame_CheckLevel; -- 存储原始的函数   TargetFrame_CheckLevel = MyAddOn_TargetFrame_CheckLevel; -- Hook进我们的   end

      因此上面所做的就是它存储原始"TargetFrame_CheckLevel" 的参量到"MyAddOn_Orig_TargetFrame_CheckLevel"。接着它用我们的函数替换了原始的,因此现在任何人调用TargetFrame_CheckLevel()时实际上得到的是被MyAddOn_TargetFrame_CheckLevel()所替代的。

      下一步就是创建我们的MyAddOn_TargetFrame_CheckLevel()。让我们假设我们想要它显示目标的级别。

     
    

      function MyAddOn_TargetFrame_CheckLevel()   local retval = MyAddOn_Orig_TargetFrame_CheckLevel(); -- 调用原始的函数   TargetLevelText:Show();   TargetHighLevelTexture:Hide();   return retval;   end

      因此在这个函数中,我们首先调用老的函数让它做它必需做的。接着,显示级别并且隐藏骷髅。非常简单不是吗?

      这只是一个怎么样hook的例子,它不是真的为你显示级别。 --影子而矣

      很容易就能Hook一个函数吗?

      如你有Sea库,那么你能hook一个函数用Sea.util.hook。

     
    

      Sea.util.hook("OldFunctionName", "NewFunctionName", "before|after|hide|replace");

      如果你指明代替,那么老的函数将只在新的函数返回真时被调用。

      如果你使用Sea.util.hook,那么你也能在此过后用Sea.util.unhook移去hook。

     
    

      Sea.util.unhook("OldFunctionName, "NewFunctionName");

      使用Sea.util.hook 要小心参数的传递,优先权,链接并且你能确保在此过后你能清掉这些。

      有选择的使用Sea

      如果你不想你的插件依赖Sea,但是你又想当它可用时获益,你可以检测它的存在:

     
    

      local MyAddOn_Old_FunctionToHook = function() end;   if Sea then   Sea.util.hook("FunctionToHook", "ReplacementFunction", "after");   else   MyAddOn_Old_FunctionToHook = FunctionToHook;   FunctionToHook = ReplacementFunction;   end   function ReplacementFunction()   MyAddOn_Old_FunctionToHook();   ...   end

      这些编码允许你在你的TOC中列出Sea做为一个OptionalDep。这能帮你防止将来用户安装Sea时其它的插件完全替换老的函数所引起的冲突。

      其它Hooking库

      Stubby

      用Stubby你能hook函数如Stubby.HookFunction

     
    

    Stubby.RegisterFunctionHook("FunctionToHook", position,

    replacementFunction [, hook1, hook2, .., hookN])

      “FunctionToHook”是一个字符串用做你想hook进的hook名字。即:"GameTooltip.SetOwner" (#游戏工具提示.设置所有者)

      “position”是一个负数或正数定义着插件的真实调用次序。更小或负数,它被你的hookFunction调用的越早,大的数字则反之。实际上初始的(hooked)函数被调用是在position 0,因此如果你的插件被hook在一个负的position,你返回的值表(看下面)将包括在Stubby调用链中以前的函数的值。

      你传递(用参量)你的函数一个你想做为替代的函数被调用。这个函数将被下面的参数调用:hookFunction(hookParams, returnValue, hook1, hook2 .. hookN)

      “hookParams”是一个包括附加参数表被传递到RegisterFunctionHook function (the "hook1, hook2, .., hookN" params)

      “returnValue”是一个在你进入Stubby调用链或如果没有为空值时被调用函数返回值的数组。

      “hook1..hookN”是在初始次序被hook函数的初始参数。

      有特殊处理的情况时你能有选择的返回下列字符串到Stubby。

      "abort" 将中止调用链(将不会调用任何在你自己所有之后的其它函数计划表)。

      "killorig"将不再调用初始的函数,但是将继续调用链。

      "setparams"将用你所指定一个列表中的你函数的第二返回值来替换函数的调用参数。

      "setreturn" 将用你所指定一个列表中的你函数的第二返回值来改变在Stubby调用链中下一个函数的返回值。

      Ace

      Ace2

      到什么地方去调用老的函数

      这是很有技巧的,并且真的依赖于你现在正在写的。缺省的情况下你应该有可能首先调用到老的函数,接着做你任何你需要做的。然而,有的时候,你想最后调用老的函数,有条件地调用它,或者根本就不调用它。

      注意:不要调用有热门效果的老函数假设另一个插件在你之前hook它。接着什么是你将做的呢,就是不要让插件看见函数调用。这个是hook库真的帮的上忙的地方。

      函数带参数

      如果你的一个函数带参数,确信你的新函数也带同样的参数,并且它能传递它。

      因此举个例子假设我们想hook ActionButton_GetPagedID( id )我们的函数定义应该象:

     
    

      function New_ActionButton_GetPagedID( id )   Old_ActionButton_GetPagedID( id );   ...   end

      函数使用全局变量

      一些函数使用全局变量,并且能在执行过程中改变这些全局变量。例如,GameTooltip_OnEvent()就是这样的函数,在其中它使用全局事件变量,并且在执行过程中改变它。在这种情况中,重要的是在调用老函数前做一个变量的拷贝。好象:

     
    

      function New_GameTooltip_OnEvent()   local myEvent = event;   Old_GameTooltip_OnEvent();   if ( myEvent = ... ) then   ...   end   end

      Hook 链

      警告:这个部分包含过时的信息。这有点技巧,但是起作用。我们说这有两个单独的的插件,一个附加玩家工具提示到鼠标,以及另一个被用来替换??的玩家级别。一个插件被称做“AnchorToolTip--锚定工具提示”,另一个被称为“ShowLevel--显示级别”。

      如果的AnchorToolTip编码是:

     
    

      local Pre_AnchorToolTip_GameTooltip_OnEvent;   function AnchorToolTip_OnLoad()   Pre_AnchorToolTip_GameTooltip_OnEvent = GameTooltip_OnEvent;   GameTooltip_OnEvent = AnchorToolTip_GameTooltip_OnEvent;   end   function AnchorToolTip_GameTooltip_OnEvent()   Pre_AnchorToolTip_GameTooltip_OnEvent();   ...   end

      以及ShowLevel的编码是:

     
    

      local Pre_ShowLevel_GameTooltip_OnEvent;   function ShowLevel_OnLoad()   Pre_ShowLevel_GameTooltip_OnEvent = GameTooltip_OnEvent;   GameTooltip_OnEvent = ShowLevel_GameTooltip_OnEvent;   end   function ShowLevel_GameTooltip_OnEvent()   Pre_ShowLevel_GameTooltip_OnEvent();   ...   end

      这真的将起作用。然而,我们说你不仅想Anchor(锚定)tooltip到鼠标当shift 键被按下时。一个小的简单改变好象:

     
    

      function AnchorToolTip_GameTooltip_OnEvent()   if ( isShiftKeyDown() ) then   Pre_AnchorToolTip_GameTooltip_OnEvent();   ...   end   end

      有可能打断hook链取决于哪个插件先加裁。因而,千万千万小心当你决定什么时候在什么地方调用老函数。你不仅在调用Blizzard的编码,你可能也调用了整个hook函数。

    展开全文
  • 易语言杀软监控源码例程程序结合易语言通用对象支持库,调用API函数监控杀软。易语言杀软监控源码对学习HOOK有所帮助。 易学编程网
  • 基于pc微信2.8.0.121版本,实现了常用功能(登录回调,好友操作、通讯录获取、数据库查询、接收消息、发送消息等)真实源码,不骗人,适合初学者研究学习用,可进行二次开发
  • VC 的APIHook实例源代码,VC 的APIHook实例源代码,大致翻了一下,只挂引入表的函数,注入有SetWindowHookEx和CreateRemoteThread两种方式,进程枚举也区分了不同系统下使用的psai和toolhelp,另外为了获得...
  • 一个vc的inlineHook MessageBox小例子,希望对大家有帮助。
  • 用React hook写一个倒计时

    千次阅读 2020-06-16 14:17:15
    import React, { useState, useEffect, useCallback, useRef } from 'react'; const CountDown: React.FC = () => { const intervalRef = useRef<any>(null); const [count, changeCount] = useState...
  • 易语言源码易语言远程HOOK监视内存读写源码.rar 易语言源码易语言远程HOOK监视内存读写源码.rar 易语言源码易语言远程HOOK监视内存读写源码.rar 易语言源码易语言远程HOOK监视内存读写源码.rar 易语言源码易语言...
  • 自己经常没事做做单机游戏的作弊软件玩,经常遇到需要写hook的时候 ,于是乎就自己写了一个小巧的hook类库, 使用了beaengine的汇编引擎,如果是用来做系统apihook 也可以做到 只是没有detour那么简单无脑好用,我...
  • 老外的sockethook代码 实现socket钩子,提供hook代码和测试例程序-Written by foreigners sockethook hook socket code to provide hook procedure code and test cases
  • io/s/ykmklm6m21 简单的数据获取 为了获取数据,你需要将一个 Promise 返回函数作为第一个参数传递给 usePromise 钩子。 它将返回与响应相关的有效负载,例如已解析的数据、请求状态或错误(如果存在)。 resolve ...
  • 用API HOOK实现禁止复制文件
  • 看到一个 开源的HOOK CreatefileA的帖子 里面说 “ 直接APIhook会 出错 只有汇编hook了 ” ,那我个APIhook的方法。用到了精易模块的APIhook类。
  • 后来我想了下我这篇更偏向于怎么写一个稳定可用hook框架,更偏向设计、编程,所以适合已经有些基础的,不是从0讲述hook到实现,虽然接下来的部分也会有很细节的部分,但是是针对一些特定的点。建议可以先看下其他人...
  • hook 写一个Loading案例

    2019-02-14 12:06:12
    我们在实际的业务场景下,遇到一个需求: 对于一些加载比较慢的资源,组件最初展示标准的Loading效果,但在一定时间(比如2秒)后,变为“资源较大,正在积极加载,请稍候”这样的友好提示,资源加载完毕后再展示...
  • 利用API Hook截获CreateFile和CloseHandle达到加解密DOC文件和防拷贝的目的 visual c++调用hook API钩子截获CreateFile和CloseHandle来加密WORD文件+实现文件防拷贝
  • Hook内存读写

    2014-01-27 21:07:32
    Hook内存读写不解释.。 更好的操作。
  • Xposed Hook专题

    2020-09-24 16:11:33
    Xposed Hook模块开发教程,从Xposed框架安装,到Xposed模块开发,详细讲解Xposed中使用到的类与方法,以及实战案例分析。
  • 我们可以通过api hook,改变一个系统api的原有功能。基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。 Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,...
  • 【JS逆向】之HOOK代码怎么写

    千次阅读 2021-06-10 20:20:52
    这里我自己写一个方法去替换。实例 function myfunction(x,y){ if(x>y){ return "是原来的方法"; }else{ return "方法参数被修改了"; } myfunction(2,1)//原来方法的执行结果 "是原来的方法" var xxx=myfu

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 77,503
精华内容 31,001
关键字:

怎样写一个hook