안드로이드 자동화에서 PIPE을 STDIN[각주:1]과 STDOUT[각주:2]을 하는 방법을 알아봐야된다.

 이 방법을 기록한 블로그가 현재 검색이 되지 않아서 MS측에서 제공하는 것을 작성할려고 한다.[각주:3]


 여기에서 작동하는 방법을 이용하면, STDIN과 STDOUT을 받아서 처리할 수 있게 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    HANDLE write_in, write_out;
    HANDLE read_in, read_out;
 
    SECURITY_ATTRIBUTES sec;
 
    long unsigned int writen=0;
    long unsigned int readn=0;
 
    int rtv;
 
    char command[80= {0,};
    char buffer[MAX_LINE];
 
    STARTUPINFO si={0,};
    PROCESS_INFORMATION pi;
 
    //pthread
    pthread_t read_pthread;
    pthread_t write_pthread;
 
    sec.nLength=sizeof(SECURITY_ATTRIBUTES);
    sec.bInheritHandle=TRUE;
    sec.lpSecurityDescriptor=NULL;
 
    CreatePipe(&write_out,&write_in,&sec,0);
    CreatePipe(&read_in,&read_out,&sec,0);
 
    sprintf(command,"./adb.exe shell",NULL);
 
    si.cb=sizeof(STARTUPINFO);
    si.hStdInput=write_out;
    si.hStdOutput=read_out;
    si.dwFlags=STARTF_USESTDHANDLES;
 
    rtv=CreateProcess(NULL,
                      command,
                      NULL,
                      NULL,
                      TRUE,
                      NULL,
                      NULL,
                      NULL,
                      &si,
                      &pi);
 
 
cs


 윗 같이 사용할 경우에, 입/출력 버퍼를 PIPE에 연결하여 처리할 수 있게 된다.

 이렇게 하면, ADB의 SHELL의 입/출력을 다른 쪽으로 연결되어서 처리하게 된다.

  1. STDIN(Standard Input) : 기본적으로 사용자가 키보드에 입력하는 것을 받아들이는 입력 버퍼 [본문으로]
  2. STDOUT (Standard Output) : 기본적으로 모니터에서 출력되는 것을 저장하는 출력 버퍼. [본문으로]
  3. https://support.microsoft.com/ko-kr/kb/190351(2015-06-13) [본문으로]
Posted by JunkMam
,

 안드로이드을 자동으로 컨트롤 하는 방법이 다양하다.

 여기서 ADB을 연결하여 안드로이드 자동화를 하는걸 목표로 공부한걸 기록하도록 한다.


 ADB[각주:1]를이용하면, 사용자가 폰을 건들지 않아도 Touch 이벤트를 일으킬 수 있다.

단, 여기서 매우 빠르게 필요한 경우면, 안 쓰는게 낫다.[각주:2]


 먼저, 자기가 만든 프로그램과 ADB랑 연결하는 방법을 기록한다.


 실행 프로그램과 PIPE로 연결 하기 위해선 FindWindows을 이용해야되지만, 이 방법은 자식 프로세서를 연결한다.


 CreateProcess라는 걸 이용하면, 자식 프로세서가 생성 및 실행이된다. 실행될 프로세서는 ADB이고, 부모 프로세서는 작성하는 프로그램이 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    STARTUPINFO si={0,};
    PROCESS_INFORMATION pi;
 
    char command[80= {0,};
 
    sprintf(command,"./adb.exe shell",NULL);
 
    si.cb=sizeof(STARTUPINFO);
    si.dwFlags=STARTF_USESTDHANDLES;
 
    rtv=CreateProcess(NULL,
                      command,
                      NULL,
                      NULL,
                      TRUE,
                      NULL,
                      NULL,
                      NULL,
                      &si,
                      &pi);
 
 
cs


 이렇게 추가하게 되면, adb의 shell과 연결이 되게 된다.

 차후에 STDIN과 STDOUT을 받는 방법을 기록하도록 한다.



  1. ADB란, Android DeBuger을 뜻한다. Android의 프로그램을 만들때나 기기를 점검할때 사용하기도 한다. [본문으로]
  2. ADB에선 이벤트를 보낼때, 아무리 빨라도 0.5초 가량의 시간이 들게 된다. [본문으로]
Posted by JunkMam
,

fine 프로그램이란,

Linux에서 존재하는 find로 파일을 찾을때 사용한다.

현재 소스는 파일명을 찾는 소스가 아닌, 전체를 훍어서 전체 경로를 출력하는 소스이다.


만드는 방법으로, 재귀 함수를 이용한 백 트레킹이다.


나눠서 컴파일을 하는 분리 컴파일을 이용하였다.


파일명: dir.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
 
//디렉토리를 사용하기 위한 헤더파일
#include <dirent.h>
//파일 정보를 받기 위한 파일.
#include <sys/stat.h>
 
//타이머설정.
#include <windows.h>
 
//잠시 일시 정지등을 하기 위한 파일.
#include <conio.h>
 
#ifndef __DIR_FIND_H__
#define __DIR_FIND_H__
int searchdir(const char*);
#endif // __DIR_FIND_H__
 
cs


파일명: dir.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
#include "_dir.h"
 
/*
searchdir
parament : const char* str
수정하지 않는 str는 디렉토리 절대 경로로 이 경로 다음에 검색을 시작한다.
*/
int searchdir(const char* str){
 
    DIR *dir=NULL;//디렉토리 연결 변수
    struct dirent *dirs=NULL;//해당 디렉토리 파일명 변수
    struct stat *status=NULL;//해당 디렉토리 파일 변수
 
    char* tmpstr=NULL;//디렉토리 연결 변수.
 
    dir=opendir(str);//디렉토리 열어서 사용.
    dirs=readdir(dir);//.(현재 디렉토리 처리)
    dirs=readdir(dir);//..(이전 디렉토리 처리)
 
    //재귀 함수를 이용하여 디렉토리를 사용한다.
    while(dirs=readdir(dir)){
 
        //파일 경로를 저장하기 위한 변수 할당.
        tmpstr=(char*)malloc(strlen(str)+dirs->d_namlen+3);
 
        //현재 디렉토리의 파일을 알아보기 위한 상태값을 받는 변수 할당.
        status=(struct stat*)malloc(sizeof(struct stat));
 
        if(tmpstr==NULL){
            printf("Errors");
            exit(-1);
        }
 
        if(status==NULL){
            printf("Errors Status");
            exit(-1);
        }
 
        strcpy(tmpstr,str);
        strcat(tmpstr,dirs->d_name);
 
        stat(tmpstr,status);
 
        if(S_ISDIR(status->st_mode)){
            strcat(tmpstr,"/");
            printf("%s\n",tmpstr);
            Sleep(50);
            searchdir(tmpstr);
        }else{
            printf("%s\n",tmpstr);
            Sleep(50);
        }
        free(status);
        free(tmpstr);
    }
 
    closedir(dir);
 
    return 0;
}
 
cs


파일명: main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
/**
find 프로그램
해당 설정 경로에서 깊이 우선 순위로 파일을 찾아서 출력하는 목표.
*/
 
#include "dir/_dir.h"
 
int main(int argc, char* argv[])
{
    if(argc >1){
        printf("Find Start %s\n",argv[1]);
        printf("Press any key to start\n");
        getch();
        searchdir(argv[1]);
    }else{
        printf("Find Start C:/\n");
        printf("Press any key to start\n");
        getch();
        searchdir("C:/");
    }
 
    return 0;
}
 
cs


find D:/을 넣을 경우

D: 드라이버에 폴더를 뒤지게 되어 있다.

Posted by JunkMam
,

 stack을 배운지 오래이다.

 여기서 생각한건 'int stack, char stack등 각 자료형을 따로 만드는건 귀찮지 않는가?' 라고 생각했었다.

 그래서 생각한건 void는 자료형을 저장하지 않는다는걸 이용하여 void_stack형을 제작할려고 한다.


 일단, void형의 stack과 자료형이 정의된 stack의 차이는 void형 자료형은 다른 자료형과 다르게, '자료형이 정의 되어있지 않는' 형태이다.

 자료형이 정의 되어 있지 않기 때문에, 자료형의 크기를 정의해줘야하며, 자료형의 크기는 최소 단위인 Byte단위로 처리된다고 생각해야된다.

 그래서 그냥 자료형의 stack 구조체는

1
2
3
4
5
struct stack{
 int size;
 int top;
 int *dats;
};
cs

이런 구조가 된다.

하지만, void형의 구조는 다음과 같이 자료형의 크기를 정의 해줘야된다.

1
2
3
4
5
6
struct _void_stack{
 int i_size;
 char v_size;
 int top;
 void *dats;
};
cs


이 구조를 나는 void_stack이라고 정의 하겠다.

나머지 void_stack에 쓰이는 함수들을 정의는 다음과 같이 할 것이다.

1
2
3
4
int mk_stack(struct _void_stack**,const int,const int);
int push_stack(struct _void_stack*,const void*);
int pop_stack(struct _void_stack*,void*);
int delete_stack(struct _void_stack**);
cs

다른 것과 차이는 mk_stack은 void_stack을 받아서 처리하도록 하고, 실패할시 1을 성공할시 0으로하여 문제점을 제거하는 방향으로 잡았다.

함수의 구현 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
int mk_stack(struct _void_stack** stack,const int i_size,const int v_size){
 
    if(stack==NULL) return 1;//Input Stack is Not Values.
    if(*stack!=NULL) return 1;//Not NULL.
 
    *stack=(struct _void_stack*)malloc(sizeof(struct _void_stack));
 
    if(*stack==NULL) return 1;//Not Create Stack.
 
    (*stack)->i_size=i_size;
    (*stack)->v_size=v_size;
    (*stack)->top=-1;
    (*stack)->dats=NULL;
 
    (*stack)->dats=(void*)malloc(i_size*v_size);
    *(char*)(*stack)->dats=10;
 
    if((*stack)->dats==NULL)return 1;
 
    return 0;
 
}
 
int push_stack(struct _void_stack* stack,const void* dats){
 
    int n = 0;
 
    if(stack==NULL) return 1;//Stack is NULL.
    if(stack->top==stack->i_size) return 1;//Stack is FULL.
 
    stack->top++;
 
    for(n=0;n<stack->v_size;n++){
        *((char*)stack->dats+(stack->v_size*stack->top)+n)=*((char*)dats+n);
    }
 
    return 0;
 
}
 
int pop_stack(struct _void_stack* stack,void* buff){
 
    int n = 0;
 
    if(stack==NULL) return 1;//Stack is NULL.
    if(stack->top==-1return 1;//Stack is Empty.
 
    for(n=0;n<stack->v_size;n++){
        //(char)buff[n]=(char)stack->dats[(stack->v_size*stack->top)+n];
        *((char*)buff+n)=*((char*)stack->dats+(stack->v_size*stack->top)+n);
    }
 
    stack->top--;
 
    return 0;
}
 
int delete_stack(struct _void_stack** stack){
 
    if(stack==NULL) return 1;
    if(*stack==NULL) return 1;
 
    free((*stack)->dats);
    free(*stack);
 
    *stack=NULL;
 
    return 0;
}
 
cs

설명으로 mk_stack의 설명을 하자면,

stack을 받는 변수에 NULL을 넣을 경우 오류나도록 하였고,

stack이 존재할 경우에 오류나도록 하였다.

이 이유는,

1. 값을 넣었을때, 문제를 일으키는 경우를 확인하는 것이다.

2. stack을 올바르게 넣었다고 하더라도 stack이 존재한 상태는 메모리를 손실을 일으킬 수 있기 때문에, 그걸 막기 위하여 NULL인지 확인 하는것이다.

이 2가지는 항상 확인해야되는 것이기 때문에, mk_stack이나, 다른 함수들이 오류나는걸 막는걸 주로 한다.

stack에서 dats을 동적할당하여 만들어 내고, 크기는 i_size[인덱스 크기]와 v_size[변수 자료형 크기]의 합이야한다.


전체 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <stdio.h>
 
#include <stdlib.h>
 
struct _void_stack{
    int i_size;//index size
    int v_size;//value size
    int top;//top
    void* dats;//data
};
 
int mk_stack(struct _void_stack**,const int,const int);
int push_stack(struct _void_stack*,const void*);
int pop_stack(struct _void_stack*,void*);
int delete_stack(struct _void_stack**);
 
 
int mk_stack(struct _void_stack** stack,const int i_size,const int v_size){
 
    if(stack==NULL) return 1;//Input Stack is Not Values.
    if(*stack!=NULL) return 1;//Not NULL.
 
    *stack=(struct _void_stack*)malloc(sizeof(struct _void_stack));
 
    if(*stack==NULL) return 1;//Not Create Stack.
 
    (*stack)->i_size=i_size;
    (*stack)->v_size=v_size;
    (*stack)->top=-1;
    (*stack)->dats=NULL;
 
    (*stack)->dats=(void*)malloc(i_size*v_size);
 
    if((*stack)->dats==NULL)return 1;
 
    return 0;
 
}
 
int push_stack(struct _void_stack* stack,const void* dats){
 
    int n = 0;
 
    if(stack==NULL) return 1;//Stack is NULL.
    if(stack->top==stack->i_size) return 1;//Stack is FULL.
 
    stack->top++;
 
    for(n=0;n<stack->v_size;n++){
        *((char*)stack->dats+(stack->v_size*stack->top)+n)=*((char*)dats+n);
    }
 
    return 0;
 
}
 
int pop_stack(struct _void_stack* stack,void* buff){
 
    int n = 0;
 
    if(stack==NULL) return 1;//Stack is NULL.
    if(stack->top==-1return 1;//Stack is Empty.
 
    for(n=0;n<stack->v_size;n++){
        //(char)buff[n]=(char)stack->dats[(stack->v_size*stack->top)+n];
        *((char*)buff+n)=*((char*)stack->dats+(stack->v_size*stack->top)+n);
    }
 
    stack->top--;
 
    return 0;
}
 
int delete_stack(struct _void_stack** stack){
 
    if(stack==NULL) return 1;
    if(*stack==NULL) return 1;
 
    free((*stack)->dats);
    free(*stack);
 
    *stack=NULL;
 
    return 0;
}
 
 
cs

이렇게 제작하면, void_stack이 완성되게 된다.


Posted by JunkMam
,