获取系统中所有进程&线程信息

读书笔记--[计算机病毒解密与对抗]

目录:

  1. 遍历进程&线程程序
  2. 终止进程
  3. 获取进程信息
  4. 获取进程内模块信息
  5. 获取进程命令行参数

代码运行环境:Win7 x64

VS2012 Update3

遍历系统中所有进程

[cpp] view plain copy

print?

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <TlHelp32.h>
  4. int main()
  5. {
  6. // 为进程的所有线程拍个快照
  7. HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  8. if( hSnapshort==INVALID_HANDLE_VALUE )
  9. {
  10. printf("CreateToolhelp32Snapshot调用失败!\n");
  11. return -1;
  12. }
  13. // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
  14. PROCESSENTRY32 stcProcessInfo;
  15. stcProcessInfo.dwSize = sizeof(stcProcessInfo);
  16. BOOL  bRet = Process32First(hSnapshort, &stcProcessInfo);
  17. printf("进程名\t\t\t 进程ID\t 线程数\t 父进程ID\n");
  18. while (bRet)
  19. {
  20. printf("%ls\t\t %d\t %d\t %d\n", stcProcessInfo.szExeFile, stcProcessInfo.th32ProcessID, stcProcessInfo.cntThreads, stcProcessInfo.th32ParentProcessID);
  21. bRet = Process32Next(hSnapshort, &stcProcessInfo);
  22. }
  23. CloseHandle(hSnapshort);
  24. system("pause");
  25. return 0;
  26. }

#include <stdio.h>
#include <windows.h>
#include <TlHelp32.h>

int main()
{
    // 为进程的所有线程拍个快照
    HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if( hSnapshort==INVALID_HANDLE_VALUE )
    {
        printf("CreateToolhelp32Snapshot调用失败!\n");
        return -1;
    }

    // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
    PROCESSENTRY32 stcProcessInfo;
    stcProcessInfo.dwSize = sizeof(stcProcessInfo);

    BOOL  bRet = Process32First(hSnapshort, &stcProcessInfo);

    printf("进程名\t\t\t 进程ID\t 线程数\t 父进程ID\n");

    while (bRet)
    {
        printf("%ls\t\t %d\t %d\t %d\n", stcProcessInfo.szExeFile, stcProcessInfo.th32ProcessID, stcProcessInfo.cntThreads, stcProcessInfo.th32ParentProcessID);

        bRet = Process32Next(hSnapshort, &stcProcessInfo);
    }

    CloseHandle(hSnapshort);

    system("pause");
    return 0;
}

遍历系统中所有线程

[cpp] view plain copy

print?

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <TlHelp32.h>
  4. int main()
  5. {
  6. // 为进程的所有线程拍个快照
  7. HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  8. if( hSnapshort==INVALID_HANDLE_VALUE )
  9. {
  10. printf("CreateToolhelp32Snapshot调用失败!\n");
  11. return -1;
  12. }
  13. // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
  14. THREADENTRY32 stcThreadInfo;
  15. stcThreadInfo.dwSize = sizeof(stcThreadInfo);
  16. BOOL  bRet = Thread32First(hSnapshort, &stcThreadInfo);
  17. DWORD dwProId = -1;  // 保存上一个线程的进程ID
  18. unsigned unCount=0;
  19. while (bRet)
  20. {
  21. if( dwProId!=stcThreadInfo.th32OwnerProcessID )
  22. {
  23. // 记录PID与所属PID不同,遍历至不属于同一进程的线程
  24. if( dwProId!=-1 )
  25. {
  26. // 不是第一次遍历
  27. printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
  28. unCount = 0;
  29. printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
  30. }
  31. dwProId = stcThreadInfo.th32OwnerProcessID;
  32. printf("进程%d:\n\n ", dwProId);
  33. printf("线程TID\t\t线程所属进程PID\t\t线程优先级\n");
  34. }
  35. printf("  %d\t\t\t%d\t\t\t %d\n",stcThreadInfo.th32ThreadID, stcThreadInfo.th32OwnerProcessID, stcThreadInfo.tpBasePri);
  36. unCount++;
  37. bRet = Thread32Next(hSnapshort, &stcThreadInfo);
  38. }
  39. printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
  40. unCount = 0;
  41. printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
  42. CloseHandle(hSnapshort);
  43. system("pause");
  44. return 0;
  45. }

#include <stdio.h>
#include <windows.h>
#include <TlHelp32.h>

int main()
{
    // 为进程的所有线程拍个快照
    HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if( hSnapshort==INVALID_HANDLE_VALUE )
    {
        printf("CreateToolhelp32Snapshot调用失败!\n");
        return -1;
    }

    // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
    THREADENTRY32 stcThreadInfo;
    stcThreadInfo.dwSize = sizeof(stcThreadInfo);

    BOOL  bRet = Thread32First(hSnapshort, &stcThreadInfo);
    DWORD dwProId = -1;  // 保存上一个线程的进程ID
    unsigned unCount=0;

    while (bRet)
    {
        if( dwProId!=stcThreadInfo.th32OwnerProcessID )
        {

            // 记录PID与所属PID不同,遍历至不属于同一进程的线程
            if( dwProId!=-1 )
            {
                // 不是第一次遍历
                printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
                unCount = 0;
                printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
            }   

            dwProId = stcThreadInfo.th32OwnerProcessID;
            printf("进程%d:\n\n ", dwProId);
            printf("线程TID\t\t线程所属进程PID\t\t线程优先级\n");
        }

        printf("  %d\t\t\t%d\t\t\t %d\n",stcThreadInfo.th32ThreadID, stcThreadInfo.th32OwnerProcessID, stcThreadInfo.tpBasePri);
        unCount++;

        bRet = Thread32Next(hSnapshort, &stcThreadInfo);
    }

    printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
    unCount = 0;
    printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");

    CloseHandle(hSnapshort);

    system("pause");
    return 0;
}

在win程序设计中除了使用ToolHelp函数可以完成进程的遍历操作之外(程序需要包含tlhelp32.h),还可以使用Psapi函数EnumProcess函数,但是它只能获取进程的ID。

进程相关操作--终止进程

[cpp] view plain copy

print?

  1. void  WINAPI  ExitProcess(
  2. UINT  uExitCode;  // 进程退出码
  3. );

void  WINAPI  ExitProcess(
    UINT  uExitCode;  // 进程退出码
);

在程序的任意一个地方调用这个函数都会立即终止自身进程的运行。在C/C++中应避免直接调用这个函数,因为C/C++运行期库得不到通知,∴没有机会去调用全局或静态C/C++对象的析构函数。

ExitProcess不能终止其他进程,应使用TerminateProcess函数。

[cpp] view plain copy

print?

  1. BOOL WINAPI TerminateProcess(
  2. HANDLE hProcess,  // 要结束的进程句柄
  3. UINT uExitCode    // 指定目标进程的退出码
  4. );

BOOL WINAPI TerminateProcess(
    HANDLE hProcess,  // 要结束的进程句柄
    UINT uExitCode    // 指定目标进程的退出码
);

我们必须通过获取目标进程的ID,然后再获取这个进程句柄,然后才可以使用这个句柄操作此进程。可以使用如下函数:

[cpp] view plain copy

print?

  1. HANDLE WINAPI OpenProcess(
  2. DWORD dwDesiredAccess,  // 指定得到的句柄具有的访问权限
  3. BOOL  bInheritHandle,   // 指定返回的句柄是否可被继承
  4. DWORD dwProcessId       // 指定要打开的进程ID
  5. );

HANDLE WINAPI OpenProcess(
    DWORD dwDesiredAccess,  // 指定得到的句柄具有的访问权限
    BOOL  bInheritHandle,   // 指定返回的句柄是否可被继承
    DWORD dwProcessId       // 指定要打开的进程ID
);

这个函数打开一个存在的进程,返回具有指定权限的句柄。

获取进程的其他信息

  • 获取进程对应的可执行程序路径

[cpp] view plain copy

print?

  1. DWORD  WINAPI  GetProcessImageFileNameA (
  2. _In_ HANDLE hProcess,                       // 要获得文件路径的进程句柄
  3. _Out_writes_(nSize) LPSTR lpImageFileName,  // 保存文件路径的内存首地址
  4. _In_ DWORD nSize<span style="white-space:pre">              </span>// 保存文件路径的内存大小
  5. );

DWORD  WINAPI  GetProcessImageFileNameA (
    _In_ HANDLE hProcess,                       // 要获得文件路径的进程句柄
    _Out_writes_(nSize) LPSTR lpImageFileName,  // 保存文件路径的内存首地址
    _In_ DWORD nSize// 保存文件路径的内存大小
    );

注意使用上述函数获取的路径并不是磁盘驱动器的路径,而是内核路径,形如: " \Device\HarddiskVolume1\WINDOWS\System32\notepad.exe ",通常此路径中的Device表示硬盘驱动器,HarddiskVolume表示分区数字表示具体分区号(1表C 2表D。。。),所以对路径需要进行转换。

[cpp] view plain copy

print?

  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <tchar.h>
  4. #include <TlHelp32.h>
  5. #include <Psapi.h>
  6. #pragma comment(lib, "psapi.lib")
  7. void TransPath(PTCHAR pPath)
  8. {
  9. // 获取驱动器字符串位置
  10. PTCHAR pFind = _tcsstr(pPath, _T("HarddiskVolume"));
  11. if( pFind==NULL )
  12. return;
  13. TCHAR tcDriver[5] = {‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘};  // 可写满24个字符,这里只是一个demo
  14. int nNum = pFind[_tcslen(_T("HarddiskVolume"))] - 0x30;
  15. PTCHAR pTemp = _tcsstr(pFind, _T("\\"));
  16. // 拼接字符串的缓冲区
  17. TCHAR tcBuffer[MAX_PATH];
  18. memset(tcBuffer, 0, MAX_PATH*sizeof(TCHAR));
  19. _stprintf_s(tcBuffer, _T("%c:%s"), tcDriver[nNum-1], pTemp);
  20. memset(pPath, 0, _tcslen(pPath));
  21. _tcscpy_s(pPath, 256, tcBuffer);
  22. }
  23. int main()
  24. {
  25. // 传入\Device\HarddiskVolume1\WINDOWS\System32\notepad.exe
  26. DWORD dwNeed;
  27. PDWORD pdwMem = new DWORD[4000];
  28. BOOL bRet = EnumProcesses(pdwMem, 4000, &dwNeed);
  29. if( !bRet )
  30. {
  31. if(pdwMem!=NULL)
  32. {
  33. delete[] pdwMem;
  34. pdwMem = nullptr;
  35. return -1;
  36. }
  37. }
  38. int nNumProc = dwNeed/4;
  39. HANDLE hProcess = NULL;
  40. DWORD dwPathLength = 0;
  41. TCHAR tcBuffer[256] = {0};
  42. for( int i=0; i<nNumProc; i++ )
  43. {
  44. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pdwMem[i]);
  45. if( hProcess==NULL )
  46. continue;
  47. memset(tcBuffer, 0, 256*sizeof(TCHAR));
  48. dwPathLength = GetProcessImageFileName(hProcess, tcBuffer, 256);
  49. if( dwPathLength!=0 )
  50. {
  51. TransPath(tcBuffer);
  52. printf("%08d %ls\n",pdwMem[i], tcBuffer);
  53. }
  54. CloseHandle(hProcess);
  55. }
  56. if( pdwMem!=NULL )
  57. {
  58. delete[] pdwMem;
  59. pdwMem = NULL;
  60. }
  61. system("pause");
  62. return 0;
  63. }

#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <TlHelp32.h>
#include <Psapi.h>

#pragma comment(lib, "psapi.lib")

void TransPath(PTCHAR pPath)
{
    // 获取驱动器字符串位置
    PTCHAR pFind = _tcsstr(pPath, _T("HarddiskVolume"));
    if( pFind==NULL )
        return;

    TCHAR tcDriver[5] = {‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘};  // 可写满24个字符,这里只是一个demo

    int nNum = pFind[_tcslen(_T("HarddiskVolume"))] - 0x30;

    PTCHAR pTemp = _tcsstr(pFind, _T("\\"));

    // 拼接字符串的缓冲区
    TCHAR tcBuffer[MAX_PATH];
    memset(tcBuffer, 0, MAX_PATH*sizeof(TCHAR));

    _stprintf_s(tcBuffer, _T("%c:%s"), tcDriver[nNum-1], pTemp);
    memset(pPath, 0, _tcslen(pPath));
    _tcscpy_s(pPath, 256, tcBuffer);
}

int main()
{
    // 传入\Device\HarddiskVolume1\WINDOWS\System32\notepad.exe
    DWORD dwNeed;
    PDWORD pdwMem = new DWORD[4000];
    BOOL bRet = EnumProcesses(pdwMem, 4000, &dwNeed);

    if( !bRet )
    {
        if(pdwMem!=NULL)
        {
            delete[] pdwMem;
            pdwMem = nullptr;
            return -1;
        }
    }

    int nNumProc = dwNeed/4;
    HANDLE hProcess = NULL;
    DWORD dwPathLength = 0;
    TCHAR tcBuffer[256] = {0};

    for( int i=0; i<nNumProc; i++ )
    {
        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pdwMem[i]);

        if( hProcess==NULL )
            continue;

        memset(tcBuffer, 0, 256*sizeof(TCHAR));
        dwPathLength = GetProcessImageFileName(hProcess, tcBuffer, 256);

        if( dwPathLength!=0 )
        {
            TransPath(tcBuffer);
            printf("%08d %ls\n",pdwMem[i], tcBuffer);
        }

        CloseHandle(hProcess);
    }

    if( pdwMem!=NULL )
    {
        delete[] pdwMem;
        pdwMem = NULL;
    }

    system("pause");
    return 0;
}
  • 获取进程内模块信息

一个可执行程序要执行就必须运行起来形成一个进程,即把自身加载到内存,我们把这段内存称为该进程的主模块。but并不是程序的所有功能都位于主模块中,也有部分功能位于动态链接库中,程序运行后也会把辅助功能的DLL加载到内存形成其他的模块。摒弃一个进程中可以存在多个模块用于辅助主模块完成各种任务。有些病毒把自身代码以模块形式加载到正常进程中去然后偷偷执行。

使用ToolHelp系列函数获取进程模块和遍历进程模块

首先给某个进程的模块拍个快照,这样即可得到这个进程的模块列表,里面记录了每个模块的详细信息。然后使用Module32FirstModule32Next即可遍历快照列表中记录的模块信息。

使用Psapi函数操作

使用EnumProcessModules函数。这个函数只能得到每个模块的句柄,不能得到模块的名称和路径,所以需要使用GetModuleFileNameEx函数通过模块句柄去获得模块的路径。在枚举进程中的模块时,第一个模块是进程的主模块,用主模块句柄得到的模块路径就是进程文件的路径。

  • 获取进程命令行参数

命令行参数即进程启动时传递给它的参数,通过这个参数可知道金城个启动情况。例如系统服务中,凡是服务对应模块是DLL文件情况,都需要svchost.exe去加载启动,这样系统中就有很多svchost进程,每个svchost进程对应一类服务,这时就是通过命令行参数来区分他们。获取本进程命令行参数API:

[cpp] view plain copy

print?


[cpp] view plain copy

print?

  1. // 返回命令行参数字符串的首地址
  2. LPTSTR  GetCommandLine(VOID);

// 返回命令行参数字符串的首地址
LPTSTR  GetCommandLine(VOID);

获取指定进程的命令行参数,可以使用OD随意调试一个Win程序,如notepad.exe。在command窗口输入follow GetCommandLineA命令即可定位到该函数的实现代码。可以看到实现代码仅一行

[cpp] view plain copy

print?

  1. mov  ax, dword ptr [7C8835F4]
  2. // 个人做测试的时候地址好像是7C8855F4

mov  ax, dword ptr [7C8835F4]
// 个人做测试的时候地址好像是7C8855F4

也就是说进程的命令行参数被保存在内存中的固定位置,只要定位到GetCommandLineA的入口地址,跳过一个字节后取出一个dword值,这个值是一个指针,指向的内容即命令行参数的地址。现在的问题即得到远程进程中GetCommandLineA函数的入口地址即可得到该进程的命令行参数。获取指定模块中某个Win32API函数地址的函数是GetProcAddress。but这个函数仅可获取当前进程中API函数的地址,要获得远程进程中某个函数的地址就必须在远程进程中执行这个函数,需要使用远线程方法,本文暂时不涉及这个内容。换个思路:GetCommandLineA使用Kernel32.dll提供,这个库是系统基本库,几乎所有程序都会加载这个模块。而且对于NT架构所有进程加载Kernel32.dll的模块基址基本都是一致的,而GetCommandLineA在其库中的地址也是固定的。所以我们在本进程中得到的此函数地址和远程进程中该函数的地址是一致的(这个方法在我的电脑Win7x64中实验失败,应该因为程序的加载基址不固定了)。获取远程进程中数据使用ReadProcessMemory函数。

[cpp] view plain copy

print?

  1. BOOL  WINAPI  ReadProcessMemory(
  2. _In_ HANDLE hProcess, <span style="white-space:pre">                    </span>         // 远程进程句柄
  3. _In_ LPCVOID lpBaseAddress,<span style="white-space:pre">                       </span> // 目标进程内存空间首地址
  4. _Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer,  // 本进程内存空间首地址,存储读出的数据
  5. _In_ SIZE_T nSize,<span style="white-space:pre">                            </span> // 要读取的字节数
  6. _Out_opt_ SIZE_T * lpNumberOfBytesRead<span style="white-space:pre">                </span> // 实际读取的字节数
  7. );

BOOL  WINAPI  ReadProcessMemory(
    _In_ HANDLE hProcess,          // 远程进程句柄
    _In_ LPCVOID lpBaseAddress, // 目标进程内存空间首地址
    _Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer,  // 本进程内存空间首地址,存储读出的数据
    _In_ SIZE_T nSize, // 要读取的字节数
    _Out_opt_ SIZE_T * lpNumberOfBytesRead // 实际读取的字节数
    );

为保证此方法成功,应判断当前系统是否是NT系统,使用GetVersion函数获取当前系统的版本。返回值表示系统的版本信息,若是NT/2k/xp则返回值小于0x80000000,否则大于该值。虚拟机中XP实验成功。

jpg改rar 

时间: 2024-10-26 10:47:48

获取系统中所有进程&线程信息的相关文章

Linux系统中查看进程和计划任务管理

? 各位小伙伴们大家好,本次给大家带来的是Linux操作系统中的进程和计划任务的管理,首先大家都知道程序是保存在外部存储介质(如硬盘.光盘)中的可执行机器代码和数据的静态集合,而进程是在CPU及内存中处于动态执行状态的计算机程序,在Linux系统中,每个程序启动后可以创建一个或多个进程.例如:提供Web服务的httpd程序当有大量用户同时访问Web页面时,httpd程序可能会创建多个进程来提供服务.那么接下来我将会从以下几点来告诉大家在Linux的CentOS 7系统中是如何查看进程信息和控制进

Linux 系统中僵尸进程

Linux 系统中僵尸进程 Linux 系统中僵尸进程和现实中僵尸(虽然我也没见过)类似,虽然已经死了,但是由于没人给它们收尸,还能四处走动.僵尸进程指的是那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸. 僵尸进程如何产生的? 如果一个进程在其终止的时候,自己就回收所有分配给它的资源,系统就不会产生所谓的僵尸进程了.那么我们说一个进程终止之后,还保留哪些信息?为什么终止之后还需要保留这些信息呢? 一个进程终止的方法很多,进程终止后有些信息对于父进程和内核还是很有用的,例如进程的

获取系统中已经安装的文字输入法

//获取系统中已经安装的文字输入法 InputLanguageCollection MyInputs = InputLanguage.InstalledInputLanguages; //获取当前输入法信息 InputLanguage CurrentInput = InputLanguage.CurrentInputLanguage; string language = CurrentInput.LayoutName; IntPtr pt = new IntPtr(134481924); for

Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免?

如题 Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免? 一个进程在调用exit命令结束自己的生命的时候,其实他并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,他的作用是使进程退出,但是也仅仅限于一个正常的进程变成了一个僵尸进程,并不能完全将其销毁).在linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态信息供其他进程收集

Oracle EBS-SQL (SYS-13):查询DBA在系统中的打补丁信息.SQL

查询DBA在系统中的打补丁信息 1. select * from ad_patch_drivers          /*查看已经打了哪些Patch*/ 2. select * from ad_patch_runs             /*查看打patch的时间,目录等信息*/ 3. select * from ad_patch_driver_langs /*查看patch的语言*/ 4. 查询补丁名称.语言.打Patch的开始时间.打Patch的完成时间: SELECT driver.dr

获取系统特殊文件夹路径信息

//获取系统特殊文件夹路径信息 try {   this.textBox1.Text=Environment.GetFolderPath(System.Environment.SpecialFolder.System);   this.textBox2.Text=Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles);   this.textBox3.Text=Environment.GetFolderPa

PhotoShop 脚本学习04 获取系统中字体清单

app.fonts可获取系统中字体清单 var fs = app.fonts; var message=""; //获取系统字体集清单,太多可能显示不下 for(var i=0;i<fs.length;i++) { message +=(i+1)+"-"+fs[i].name+"\t"; } alert(message); 原文地址:https://www.cnblogs.com/52vsto/p/12255652.html

Linux系统中如何查看日志信息

日志文件是用于记录Linux系统中各种运行消息的文件,不同的日志文件记载了不同类型的信息,对于诊断和解决系统中的问题很有帮助 分析日志文件 日志数据主要包括三种类型:内核及系统日志.用户日志.程序日志 #对于大多数的文本格式的日志文件,使用tail.more.less.cat 等命令就可查看日志内容 #对于一些二进制格式的日志文件(如用户日志文件),使用who.w.users.last.lastb等 内核及系统日志的配置文件为 /etc/rsyslog.conf,通过查看文件内容,可以了解到系统

如何快速地获取Teamcenter中的的产品信息

实现Teamcenter和其他系统集成的第一步就是获取Teamcenter中的数据. 一般情况可以通过ITK编程或者调用Teamcenter的web service. ITK 是teamcenter的API编程接口的缩写( Integration Tool Kit). Teamcenter提供全面丰富的ITK接口,可以适用于各种需要,但是编程复杂,开发周期长. Web service是一种比较方便的方法,但是teamcenter提供的web service有限,如需要实现更为复制的功能,需要自己