Làm thế nào để có được pid process riêng từ dấu nhắc lệnh trong windows


26

Tôi đang cố gắng tìm cách để có được PID của riêng mình từ một dấu nhắc lệnh (để sử dụng sau này trong tập lệnh bat) cho đến nay cách hữu ích duy nhất tôi tìm thấy là sử dụng getpids.exe từ đây: http://www.scheibli.com/ dự án / getpids / index.html nhưng tôi đang tìm kiếm một lệnh "tích hợp" cho windows

chỉnh sửa: tôi đang tìm kiếm một cách "chống đạn" - không có giả định nào về quy trình của tôi là cmd.exe duy nhất hoặc bất cứ điều gì

Câu trả lời:


36

Vì không có giải pháp nào khác có khả năng chống đạn và tích hợp sẵn, tôi cho rằng tôi sẽ cung cấp giải pháp sau đây, nhưng lưu ý rằng bạn sẽ cần phân tích / lưu kết quả bằng cách nào đó:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"

đó là thực sự gọn gàng. Tôi khá chắc chắn thời gian hiện tại + một số số được tạo ngẫu nhiên có thể được đặt làm tiêu đề để đến gần chống đạn
radai

3
Không sử dụng% ngẫu nhiên% +% time% nếu bạn có một trình lập lịch gọi tập lệnh bó của bạn hai lần cùng một lúc. Tôi gặp vấn đề là cùng một kịch bản được gọi với các tham số khác nhau cùng một lúc. Hạt giống ngẫu nhiên là như nhau và tôi đã va chạm khi tạo một thư mục tạm thời. Không có cách nào để xử lý lỗi khi tạo thư mục tạm thời. Câu chuyện dài, nếu bạn có thể cho rằng kịch bản của mình không bị sa thải hai lần cùng một lúc, thủ thuật này sẽ hoạt động.
Peter Schuetze

Có thể (không được kiểm tra sâu) rằng nhận được dấu thời gian chính xác hơn (bao gồm microseconds, thay vì 1/100 giây như trong% time%), sẽ đáng tin cậy hơn trong trường hợp này: wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Timezone). Trừ khi người lập lịch có thể chạy hai thứ trong cùng một phần triệu giây ...
Gauthier Boaglio

Điều này sẽ không hoạt động nếu quá trình đang chạy trong một phiên khác trên máy tính vì tiêu đề được hiển thị là N / A
FrinkTheBrave

Điều này cung cấp cho PID của quá trình cha.
access_granted

7

Tôi tin rằng những điều sau đây là chống đạn, miễn là người dùng có quyền truy cập vào các điểm WMIC và TEMP đến một đường dẫn hợp lệ nơi người dùng có đặc quyền ghi. Đây là kết quả cuối cùng của một số công việc hợp tác tại http://www.dostips.com/forum/viewtopic.php?f=3&t=6133 .

@echo off

:getPID  [RtnVar]
::
:: Store the Process ID (PID) of the currently running script in environment variable RtnVar.
:: If called without any argument, then simply write the PID to stdout.
::
setlocal disableDelayedExpansion
:getLock
set "lock=%temp%\%~nx0.%time::=.%.lock"
set "uid=%lock:\=:b%"
set "uid=%uid:,=:c%"
set "uid=%uid:'=:q%"
set "uid=%uid:_=:u%"
setlocal enableDelayedExpansion
set "uid=!uid:%%=:p!"
endlocal & set "uid=%uid%"
2>nul ( 9>"%lock%" (
  for /f "skip=1" %%A in (
    'wmic process where "name='cmd.exe' and CommandLine like '%%<%uid%>%%'" get ParentProcessID'
  ) do for %%B in (%%A) do set "PID=%%B"
  (call )
))||goto :getLock
del "%lock%" 2>nul
endlocal & if "%~1" equ "" (echo(%PID%) else set "%~1=%PID%"
exit /b

Kịch bản thiết lập một khóa độc quyền trên một tệp tạm thời kết hợp thời gian hiện tại vào tên. Chỉ có thể có xung đột nếu hai quá trình giống như được đặt tên cố gắng để có được PID trong cùng khoảng thời gian 0,01 giây, trong trường hợp đó chỉ có một quá trình sẽ thành công.

Bất kỳ quá trình nào không thành công sẽ lặp lại nhiều lần và thử lại với đường dẫn tệp khóa mới cho đến khi thành công.

Đường dẫn đầy đủ đến tệp khóa được chuyển thành ID duy nhất có thể được sử dụng trong truy vấn WMIC. WMIC được chạy trong lệnh FOR / F, có nghĩa là nó đang chạy trong tiến trình cmd.exe con. Đó là lý do tại sao ParentProcessID của quá trình cmd.exe được truy xuất.


7

Mở rộng theo câu trả lời của Tony Roth:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do echo %f

Sử dụng bộ lọc WINDOWTITLE để tránh đường ống để bạn có thể đặt nó vào một vòng lặp for và gán nó cho một biến với SET nếu bạn muốn:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do set ourPID=%f

Loại bỏ /vlàm cho nó nhanh hơn và /NHthoát khỏi dòng tiêu đề. Bạn cần ký tự đại diện sau "uniqueTitle"vì tiêu đề cửa sổ thực sự chứa lệnh hiện tại (do đó nó sẽ tiếp tục và tiếp tục nếu bạn cố gắng khớp hoàn toàn với nó).


6

Sử dụng PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId

Tốt đẹp; nếu bạn có PowerShell Core , việc này thậm chí còn dễ dàng hơn (mặc dù không lệnh nào sẽ nhanh ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mkuity

5
  1. Trình quản lý tác vụ Windows, bạn sẽ cần vào Xem -> Chọn Cột .. và chọn PID.
  2. "tasklist / v" để nhận thông tin tác vụ dài dòng trong dấu nhắc lệnh.
  3. Process Explorer từ live.sysiternals.com .

2
@Vivek, từ một dấu nhắc lệnh ... và bạn đang trả lời các câu trả lời
WooYek

tôi chỉ đưa ra tất cả các tùy chọn có thể .. và không trùng lặp .. tôi cũng có thể đã đề cập đến PowerShell nhưng tôi đã tự kiềm chế vì điều đó không có trong mặc định trong XP và 2003. Nếu đây là cho Vista trở đi HĐH, Yes PowerShell sẽ là sở thích của tôi .
Vivek Kumbhar

5

nếu bạn biết chỉ có một cmd.exe đang chạy, bạn có thể nhận được PID theo cách này:

for /F "tokens=1,2" %%i in ('tasklist /FI "IMAGENAME eq cmd.exe" /fo table /nh') do set pid=%%j

echo %pid%

Nghe có vẻ như là một giả định không thể thực hiện được, mã của bạn có thể không ổn định
Raúl Salinas-Monteagudo

Raul, tôi hiểu những gì bạn đang nói. Nó không an toàn trong nhiều trường hợp, nhưng an toàn trong một số trường hợp - chẳng hạn như hệ thống kiosk hoặc VM nơi bạn có toàn quyền kiểm soát những quy trình đang bắt đầu và không
zumalifeguard

4

Cái này cần phải dùng mẹo:

nhiệm vụ / v


3

Nếu bạn muốn tìm PID của tên hình ảnh "notepad.exe", thì đoạn mã sau sẽ hoạt động cho bạn:

for /F "tokens=1,2" %i in ('tasklist') do (
 if "%i" equ "notepad.exe" (set x=%j)
)
echo %x%

2

Nếu bạn đã có bộ tài nguyên Windows 2003, hãy đẩy nó qua qgrep để có được dòng bạn muốn. Sau đó, bạn có thể trích xuất pid từ đây (điều này giả sử bạn chỉ có một cmd chạy mỗi lần),

tasklist /v | qgrep cmd

cmd.exe 2040 RDP-Tcp#447 0 1,804 K Running MACHINE\Administrator  0:00:00 Command Prompt

1

Hãy xem thủ thuật lô nhỏ này . Nó đặt tiêu đề của cmd thành một giá trị đặc biệt sau đó sử dụng danh sách tác vụ để tìm nó. Sáng tạo

\ Greg


0

ĐÂY LÀ CÁCH NGẮN HẠN ĐỂ NHẬN ID QUY TRÌNH CHO MỞ CMD

tasklist /v /fi "imagename EQ cmd.exe" /FO LIST | FIND "PID:"

0

Câu trả lời này sẽ cung cấp cho bạn CHỈ ID quy trình và không có nội dung bổ sung nào mà câu trả lời hàng đầu bao gồm.

title mycmd
tasklist /v /fo csv | findstr /i "mycmd" > PIDinfo.txt

set /p PIDinfo=<PIDinfo.txt
set PID1=%PIDinfo:~11,5%
set PID2=%PIDinfo:~11,4%

if %PID2% gtr 8100 (
    set PID=%PID2%
) else (
    set PID=%PID1%
)

echo %PID%

Giải trình:

-có thể sẽ không phải là một PID cho cmd.exe lớn hơn 18100, vì vậy hãy kiểm tra xem PID2 có lớn hơn 8100 không để chúng tôi biết đó là số có 4 chữ số hay 5 chữ số

trường hợp 1: một PID gồm 5 chữ số như 17504 có giá trị PID1 là 17504 và giá trị PID2 là 1750, vì vậy chúng tôi sử dụng PID1

trường hợp 2: một PID gồm 4 chữ số như 8205 có giá trị PID1 là 8205 "và giá trị PID2 là 8205, vì vậy chúng tôi sử dụng PID2

trường hợp 3: một PID gồm 4 chữ số như 4352 có giá trị PID1 là 4352 "và giá trị PID2 là 4352, vì vậy chúng tôi sử dụng PID2

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.