VS中使用API断点

1. 先加载微软的符号

可使用其它的符号服务器地址

插入图片

2. 增加函数断点

比如要对PostMessage这个API下断点,可增加函数断点:{,,user32.dll}_PostMessageW@16
PostMessage是user32.dll中的API,所以用了{,,user32.dll}, 后面的16是因为它有4个参数(1个参数就是4,以此类推)

插入图片

加载符号后,就可以下断点调试了

hexo环境搭建

hexo静态博客简介

Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。

环境搭建

安装nodejs环境,安装hexo终端命令,克隆博客仓库

#安装nodejs环境
node-v12.18.2-x64.msi
#配置国内的镜像源
npm config set registry https://registry.npm.taobao.org
# 测试查看hexo的安装信息,是否是taobao.org的源	
npm info hexo
#安装hexo终端命令
npm install -g hexo-cli
#安装nodejs依赖
npm install
#验证安装成功
hexo -v
#克隆博客仓库

开发环境安装完成, 开启本地服务器.

#生成html静态页面
hexo generate
#开启服务
hexo server

npm install hexo-deployer-git --save
hexo deploy

此时直接到浏览器http://localhost:4000访问即可

创建一篇新文章

在blog目录执行

#文章名叫 发布文章教程
hexo new post  发布文章教程

会在source/_posts目录下新建一个文件名叫发布文章教程.md

编辑文章头部信息

打开source/_posts/发布文章教程.md, 最上部分内容如下

---
title: 发布文章教程
tags: [hexo, blog]
categories: 环境搭建
date: 2020-7-28 9:00:00
author: hexo
---

修改相应字段. 注意:

  • 冒号后必须跟一个空格
  • tags可以添加多个, 用,隔开. 如tags: [tag1, tag2]
  • categories只能添加一个,多个的时候会识别为分类级别. 如categories: [分类1, 分类2], 会认为当前的分类是分类2, 并且分类2分类1的下级分类.
编辑文章正文

开始用markdown编辑正文吧.
插入图片

预览

编辑好正文之后在本地进行预览

#删除已经生成的静态页面
hexo clean
#重新生成html静态页面
hexo generate
#启动服务
hexo server

提交

预览好之后将新增的md文件以及引用的图片提交到仓库

COM本质论2.COM接口

此博客均属原创或译文,欢迎转载但请注明出处
GiteePage:https://liukang325.gitee.io

看COM本质论做的总结

2.1 再谈接口与实现

其实从上一章“COM是个更好的C++”可以看出,COM最重要的就是将接口与实现分离。

上一章中接口定义头文件中采用C++抽象类的形式,如果调用方是C++环境当然不会有问题。但如果调用方不是C++的编译环境呢?

为了把“接口定义”与“特定实现过程所用到的语言”之间的关联尽可能的断开,我们必须把这两项分离开来,如果所有参与的各方统一使用一种语言(而非C++抽象基类)来定义接口,那么就有可能只定义一次接口,然后在必要的时候导出新的、与实现语言相关的接口定义来。COM提供了这样一种语言,只用到基本的、大家熟悉的C语法,同时加入某些用来“消除C语言二义性特征”的能力。这种语言被称为接口定义语言(Interface Definition Language, IDL)

2.2 IDL

IDL语法就是简单的C语法。IDL支持struct,union,enum,typedef。

IDL属性位于方括号中,多个属性之间以逗号作为分割符,即所谓的属性列表,以区别于基本的IDL文本流。属性总是出现在相应主题的定义之前。

[
	v1_enum,helpstring("This is a color!")
]
enum COLOR { RED, GREEN, BLUE}

当我们在IDL中定义COM方法时,我们必须要显式地指明调用方或被调用方将写入或读每一个参数。

void Method1([in] long arg1,
			 [out] long *parg2,
			 [in,out] long *parg3);

2.3 方法和结果

几乎所有的COM方法都会返回一个HRESULT类型的错误号。对于许多COM兼容的实现语言(如VB,JAVA),这些HRESULT被运行时库或虚拟机截取,然后被映射成为语言中特定的异常(exception)

HRESULT是32位的整数。包含比如网络错误、服务器失败等信息

//31位:严重程度位
//30-29位:保留
//28-16位:操作码
//15-0位:信息码
#define SUCCEEDED(hr)	(long(hr) >= 0)
#define FAILED(hr)		(long(ht) < 0)
//这两个宏充分利用了“当把HRESULT当作有符号的整数时,严重程序位也就是符号位”这一事实

S_OK	一般操作,成功执行
S_FALSE	成功地返回逻辑错误
E_FAIL	一般性失败
E_NOTIMPL	方法没有实现
E_UNEXPECTED 在不准确的时间调用了方法

为了让方法返回一个与“方法的物理HRESULT”不相关的逻辑结果,COM IDL支持retval参数属性,表示: 相关的物理方法参数 实现上是 操作的逻辑结果 ,在支持retval的环境中,该参数应该被映射为操作的结果。

HRESULT Method2([in] short arg1,
				[out,retval] short* arg2);

在Java语言中,被映射为下面的函数:

public short Method2(short arg1);

在Visual Basic中,方法定义下如:

Function Method2(arg1 as Integer) As Integer

Microsoft C++把这个方法映射为:

virtual HRESULT _stdcall Method2(short arg1, short* arg2) = 0;

这样C++的调用代码如下:

short sum = 10;
short s;
HRESULT hr = pItf->Method2(20, &s);
if(FAILED(hr))
	throw hr;
sum += s;

等同于下面的JAVA代码

short sum = 10;
short s = itf.Method2(20);
sum += s;

如果该方法返回的HRESULT表示一个不正常的结果,那么Java虚拟机将把HRESULT映射为Java的异常。而C++代码片断必须要手工检查方法返回的HRESULT,然后相应的处理不正常的结果。

2.4 接口和IDL

IDL的interface关键字用来作为接口定义的开始。接口定义有四个部分:接口名字、基接口名字、接口体、接口属性。

[attribute1, attribute2, ...]
interface IThisInterface: IBaseInterface {
	typedef1;
	typedef2;
	..
	method1;
	method2;
	..
}

COM接口需要一个不同于 逻辑名字 实质名字 。why? 请考虑下面的场景:两个开发人员都选择了同一个逻辑名字ICalculator,如果客户只是简单地使用字符串“ICalculator”来询问对象是否支持这个接口,就有可能获得的不是客户想要的对象接口,尽管接口共享了同一个逻辑名字,但它们是完全不同的接口。

为了消除这样的冲突,所有的COM接口在设计时都被分配了一个二进制的名字,这就是接口的 实质名字 ,这些实质名字被称为全局唯一标识符(Globally Unique Identifier, GUID)

GUID是个128位的大数,可保证在时间和空间两个方面都是唯一,GUID也常被称为接口ID(IID),也被称为类ID(CLSID)

BDA4A270-A1BA-11D0-8C2C-0080C73925BA

为了创建一个新的GUID,COM暴露了一个API函数,可以用来产生新的128位值。该函数使用了非集中式的唯一性算法,所以理论上可以保证结果值不会重复出现。函数原型如下:

HRESULT CoCreateGuid(GUID *pguid);

每个COM接口都必须要有两个IDL属性,[object]属性是必需的,它说明该接口定义是一个COM接口,而不是DCE风格的接口

为了把接口的 实质名字 和它在IDL中的定义联系起来,我们要使用另一个 [uuid] 接口属性,接口一个参数,即GUID的标准文本形式。示例如下:

[object, uuid(BDA4A270-A1BA-11D0-8C2C-0080C73925BA)]
interface ICalculator : IBaseInterface {
	HRESULT Clear(void);
	HRESULT Add([in] long n);
	HRESULT Sum([out, retval] long *pn);
}

接口ICalculator也有一个IID,通过IDL产生的常量IID_ICalculator,我们可以在程序中访问这个IID。

因为很少有编译器支持128位整数,所以COM定义了一个C结构,用来表示GUID

typedef struct _GUID{
	DWORD Data1;
	WORD Data2;
	WORD Data3;
	BYTE Data4[8];
} GUID
typedef GUID IID;
typedef GUID CLSID;

为了允许对GUID值进行比较,COM提供了等价性的测试函数,重载了“==”操作符和“!=”操作符。

既然接口运行时的名字是GUID, 而不是字符串,这就意味着前一章讲的Dynamic_Cast方法需要重新修订。实际上,整个IExtensibleObject接口都需要重新考察,终终要换到COM中的等价接口:IUnknown。

1.5 IUnknown

IUnknow与上一章定义的IExtensibleObject接口用于同样的目的。

class IExtensibleObject {
public:
	virtual void *Dynamic_Cast(const char* pszType) = 0;
	virtual void DuplicatePointer(void) = 0;
	virtual void DestroyPointer(void) = 0;
};

下面是IUnknown的C++定义

extern "C" const IId IID_IUnknow;
interface IUnknow {
	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv) = 0;
	virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
	virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
}

IUnknown的IDL定义可以从SDK的include目录下的unknwn.idl文件中找到:

[
  local,
  object,
  uuid(00000000-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IUnknown
{
  typedef [unique] IUnknown *LPUNKNOWN;

  HRESULT QueryInterface(
    [in] REFIID riid,
    [out, iid_is(riid), annotation("__RPC__deref_out")] void **ppvObject);
  ULONG AddRef();
  ULONG Release();
}
//[local]属性禁止为该接口产生网络代码。这个属性可以放宽COM的要求,否则,所有的远程方法必须返回HRESULT。

再看看我们实现的calculator.idl

[object, uuid(BDA4A270-A1BA-11D0-8C2C-0080C73925BA)]
interface ICalculator : IUnknown {
	import "unknwn.idl";	//引入IUnknown的定义,相当于C++中的 #include "unknown.h"
	HRESULT Clear(void);
	HRESULT Add([in] long n);
	HRESULT Sum([out, retval] long *pn);
}

COM限制了接口的继承性:COM接口不能从多个接口中继承,只能从一个接口继承。 简单的说不支持多重继承

2.6 资源管理和IUnknown

2.7 类型强制转换和IUnknown

2.8 实现IUnknown

2.9 使用COM接口指针

2.10 优化QueryInterface

2.11 数据类型

2.12 IDL属性和COM属性

2.13 异常

2.14 我们走到哪儿了?

COM是一个更好的C++

此博客均属原创或译文,欢迎转载但请注明出处
GiteePage:https://liukang325.gitee.io

看COM本质论做的总结

1.1 软件分发和C++

class FastString {
	char* m_psz;
public:
	FastString(const char *psz);
	~FastString();
	int Length(void) const;
	int Find(const char *psz)const;
};
#include "faststring.h"
#include <string.h>

FastString::FastString(const char *psz)
	:m_psz(new char[strlen(psz) + 1])
{
	strcpy(m_psz, psz);
}
FastString::~FastString()
{
	delete[] m_psz;
}
int FastString::Length(void) const
{
	return strlen(m_psz);
}
int FastString::Find(const char *psz) const
{
	// O(1)
	return 0;
}

假如一个faststring.obj 需要16MB的空间,有三个应用程序ABC都要用到这个类,的方法,那虚拟内存就需要48MB;

另一种情况是,一旦类库的厂商发现了FastString类中的缺陷,我们只能全部重新编译ABC三个应用程序;

1.2 动态链接和C++

解决上面的问题,就是将FastString独立为dll类

#ifndef EXPORT_IMPORT_API
	#ifdef MAKING_LIBRARY
		#define EXPORT_IMPORT_API __declspec(dllexport)
	#else
		#define EXPORT_IMPORT_API __declspec(dllimport)
	#endif
#endif

class EXPORT_IMPORT_API FastString {
	char* m_psz;
public:
	FastString(const char *psz);
	~FastString();
	int Length(void) const;
	int Find(const char *psz) const;
};

库的编译add_definitions(-DMAKING_LIBRARY)

应用程序调用不需要define MAKING_LIBRARY

1.3 C++和可移植性

到此,以上用dll的形式,你将面临C++的基本弱点: C++缺少二进制一级标准。

由于FastString 引入库lib和引出符号dll使用了创建该dll的编译器(比如Gnu C++)的名字改编方案,所以使用其它编译器(比如Borland C++)产生的客户将无法与引入库lib成功链接。

消除名字改编现象的经典技术是使用 extern “C”, 但是这项技术对于FastString这种情况并没有用,因为它引出的是成员函数,而非全局函数。

有一项技术能够减轻这个问题,就是在客户的链接器上,使用模块定义文件(Module Definition File, 通称为DEF文件)

1.4 封装性和C++

假设此时你需要优化一下FastString类,增加了一个成员变量 int m_len(如下)

class EXPORT_IMPORT_API FastString {
    const int m_len; //add
	char* m_psz;
public:
	FastString(const char *psz);
	~FastString();
	int Length(void) const;
	int Find(const char *psz) const;
};

虽然类的公共接口没有变,但实际上sizeof(FastString)发生了变量,由原来的4变成了8。如果直接替换FastString.dll,这样新增的4字节内存就可能被应用程序其它地方占用,造成异常。

所以不得不重新用新的FastString.lib重新编译应用程序ABC。 由于这种耦合性,以及上一节的到的编译器和链接器的不兼容性,“简单地把C++类的定义从DLL中引出来”这种方案并不能提供合理的二进制组件结构。

1.5 把接口从实现中分离出来

faststringitf.h

class EXPORT_IMPORT_API FastStringItf {
    class FastString;
    FastString *m_pThis;
public:
	FastStringItf(const char *psz);
	~FastStringItf();
	int Length(void) const;
	int Find(const char *psz) const;
};

faststringitf.cpp

#include "faststring.h"
#include "faststringitf.h"

FastStringItf::FastStringItf(const char *psz)
	:m_pThis(new FastString(psz))
{
	assert(m_pThis != 0);
}
FastStringItf::~FastStringItf()
{
	delete m_pThis;
}
int FastStringItf::Length(void) const
{
	return m_pThis->Length();
}
int FastStringItf::Find(const char *psz) const
{
	return m_pThis->Find(psz);
}

这样,客户只用包含FastStringItf类的头文件就行,FastStringItf构造函数中的new操作符的调用也要被重新编译,以确保总是分配足够的内存。而且客户永远不会包含实现类FastString类的定义,这使FastString实现者非常灵活。解决了1.4中所存在的问题。

但这样有个坏处,就是如果公有函数比较多的大型类库,光编写这些传递过程就可能非常冗长,也增加出错的可能性,也增加开销。

1.6 抽象基类作为二进制接口 (接口与实现分离)

ifaststring.h

class IFastString {
public:
	virtual int Length(void) const = 0;
	virtual int Find(const char *psz) const = 0;
};

extern "C" IFastString* CreateFastString(const char* psz);

IFastString* CreateFastString(const char* psz)
{
    return new FastString(psz);
}

class FastString : public IFastString{
    const int m_len;
	char* m_psz;
public:
	FastString(const char *psz);
	~FastString();
	int Length(void) const;
	int Find(const char *psz)const;
};

调用:

int f()
{
    IFastString *pfs = CreateFastString("Liukang");
    int n = pfs->Find("kang");
    delete pfs;
    return n;
}

由于接口类的析构函数并不是虚函数,这意味着delete的调用并不会动态找到派生类的析构函数,导致内存泄漏

class IFastString {
public:
	virtual int Delete(void) const = 0; //add
	virtual int Length(void) const = 0;
	virtual int Find(const char *psz) const = 0;
};

在FastString实现类中增加Delete的实现,释放内存

int FastString::Delete(void)
{
    delete this;
}

调用:

int f()
{
    int n = -1;
    IFastString *pfs = CreateFastString("Deface me");
    if(pfs)
    {
        pfs->Find("ace me");
        pfs->Delete();
    }
    return n;
}

在FastString.dll中,除了一个入口函数CreateFastString外,其它所以入口函数都是虚函数。

1.7 运行时多态

到此其实我们已经进入C++库调用的显式加载了

IFastString *CallCreateFastString(const char* psz){
    static IFastString* (*pfn)(const char*) = 0;
    if(pfn){
        const TCHAR szDll[] = __TEXT("FastString.dll");
        const char szFn[] = "CreateFastString";
        HINSTANCE h = LoadLibrary(szDll);
        if(h)
            *(FARPROC*)&pfn = GetProcAddress(h, szFn);
    }
    return pfn ? pfn(psz) : 0;
}

这样的好处是,客户不需要连接dll的引入库lib,对dll没有依赖性。用到才装载dll,没用到就不会被装载。

1.8 对象的扩展性

假设我们需要扩展Load和Save的方法,可按下面的方式

class IExtensibleObject {
public:
	virtual void *Dynamic_Cast(const char* pszType) = 0;
	virtual void Delete(void) = 0;
};
class IFastString : public IExtensibleObject {
public:
	virtual int Length() = 0;
	virtual int Find(const char* psz) = 0;
};
class IPersistentObject : public IExtensibleObject {
public:
	virtual bool Load(const char* pszFileName) = 0;
	virtual bool Save(const char* pszFileName) = 0;
};

有了这样的类型层次之后,客户就可以利用编译器独立的结构,动态地查询对象是否实现了某个指定的接口

bool SaveString(IFastString* pfs, const char* pszFN)
{
	bool bResult = false;
	IPersistentObject *ppo = (IPersistentObject*)pfs->Dynamic_Cast("IPersistentObject");
	if (ppo)
	{
		bResult = ppo->Save(pszFN);
	}
	return bResult;
}

FastString中的Dynamic_Cast的实现可以简单使用显式的静态类型转换功能:

void* FastString::Dynamic_Cast(const char* pszType) {
	if (0 == strcmp(pszType, "IFastString"))
		return static_cast<IFastString*>(this);
	else if (0 == strcmp(pszType, "IPersistentObject"))
		return static_cast<IPersistentObject*>(this);
	else if (0 == strcmp(pszType, "IExtensibleObject")
		return static_cast<IFastString*>(this);
	return 0;
}
/*
注意,当客户请求公共的基接口IExtensibleObject 时,实现类将自己静态转换为IFastString, 是因为
return static_cast<IExtensibleObject*>(this); 有二义性,因为IFastString和IPersistentObject都是从IExtensibleObject继承过来的。
如果IExtensibleObject是IFastString和IPersistentObject的虚基类,那么这个转换就不会有二义性的问题,所以这条语句能够正确编译。
然而,引入虚基类将导致在结果对象中加入不必要的运行时复杂性,而且也会带来编译器相信性。这是因为虚基类是另一项“编译器厂商可以选择自己的实现方法”的c++语言特性。
*/

1.9 资源管理

考虑下面的客户代码:

void f(void)
{
	IFastString* pfs = 0;
	IPersistentObject* ppo = 0;
	pfs = CreateFastString("Feed BOB");
	if (pfs) {
		ppo = (IPersistentObject*)pfs->Dynamic_Cast("IPersistentObject");
		if (!ppo) {
			pfs->Delete();
		}
		else {
			ppo->Save("C:\\autoexec.bat");
			ppo->Delete();
		}
	}
}

客户必须记录下哪个指针是与哪个对象联系在一起的,并且每个对象只能调用一次Delete方法。对于上面的简单代码,并不是繁重的负担,但如果在复杂的客户代码中,管理这些关系会变得非常复杂,并容易出错。为了简化,把管理对象生命周期的责任放在对象的实现部分。参考智能指针的实现方式。

在IExtensibleObject基类中增加两个接口

class IExtensibleObject {
public:
	virtual void *Dynamic_Cast(const char* pszType) = 0;
	virtual void DuplicatePointer(void) = 0;	//add
	virtual void DestroyPointer(void) = 0;		//add
};

在FastString类中增加下面的实现

class FastString : public IFastString ,public IPersistentObject
{
	int m_cPtrs;
public:
	FastString(const char *psz) :m_cPtrs(0) {}
	void DuplicatePointer(void) {
		m_cPtrs++;
	}
	void DestroyPointer(void) {
		if (--m_cPtrs == 0)
			delete this;
	}
};

在两个复制的地方增加指针的计数

//extern "C" 对外接口,new在堆中,复制到stack中
IFastString* CreateFastString(const char* psz)
{
	IFastString* pFsResult = new FastString(psz);
	if (pFsResult)
		pFsResult->DuplicatePointer();
	return pFsResult;
}
//有指针的复制
void* FastString::Dynamic_Cast(const char* pszType) {
	void* pvResult = 0;
	if (0 == strcmp(pszType, "IFastString"))
		pvResult = static_cast<IFastString*>(this);
	else if (0 == strcmp(pszType, "IPersistentObject"))
		pvResult = static_cast<IPersistentObject*>(this);
	else if (0 == strcmp(pszType, "IExtensibleObject")
		pvResult = static_cast<IFastString*>(this);
	//pvResult含有一个复制的指针,所以需要调用
	((IExtensibleObject*)pvResult).DuplicatePointer();
	return pvResult;
}

至此,客户的代码就可以写成:

void f(void)
{
	IFastString* pfs = 0;
	IPersistentObject* ppo = 0;
	pfs = CreateFastString("Feed BOB");
	if (pfs) {
		ppo = (IPersistentObject*)pfs->Dynamic_Cast("IPersistentObject");
		if (ppo) {
			ppo->Save("C:\\autoexec.bat");
			ppo->DestroyPointer();
		}
		pfs->DestroyPointer();
	}
}

1.10 我们走到哪了?

其实不知不觉,我们刚刚一步步设计了组件对象模型(COM, Component Object Model)

Ubuntu Server连接wifi

将旧笔记本装上ubuntu当作服务器,起初装了个 ubuntu-18.10-desktop-amd64.iso

发现没必要装桌面版,于是就装了服务版 ubuntu-18.10-live-server-amd64.iso

(使用UltraISO.exe烧写iso到U盘时,记得选择RAW模式烧写,否则无法装server版)

安装系统 ubuntu-18.10-live-server-amd64.iso

基本参照下面这个步骤完成

其它没什么要注意的,主要是中间要将国外的镜像地址 http://archive.ubuntu.com/ubuntu

换为国内的 http://mirrors.163.com/ubuntu

运行,连wifi

安装成功后,默认不插上网线系统是不能启动的,一直会卡在等待网络那块,无奈先找根网线插上。

由于网线有线,我需要将笔记本连上wifi。

  1. 使用iwconfig命令查看无线网卡的信息, 我的已经连接上了,所以SSID也显示了,第一次配时未显示SSID
liukang@liukang:~$ iwconfig
wlp6s0    IEEE 802.11  ESSID:"CMCC-Qt2.4"  
          Mode:Managed  Frequency:2.462 GHz  Access Point: 3C:E8:24:2E:1E:B8   
          Bit Rate=6.5 Mb/s   Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=45/70  Signal level=-65 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:15  Invalid misc:422   Missed beacon:0

lo        no wireless extensions.

enp7s0    no wireless extensions.

能正常显示出wlp6s0,说明电脑上存在无线网卡, 有的人是wlan0

  1. 启动无线网卡项,或者确认其是启动的:
sudo ip link set wlp6s0 up
  1. 扫描所检测到的无线网络
sudo iw dev wlp6s0 scan | less

这一步会扫描出无线网卡能搜索到的所有无线wifi,我们需要从里面选择一个wifi进行连接。

  1. 连接网络

如果所连接的网络是开放的、没有加密的,则可以轻松地直接连接:

ubuntu:~$ sudo iw dev wlp6s0 connect [网络 SSID]

如果网络是用较低级的协议,WEP加密的,则也比较容易:

ubuntu:~$ sudo iw dev wlp6s0 connect [网络 SSID] key 0:[WEP 密钥]

如果网络使用的是WPA或者WPA2协议,则需要使用一个叫做wpasupplicant的工具,通过如下命令可以自动安装:

ubuntu:~$ sudo apt install wpasupplicant
ubuntu:~$ sudo vim /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant

ap_scan=1

network={
	ssid="CMCC-Qt2.4"
	psk="mypassword"
	priority=1
}

然后在后台启动

sudo wpa_supplicant -i wlp6s0 -c /etc/wpa_supplicant/wpa_supplicant.conf &

有时这个会运行失败,是因为后台已经有一个wpa_supplicant的进程在启动,需要先杀掉

pkill wpa_supplicant

  1. 使用dhclient或者dhcpcd命令为本机获取ip地址:
sudo dhclient wlp6s0
  1. 成功,通过ifconfig 查看wlp6s0(wlan0)的ip地址,说明连接成功,就可以拔网线了。

但如果重启好像又必须插上网线才能成功启动

=================

为了方便每次连接wifi, 在配置好 /etc/wpa_supplicant/wpa_supplicant.conf 的前提下,我写了个脚本

wlan.sh

sudo pkill wpa_supplicant
sudo wpa_supplicant -i wlp6s0 -c /etc/wpa_supplicant/wpa_supplicant.conf &
sudo dhclient wlp6s0

下次运行脚本 即可方便连接wifi

Ubuntu初始化-源及输入法安装

记录此篇的目的,是因为每次重新装一个ubuntu的系统,都需要经历这些基本的初始化步骤,每次都到处在网上找博客,虽然很容易找到,但还是想自己记录下来,避免以后到处百度。

想要安装软件的第一步就是要将软件源改为国内的,否则很多软件无法下载

Ubuntu将软件源改为国内源

  1. 备份原始文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
  1. 修改文件并添加国内源
sudo vi /etc/apt/sources.list

清空并添加下面这些国内常用软件源

#清华的源(推荐)
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main multiverse restricted universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main multiverse restricted universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main multiverse restricted universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main multiverse restricted universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main multiverse restricted universe
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main multiverse restricted universe
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main multiverse restricted universe
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main multiverse restricted universe
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main multiverse restricted universe
deb-src http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main multiverse restricted universe

#阿里云
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse

#网易163
deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse

  1. 更新源
sudo apt-get update
  1. 更新软件(可选,非必需)
sudo apt-get dist-upgrade
sudo apt-get upgrade

安装五笔输入法

实在用不惯自带的拼音输入法,所以每次重装系统第一件事就是装五笔输入法.

由于上面的国内源已经设置好了,所以这步会比较顺利. 否则会各种下不下来.

这里用的ibus,个人觉得比较好用

sudo apt-get install ibus ibus-table ibus-table-wubi

重启一下输入法

ibus-daemon -drx

打开设置对话框

ibus-setup

还是不生效的话记得注销或重启.

Ubuntu使xshell能连接

  1. 安装ssh服务器

    sudo apt-get install openssh-server
  2. 重启ssh服务

    sudo service ssh restart

CMake常用语法摘要

#增加管理员权限
SET_TARGET_PROPERTIES(BoZhuShou PROPERTIES LINK_FLAGS "/level='requireAdministrator' /uiAccess='false'")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
#VS Release 下可调试
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
SET_TARGET_PROPERTIES(${PROJECT} PROPERTIES COMPILE_FLAGS "/Od")
SET_TARGET_PROPERTIES(${PROJECT} PROPERTIES LINK_FLAGS "/DEBUG")
#用CMake屏蔽Release运行时的控制台窗口
Set_Target_Properties(${PROJECT} PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")

C++提升应用程序的权限

BOOL IsRunAsAdmin()
{
	BOOL fIsRunAsAdmin = FALSE;
	DWORD dwError = ERROR_SUCCESS;
	PSID pAdministratorsGroup = NULL;

	// Allocate and initialize a SID of the administrators group.  
	SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
	if (!AllocateAndInitializeSid(
		&NtAuthority,
		2,
		SECURITY_BUILTIN_DOMAIN_RID,
		DOMAIN_ALIAS_RID_ADMINS,
		0, 0, 0, 0, 0, 0,
		&pAdministratorsGroup))
	{
		dwError = GetLastError();
		goto Cleanup;
	}

	// Determine whether the SID of administrators group is enabled in   
	// the primary access token of the process.  
	if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) 
	{
		dwError = GetLastError();
		goto Cleanup;
	}

Cleanup:
	// Centralized cleanup for all allocated resources.  
	if (pAdministratorsGroup) 
	{
		FreeSid(pAdministratorsGroup);
		pAdministratorsGroup = NULL;
	}

	// Throw the error if something failed in the function.  
	if (ERROR_SUCCESS != dwError)
	{
		throw dwError;
	}

	return fIsRunAsAdmin;
}
BOOL ElevateCurrentProcess(LPCTSTR sCmdLine)
{
	USES_CONVERSION;
	TCHAR szPath[MAX_PATH] = { 0 };
	if (::GetModuleFileName(NULL, szPath, MAX_PATH)) 
	{
		// Launch itself as administrator.  
		SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };
		sei.lpVerb = L"runas";
		sei.lpFile = szPath;
		sei.lpParameters = sCmdLine;
		//  sei.hwnd = hWnd;  
		sei.nShow = SW_SHOWNORMAL;

		if (!ShellExecuteEx(&sei))
		{
			DWORD dwStatus = GetLastError();
			if (dwStatus == ERROR_CANCELLED) 
			{
				return FALSE;
			}
			else if (dwStatus == ERROR_FILE_NOT_FOUND)
			{
				return FALSE;
			}
			return FALSE;
		}
		return TRUE;
	}
	return FALSE;
}

使用

if (!IsRunAsAdmin())
{
    QString cmdline = " /action=add";
	ElevateCurrentProcess(cmdline.utf16());
	emit exitApp();
	return;
}

命令行编译obs-studio带cef编译

此博客均属原创或译文,欢迎转载但请注明出处
GiteePage:https://liukang325.gitee.io

早期写过一篇关于obs-studio编译的博客 obs-studio的编译环境配置

图文应该比较清楚了,但每次配一次也需要花不少时间,主要是用鼠标选择很多环境变量。现在用cmake命令行的方式整理下。

其它细节就请参考另一篇博客。

1. 编译cef_binary_3.3112.1659.gfef43e0_windows32.tar.bz2

创建D:\BaiduNetdiskDownload\cef_binary_3.3112.1659.gfef43e0_windows32\build

打开MSBuild Command Prompt for VS2015

cmake -G "Visual Studio 14" ..\

msbuild cef.sln /p:Configuration=Release /t:libcef_dll_wrapper

(cef.sln中包含一些例子,编译会有问题也不需要。这里只需要libcef_dll_wrapper.lib)

2. 编译obs-studio

cmake -DDepsPath=D:\BaiduNetdiskDownload\dependencies2015\win32 -DQTDIR=D:\Qt\Qt5.7.1\5.7\msvc2015 -DCEF_ROOT_DIR=D:\BaiduNetdiskDownload\cef_binary_3.3112.1659.gfef43e0_windows32 -DCEFWRAPPER_LIBRARY=D:\BaiduNetdiskDownload\cef_binary_3.3112.1659.gfef43e0_windows32\build\libcef_dll_wrapper\Release\libcef_dll_wrapper.lib -G "Visual Studio 14" ..\obs-studio

msbuild obs-studio.sln /p:Configuration=Release
  • Copyrights © 2015-2020 阳光柠檬

请我喝杯咖啡吧~

支付宝
微信