adb server不能运维方法,截止占用端口的经过

 使用ntsd程序 (如果安装过VS,在VS的安装目录下,比如“C:\Program Files
(x86)\Debugging Tools for Windows
(x86)\ntsd.exe”,也可以在这里下载)

  最近在做一个类似与任务管理器的东西,里面有个功能,可以通过这个管理器结束掉其他的进程。

 

 

adb server is out of date.  killing…
ADB server didn’t ACK
* failed to start daemon *
error: unknown host service

 

使用adb时,若出上面的错,使用adb
kill-server是没有用的,因为此时是其他进程的监听了端口,而不是adb。我用cmd+命令管理器解决:

输入netstat -ano | findstr “5037”  

找到下列进程

  TCP    127.0.0.1:5037         0.0.0.0:0              LISTENING       4236  

  TCP    127.0.0.1:5037         127.0.0.1:49422        ESTABLISHED     4236  

  TCP    127.0.0.1:49422        127.0.0.1:5037         ESTABLISHED     3840  

此时把4236这个进程结束就行了。

TASKLIST | findstr “4236”

我的是被一个叫tadb.exe的挟持了,貌似是qqmusic的进程,结束它,over

图片 1

在linux系统管理中,我们有时候需要结束掉某个用户的所有进程。初学者一般会先查询出用户的所有pid,然后一条条kill结束掉,或者写一个脚本。实际上结束的方法有很多,博主这边总结了下面4种方法,以kill用户zhangnq为例。

Process类的CloseMainWindow, Kill, Close

Process.CloseMainWindow是GUI程序的最友好结束方式,从名字上就可以看出来它是通过结束主窗体,相当于用户点击窗体的关闭按钮或者按Alt
+
F4。它的本质就是向主窗体发送WM_CLOSE消息(Process.MainWindowsHandle可以返回主窗体的句柄)。这个可以在.NET
Framework源代码中看出来:

publicbool
CloseMainWindow()

{

IntPtr mainWindowHandle =this.MainWindowHandle;

//句柄是否为0

if
(mainWindowHandle ==IntPtr.Zero)

{

returnfalse;

}

//GetWindowLong是否成功执行

if
((NativeMethods.GetWindowLong(newHandleRef(this,
mainWindowHandle), -16)
&0x8000000)
!=0)

{

returnfalse;

}

//0x10 是 WM_CLOSE消息

//向主窗体发送WM_CLOSE,注意是PostMessage而不是SendMessage

NativeMethods.PostMessage(newHandleRef(this,
mainWindowHandle), 0x10, IntPtr.Zero,
IntPtr.Zero);

returntrue;

}

 

CloseMainWindow方法使用PostMessage(不是SendMessage,所以消息会加在消息队列的最后)方法向主窗体发送一个WM_CLOSE消息,这样等主窗体处理完所有消息后,等遇到WM_CLOSE便开始执行退出动作。

比如记事本接到了WM_CLOSE消息但是有未保存的文件记事本会弹出对话框提示用户保存还是不保存还是取消退出操作。Windows
Forms和WPF的窗体都会有类似操作,通过窗体的Closing事件来在WM_CLOSE消息接收后做出是否退出的决定。

 

之后我们会讲到Windows
Forms和WPF都有自己的友好型常规退出方式,但是其实有一个通用的GUI程序退出方式,就是利用这个CloseMainWindow方法:

//Windows Forms和WPF都可以用

//Windows
Forms的Form.Closing事件会在之后发生

//WPF的Windows.Closing事件也会

Process.GetCurrentProcess().CloseMainWindow();

 

 

 

接下来就是Process.Kill方法,从名字也可以看出来,直接杀掉,不给喘息喘息机会呵呵。Kill方法会直接结束整个进程,不进行常规资源清理(什么finally块等……)。Kill本质调用本地API:TerminateProcess函数。

 

 

最后一个是Process.Close方法。抱歉它根本不是用来结束进程的!这个方法名字有些误导,其实根本则不然。它仅仅是而是IDisposable的Dispose方法的具体执行,用来进行Process类的托管资源清理的!

由于Process类继承自Component类,后者继承IDisposable而同时又有析构函数,而通过一个继承类可改写的Dispose方法(参数是bool
disposing)来判断这个Dispose是用户调用还是GC调用。而这个Process.Close()方法正是用户调用Dispose时进行托管资源的清理方法:

下面Process.Dispose方法代码:

protectedoverridevoid
Dispose(bool disposing)

{

if
(!this.disposed)

{

if
(disposing)

{

//用户调用,清理托管资源

this.Close();

}

this.disposed
=true;

//调用Component的Dispose

base.Dispose(disposing);

}

}

 

这个Close方法类似很多其他.NET中的类,比如Stream……因此Close肯定不会结束进程,仅仅是Process类作为IDisposable接口的间接继承者的自我清理方法。

 

 

 

ntsd -c q -p PID
ntsd -c q -pn PName

  在Android平台下,结束进程的方法还是比较多的。首先指明,此处的“结束进程”,包含了结束自身进程和结束其他进程两个方面。通过查阅SDK文档和网上的一些资料,自己找到一些结束进程的方法。在这里做一些归纳和总结,文章的部分信息有可能来自网上已有的文章和帖子,由于过了比较长时间,所以若发现本文与其他文章雷同,请谅解。

  1. pkill方式

    # pkill -u zhangnq

  2. killall方式

    # killall -u zhangnq

  3. ps方式 ps列出zhangnq的pid,然后依次kill掉,比较繁琐。

    # ps -ef | grep zhangnq | awk ‘{ print $2 }’ | xargs kill -9

  4. pgrep方式 pgrep -u参数查出用户的所有pid,然后依次kill

    # pgrep -u zhangnq | xargs kill -9

Environment类的Exit和FailFast

Environment.Exit相当于在Main函数中的return指令。不过它不会执行代码块的finally块(如果有的话),但资源清理还是要进行的。

 

它是最常见的退出当前进程的方法之一。在Main函数中我们可以直接return语句便退出了程序。如果不在Main函数内,那么Environment.Exit方法就可以派上用场:

classa

{

~a()

{

Console.WriteLine(“析构函数”);

}

}

classProgram

{

staticvoid
Main()

{

try

{

a oa
=newa();

test();

}

finally

{

//这段代码永远不会执行

Console.WriteLine(“finally”);

}

}

 

staticvoid
test()

{

Environment.Exit(0);

}

}

 

代码将会输出:

析构函数

看来GC调用了oa的析构函数,但注意finally块没有运行。

 

 

Environment.FailFast方法更速度,它甚至不需要向操作系统返回进程退出代码(ExitCode),直接结束当前进程并在应用程序事件薄中写入信息,用于程序出现致命错误需要立即停止。

classa

{

~a()

{

Console.WriteLine(“析构函数”);

}

}

classProgram

{

staticvoid
Main()

{

try

{

a oa
=newa();

Environment.FailFast(“致命错误发生!”);

}

finally

{

//这段代码永远不会执行

Console.WriteLine(“finally”);

}

}

}

 

在.NET
4.0下,Environment.FailFast代码会抛出FatalExecutionEngineError,而在4.0之前会抛出ExecutionEngineException。但都不会有任何输出(GC没有清理对象,同时finally块也没有运行)

 

 

 

 

两种方法

一、结束一个活动Activity

WPF的Shutdown和Windows Forms的Exit

GUI程序往往都有自己的消息队列和事件管理模式,因此结束一个GUI程序要远复杂与结束一个控制台程序。上述的方法中,Process.Kill和Environment.Exit和FailFast如果用在一个GUI程序中,都会直接强制结束整个程序,而不会激发GUI窗体的一些针对应用程序结束的事件(比如Closing事件)。而上面也讲过:Process.CloseMainWindow通过向主窗体发送一个WM_CLOSE消息可以很好的结束一个GUI程序,不过往往更自然的方法是利用GUI框架本身提供的结束程序的方法。

 

WPF中是System.Windows.Application.Shutdown方法,它其实就是在当前线程的消息队列Dispatcher对象中加入一个正常优先级(DispatcherPriority.Normal)的回调退出函数,等消息队列最后处理到该项时程序开始退出操作。通常这样使用:

//或者App也可以,WPF程序默认会有一个App类继承Application类

Application.Current.Shutdown();

 

 

Windows
Forms中是:System.Windows.Forms.Application.Exit方法。它是通过Application.OpenFormsInternal属性先把已经打开的窗体通过正常方式都关闭(运行Form.Closing事件),最后再结束整个应用程序进程。

 

而且通过WPF的Window.Closing或Windows
Forms的Form.Closing事件都可以取消这种形式的退出操作。

 

 

 

一种是使用进程的ID号,将PID换成对应进程ID号即可

  要主动的结束一个活动Activity,(先强调一下,是结束一个活动,而不是进程)众所周知,肯定是finish方法啦,这个就毋庸置疑了,而且这个方法最后会调用Activity的生命周期函数onDestroy方法,结束当前的Activity,从任务栈中弹出当前的Activity,激活下一个Activity。当然其他的finish系列方法,我们不在这里做详细讨论,有兴趣的同学可以自己查阅一下SDK
的文档。

非托管的ExitProcess和TerminateProcess

这是Windows
API中结束进程的非托管方法。ExitProcess结束进程更友好些,而TerminateProcess会立即强制结束进程。两者的关系有点像Environment.Exit和FailFast,但我不确定本质上是否一样。而且TerminateProcess可以指定进程返回值,但FailFast不可以。两个非托管API的执行都不回运行finally块。

使用起来很简单(关键是P/Invoke,参考:http://www.pinvoke.net,很有用的)

using
System.Runtime.InteropServices;

classProgram

{

[DllImport(“kernel32.dll”)]

staticexternvoid
ExitProcess(uint uExitCode);

 

[DllImport(“kernel32.dll”, SetLastError =true)]

[return:
MarshalAs(UnmanagedType.Bool)]

staticexternbool
TerminateProcess(IntPtr hProcess, uint
uExitCode);

 

staticvoid
Main()

{

ExitProcess(1);

//或者

TerminateProcess(Process.GetCurrentProcess().Handle,
1);

}

}

 

 

 

 

一种是使用进程的名称,将PName换成对应的exe名字即可,比如notepad.exe

二、强制结束当前的进程

手动发送WM_CLOSE,WM_DESTROY,WM_QUIT消息

在一个GUI程序运行环境下,我们通过得到窗体的句柄,然后便可以向该句柄发送消息,WndProc(Window
Procedure)函数会处理相应的事件。其中WM_CLOSE相当于用户点击关闭按钮,使用PostMessage将WM_CLOSE发送至主窗体等价于.NET中Process类的CloseMainWindow方法,当接收到WM_CLOSE消息时,应用程序是可以选择是否真正结束程序的,如果继续结束程序而不取消。接着WM_DESTROY消息会发送,这个消息代表着窗体开始真正关闭,此时可以进行一些资源的清理。最后当前线程接收到WM_QUIT消息,线程的消息循环会被终止。

 

因此向窗体发送这3个消息,只有WM_CLOSE会引发Closing事件,属于正常窗体退出逻辑,其他两个中消息会直接强行关闭窗体。

注意WM_QUIT消息只能用PostMessage将其送至消息队列尾部,使用SendMessage立即发送在WPF应用程序上运行后程序没有任何反应。

 

下面是一个WPF程序发送下列消息,(并没有贴XAML,你一定知道怎样加3个按钮然后把Click事件和窗体的Closing事件绑在代码上吧)

using
System;

using
System.Collections.Generic;

using
System.Linq;

using
System.Text;

using
System.Windows;

using
System.Windows.Controls;

using
System.Windows.Data;

using
System.Windows.Documents;

using
System.Windows.Input;

using
System.Windows.Media;

using
System.Windows.Media.Imaging;

using
System.Windows.Navigation;

using
System.Windows.Shapes;

//外加命名空间

using
System.Diagnostics;

using
System.Runtime.InteropServices;

 

namespace Mgen.TEX

{

publicpartialclassMainWindow
: Window

{

public MainWindow()

{

InitializeComponent();

}

 

//Windows消息值

constuint
WM_CLOSE =0x10;

constuint
WM_DESTROY =0x02;

constuint
WM_QUIT =0x12;

 

//SendMessage和PostMessage的P/Invoke

[DllImport(“user32.dll”, CharSet =CharSet.Auto)]

staticexternIntPtr
SendMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr
lParam);

 

[return:
MarshalAs(UnmanagedType.Bool)]

[DllImport(“user32.dll”, SetLastError =true)]

staticexternbool
PostMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr
lParam);

 

//窗体的Closing事件,判断Closing是否被运行

privatevoid
Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

MessageBox.Show(“Closing事件!”);

}

 

//发送三种消息

privatevoid
WM_CLOSE_Click(object sender, RoutedEventArgs e)

{

//也可以用PostMessage

SendMessage(Process.GetCurrentProcess().MainWindowHandle, WM_CLOSE, IntPtr.Zero,
IntPtr.Zero);

}

 

privatevoid
WM_DESTROY_Click(object
sender, RoutedEventArgs e)

{

//也可以用PostMessage

SendMessage(Process.GetCurrentProcess().MainWindowHandle, WM_DESTROY, IntPtr.Zero,
IntPtr.Zero);

}

 

privatevoid
WM_QUIT_Click(object sender, RoutedEventArgs e)

{

//只能使用PostMessage去将WM_QUIT送至消息队列尾部

PostMessage(Process.GetCurrentProcess().MainWindowHandle, WM_QUIT, IntPtr.Zero,
IntPtr.Zero);

}

 

}

}

为了方便,写了个批处理,将该批处理和ntsd放在一起,使用时执行批处理,选择对应的方式,并输入参数即可。

  强行结束当前进程有两个方法。(呵呵,这里就是结束进程了)

@ECHO OFF
TITLE 结束使用普通方法无法结束的进程
COLOR 0A
MODE con: COLS=62 LINES=22

:MENU
set tm1=%time:~0,2%
set tm2=%time:~3,2%
set tm3=%time:~6,2%
ECHO.  %date% %tm1%点%tm2%分%tm3%秒 
ECHO.   ========================================
ECHO.   请选择要进行的操作,然后按回车
ECHO.   ────────────────────
ECHO.  1    根据进程号PID结束进程
ECHO.  2    根据进程名称结束进程

ECHO.  0    退出
ECHO.
ECHO.请输入选择项目的序号:

set /p choose=
if "%choose%" equ "" goto MENU
if %choose%==1 goto killusingpid
if %choose%==2 goto killusingname
if %choose%==0 goto END

ECHO. 输入错误,请输入正确的项目序号:
goto MENU

:killusingpid
set choose=
ECHO.请输入进程号PID,然后按回车
set /p proid=
set /a i=0
:kpid
ntsd -c q -p %proid%
if %i% GEQ 10 ( ( echo 结束进程%proid%失败 ) & goto MENU )
set /a i=%i%+1
echo 结束进程%proid%第%i%次
tasklist | findstr /i %proid% && ( goto kpid )
echo 结束进程ID为%proid%的程序成功或进程ID:%proid%不存在
GOTO MENU

:killusingname
set choose=
ECHO.请输入进程的名称(比如notepad.exe),然后按回车
set /p proname=
set /a i=0
:kpname
ntsd -c q -pn %proname%
if %i% GEQ 10 ( ( echo 结束程序%proname%失败 ) & goto Menu )
set /a i=%i%+1
echo 结束程序%proname%第%i%次
tasklist | findstr /i %proname% && goto kpname
echo 结束程序%proname%成功或程序:%proname%未启动

GOTO MENU

:END
exit

  1、killProcess(int pid)            
 例子:android.os.Process.killProcess(android.os.Process.myPid());

 

  对于这个方法,需要详细解释一下。在SDK的文档中,解释如下:

 

Kill the process with the given PID. Note
that, though this API allows us to request to kill any process based on
its PID, the kernel will still impose standard restrictions on which
PIDs you are actually able to kill. Typically this means only the
process running the caller’s packages/application and any additional
processes created by that app; packages sharing a common UID will also
be able to kill each other’s processes.

 

英语不好,不能准确翻译,所以希望大家自己理解,免得对大家造成误解。我个人对这句话的解释就是,这个方法使用是有条件的:

 

a、将被杀掉的进程 和 当前进程
处于同一个包或者应用程序中;

参考:

b、将被杀掉的进程
是由当前应用程序所创建的附加进程;

c、将被杀掉的进程 和 当前进程
共享了普通用户的UID。(这里的普通用户,是相对于Root权限的用户来说的)

 

  2、System.exit(int code)            
例子:System.exit(0);

  该方法只能用于结束当前进程自身,个人觉得在程序遇到异常,无法正常执行时,可以通过这个方法强制退出。

  需要注意的是,这两个方法,会导致进程非正常退出,就是说,进程退出时不会去执行onPause、onStop和onDestroy方法,那么进程很有可能错过了保存数据的机会。因此,这两个方法最好使用在出现异常的时候!

三、结束另一个进程

  要通过一个进程去结束另一个进程。在之前的SDK版本中,一直使用方法restartPackage(packageName)方法,但是在Android的开发文档中介绍说,这个函数会导致一些问题( the
previous behavior here is no longer available to applications because it
allows them to break other applications by removing their alarms,
stopping their services, etc.
),所以建议大家使用一个新的方法: 

  void killBackgroundProcesses)(String packageName)

  由于这个方法没有返回值,所以我们也不知道我们的目标进程是否真的退出了。但是,我目前只发现了这个可以结束另一个进程的方法。

四、退出到主屏幕(记得是对当前进程的处理)

  这个方法,也是退出当前进程的一个方法。如果我们在进程中创建了很多的Activity,但是又不想关闭时去退出不在任务栈顶的Activity,那么就可以直接使用这个方法了。这个方法是通过查阅网上资料看到的。在此先感谢
追梦人
了(他的博客地址:,欢迎大家去看看他的博客)。

功能:当按下返回键时,就返回到主屏幕,并带有参数FLAG_ACTIVITY_CLEAR_TOP,会清理掉当前的活动。

 1     @Override
 2     public boolean onKeyDown(int keyCode, KeyEvent event) {
 3         if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { // 按下的如果是BACK,同时没有重复  
 4                 Intent home = new Intent(Intent.ACTION_MAIN);  
 5                home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  
 6                home.addCategory(Intent.CATEGORY_HOME);  
 7                startActivity(home);  
 8         }
 9         return super.onKeyDown(keyCode, event);  
10     }

  此方法确实结束了当前进程,但是通过Android平台的App
Manager工具去查看的话,使用2.3.3的模拟器,会发现刚刚被结束的进程会以Cached
background
Process的形式存在,并且模拟器给出了解释,说是为了下一次更快捷的启动这个进程。

===============================优雅的分割线===============================

【声明】本文系本人原创,转载请注明文章出处:  
博客园

发表评论

电子邮件地址不会被公开。 必填项已用*标注