קליטת תו מהקונסול - #C
-
@dovid כתב בקליטת תו מהקונסול - #C:
להבנתי אי אפשר מהקונסול הרגיל
גם אני חשבתי כמוך אבל למרבה הפלא מתברר שזה לא נכון
חשבתי שאי אפשר כי תהליך הקונסול והתהליך של האפליקציה שלך הם שני תהליכים נפרדים, ואחרי שפלטת טקסט החוצה, הטקסט הזה קיים רק בזיכרון של תהליך הטרמינל לצורך הצגה אבל זה כבר יצא מהזכרון של התהליך שלך
הטענה צודקת לגבי לינוקס, שם באמת הטרמינל היא תוכנה נפרדת לגמרי ואין לתוכנה שלך שום גישה לטקסט שהטרמינל מציג, הגישה היחידה שיש לתוכנה היא לצינור שאפשר לפלוט אליו טקסט ולקבל קלט ממנו.
אבל בווינדוס יש גישה שונה מאוד לטרמינל, הקונסול הוא חלק מהאפליקציה שלך (לכן הרצה של פקודת שורת הפקודה פותחת קונסול, ובלינוקס זה רץ בשקט ברקע), ולכן יש לך גישה מלאה למה שהטרמינל מציג (יש שכבת בידוד בין האפליקציה לקונסול והתוכן של הקונסול מוארח בתהליך נפרד אבל זה לא אמור לעניין את המתכנת)
ב-#C (דוטנט) אין פוקנציה לקרוא את ה-buffer של הטרמינל, אבל יש פונקציה נייטיבית לזה, כתבתי קוד פייתון שמדגים את זה
שים לב שאפשר ככה לגנוב פלט מפקודות קודמות
זה היה פלא בעיני שיש חור אבטחה/פרטיות כזה בווינדוס, אבל שוב התבוננתי שהתוקף הנחוש יכול לקבל את התוכן של הקונסול בכמה דרכים אחרות ואז נחה דעתיfrom win32console import PyConsoleScreenBufferType, PyCOORDType, GetStdHandle, STD_OUTPUT_HANDLE buffer = PyConsoleScreenBufferType(GetStdHandle(STD_OUTPUT_HANDLE)) info = buffer.GetConsoleScreenBufferInfo() print("=" * info["Size"].X) print("YOUR CONSOLE HISTORY") print("=" * info["Size"].X) print(buffer.ReadConsoleOutputCharacter(info["Size"].X * info["CursorPosition"].Y, PyCOORDType(0,0))) print("=" * info["Size"].X)
אפשר להשתמש בפונקציות אלו של ווינדוס גם בדוטנט ע"י P/Invoke
-
@yossiz היה ברור לי שיש דרך בעולם (אולי לא מחכמה אל מהעדרה או מאינטואיציה וניסיון, כי לא ידעתי כל מה שכתבת), כמו עם WM_GETTEX של הנגישות (למרות שכנראה דוקא עם זה אי אפשר).
למרות זאת כתבתי שזה לא אפשרי בהתחשב בהקשר, ולכן אני עדיין סבור שזה התשובה המדוייקת בעיני. -
@dovid זה לא דומה כלל ל-WM_GETTEXT או ל-API של הנגישות, מדובר על אותו buffer שאתה כותב לו כדי להציג דברים בקונסול, יש פונקציה לשלוף מאותו buffer עצמו. זה כמעט דרך המלך. אלא שיותר נכון לבנות את המשחק בצורה שאתה שומר state בתוך הקוד שלך ומרנדר לקונסול לפי הצורך מה-state שלך ולא לסמוך על הטקסט של הקונסול לשמור בשבילך state
(יש הסתייגות נוספת, שמייקרוסופט רוצים שתשתמש ב-API החדש של הטרמינל שבנוי כמו בלינוקס שאין לך גישה ל-buffer ולא להשתמש ב-API הישנים, אבל הם בעצמם אומרים שהם ממשיכים לתמוך בזה בצורה מלאה) -
@dovid כתב בקליטת תו מהקונסול - #C:
בכל מקרה השאלה פה צועקת את XY Problem.
אני מאמין שבשביל להגיע להבנה טובה של חומר, אחרי שניסית והצלחת לעבוד עם הדרכים המקובלות, תנסה את הדרכים הפחות מקובלות והיותר ביזאריות, באופן זה אתה "נוגע" בגבולות הגזרה של המערכת ומגיע למידע שלא תגיע בדרכים רגילות.
אבל אולי זה רק אני... -
@dovid כתב בקליטת תו מהקונסול - #C:
@yyy לא הבנתי מה שכתבת,
אני רק התכוונתי שבעוד שלהבנתך לא רלוונטי לכתוב למה אתה צריך את זה (קריאה מטקסט בקונסול),
אני בטוח כמעט במאת האחוזים שאם היית מספר למה אתה צריך את זה היו תשובות פשוטות בהרבה.אני פשוט טוען שנושא ה-X שלי הוא רצון להכיר טוב יותר את המערכת, ולכן הבעיה שהצגתי היא ה-X עצמו ולא Y.
-
@yyy אני מסכים לך שחקירת נושאים כאלו מרחיבים את הידע
בשאלות מסוג זה המידע עצמה של התשובה עונה לך על השאלה אבל זה משהו ש-99% מהמתכנתים לא יודעים ולא צריכים לדעת (בגלל הטענה של דוד שיש צורה אחרת לפתור את הבעיה), ויש מליון וחצי כאלו פיסות מידע ששימושיים חד פעמי למקרים ספציפיים
הכישור למצוא תשובה לשאלה כזאת הוא יותר חשוב, כדי שמתי שבאמת אתה צריך תשובה תוכל להגיע לזה בכוחות עצמך
וגם בחקירת נושא כזה אפשר ללקט על הדרך ידע כללי בנושא
נהניתי מהשאלה והחיפוש לתשובה זה נושא שמעניין אותי אז תודה על העלאת השאלה
תהליך ההגעה לתשובה שלי היה כנראה על ידי חיפוש גוגל (אני לא מוצא כעת את החיפוש המדוייק בהיסטורית הדפדפן) שזה הביא אותי לתשובה ב-stackoverflow שהוביל אותי לתיעוד המקורי של מייקרוסופט על נושא הקונסול, קריאה של כמה עמודי תיעוד (והכירות קודמת בנושאים שמסביב לתוכנות של שורות הפקודה) עזרו אותי בתשובת השאלהמי שמכיר בעיקר את לינוקס היה צריך לחשוב מיד שזה בטח בלתי אפשרי וכך אני חשבתי אבל אז אמרתי לעצמי שלפני שאני עונה שזה בלתי אפשרי בוא נבדוק בגוגל אולי אני טועה
-
@yossiz
אכן מה שהביא אותי להרהר בדבר הוא תחום מערכות ההפעלה, בו למיטב זכרוני למדתי שתחום התצוגה מתוחזק בדר"כ ע"י מערכת ההפעלה ולא ע"י האפלקציה.לסיכום התשובות ע"פ הקישור שהביא @Aharon-0
יש 2 שיטות:האחת הסטנדרטית יותר היא יצירת מחלקה (בדומה אולי ל -pipe בלינוקס) שפשוט משמשת "איש באמצע" ומתעדת את כל הפניות לקונסול. (גישה זו פחות "מעניינת" בעיני כי היא בדיוק כמו יצירת מטריצת משתנים המייצגים לוח.)
השניה היא גישה ל-Buffer (דרך די מורכבת אם רוצים להתחיל מ-0)
כך או כך אין דרך מובנית לעשות זאת.